;; --------------------------------------------------------------------------- ;; Ping Pong ;; To play: ;; set library to pingp-lib.ss ;; uncomment the last line ;; click execute ;; To change wind/speed of delivery: ;; see Web instructions (from 210 page) ;; Positions: (define-struct posn (x y)) is pre-defined. ;; A posn is (make-posn n m) where n and m are numbers. ;; See HtDP for restrictions on the numbers. ;; Also: recall that y grows the further South a posn ;; apears on the screen. ;; Speed and its relationship to positions ;; --------------------------------------- (define-struct speed (x y)) ;; A speed is (make-speed n m) ;; where n and m are numbers but not 0. ;; posn+ : posn vec -> vec ;; add the respective components (define (posn+ p v) (make-posn (+ (posn-x p) (speed-x v)) (+ (posn-y p) (speed-y v)))) ;; posn*s : number vec -> posn ;; multiply each component of p by f (define (posn*s f p) (make-speed (* f (speed-x p)) (* f (speed-y p)))) ;; vec* : vec vec -> vec ;; multiply the respective components (define (vec* v1 v2) (make-speed (* (speed-x v1) (speed-x v2)) (* (speed-y v1) (speed-y v2)))) ;; The ball representation and some basic primitives: ;; --------------------------------------------------- (define-struct ball (posn speed)) ;; A ball is (make-ball P S) ;; where P is a posn and S is a speed. ;; ns-direction : ball -> {'NORTH, 'SOUTH} ;; compute the N/S direction of a ball (define (ns-direction ball) (cond ((< (speed-y (ball-speed ball)) 0) 'NORTH) ((> (speed-y (ball-speed ball)) 0) 'SOUTH) (else (error 'make-direction "can't happen")))) ;; ew-direction : ball -> {'EAST, 'WEST} ;; compute the E/W direction of a ball (define (ew-direction ball) (cond ((< (speed-x (ball-speed ball)) 0) 'WEST) ((> (speed-x (ball-speed ball)) 0) 'EAST) (else (error 'make-direction "can't happen")))) ;; ns-distance-to-wall : ball -> number ;; compute the distance to the N/S wall in the direction of flight (define (ns-distance-to-wall ball) (if (eq? (ns-direction ball) 'NORTH) (- (posn-y (ball-posn ball)) NORTH) (- SOUTH (posn-y (ball-posn ball))))) ;; ew-distance-to-wall : ball -> number ;; compute the distance to the N/S wall in the direction of flight (define (ew-distance-to-wall ball) (if (eq? (ew-direction ball) 'WEST) (- (posn-x (ball-posn ball)) WEST) (- EAST (posn-x (ball-posn ball))))) ;; ns-time-to-wall : ball -> number ;; compute the time that the ball needs to travel in the ;; N/S direction before it hits the wall (define (ns-time-to-wall ball) (/ (ns-distance-to-wall ball) (abs (speed-y (ball-speed ball))))) ;; ew-time-to-wall : ball -> number (time before ew wall is hit) ;; compute the time that the ball needs to travel in the ;; E/W direction before it hits the wall (define (ew-time-to-wall ball) (/ (ew-distance-to-wall ball) (abs (speed-x (ball-speed ball))))) ;; Moving a Ball ;; ------------- ;; move-in-box : ball number -> ball ;; make a ball that represents a move of a-ball for t time units ;; the ball may bounce from any of the four walls (define (move-in-box a-ball t) (case (bounces-from a-ball t) ((NORTH SOUTH) (bouncing-move ns-bounce (ns-time-to-wall a-ball) t a-ball)) ((EAST WEST) (bouncing-move ew-bounce (ew-time-to-wall a-ball) t a-ball)) (else (move-ball a-ball t)))) ;; move-ball : ball number -> ball ;; make a ball that represents a straight-line move of a-ball for t time units (define (move-ball ball t) (make-ball (posn+ (ball-posn ball) (posn*s t (ball-speed ball))) (ball-speed ball))) ;; bouncing-move : (ball -> ball) num num ball -> ball ;; make a ball that represents a bouncing move of a-ball for t time units ;; the bounce is computed by bounce, which is a function (define (bouncing-move bounce t-bounce t ball) (move-in-box (bounce (move-ball ball t-bounce)) (- t t-bounce))) ;; bounces-from : ball number -> {'NORTH, 'SOUTH, 'EAST, 'WEST, 'none} ;; compute from which wall (or from which paddle) the ball will bounce (define (bounces-from ball t) (cond ((<= (ns-time-to-wall ball) (min t (ew-time-to-wall ball))) (ns-direction ball)) ((<= (ew-time-to-wall ball) (min t (ns-time-to-wall ball))) (cond ((landed-on-paddle? (ball-posn (move-ball ball (ew-time-to-wall ball)))) (ew-direction ball)) (else 'none))) (else 'none))) ;; ns-bounce : ball -> ball ;; make a ball that represents the bouncing moment of a-ball at a N/S wall (define (ns-bounce ball) (make-ball (ball-posn ball) (vec* (ball-speed ball) (make-speed 1 -1)))) ;; ew-bounce-west : ball -> ball ;; make a ball that represents the bouncing moment of a-ball at a E/W wall (define (ew-bounce ball) (make-ball (ball-posn ball) (vec* (ball-speed ball) (make-speed -1 1)))) ; (play make-ball make-speed ball-posn move-in-box)