;; **************************************** ;; * Csu 211 : 3/10/2008 ;; * Lecture #22 Code ;; * Bouncing and the Ping Game ;; **************************************** ;; Size of the Ball and Pings (define radius 20) ;; The World is: (make-world Posn Posn (listof Posn) Number) (define-struct world (ball dir lop speed)) ;; check: World-> World ;; Check for a Bounce (define (check w) (local ((define hi (hit (world-lop w) (world-ball w) 0))) (make-world (world-ball w) (cond [(>= hi 0) (dir (world-ball w) (list-ref (world-lop w) hi))] [else (world-dir w)]) (world-lop w) (world-speed w)))) ;; hit: (listof Posn) Posn Number -> Number ;; Return the index of the first Ping Hit by the ball (define (hit lop b n) (cond [(empty? lop) -1] [(<= (dist (first lop) b) (* 2 radius)) n] [else (hit (rest lop) b (+ n 1))])) ;; len: Number Number -> Number ;; Compute the length of the vector (dx,dy) (define (len dx dy) (sqrt (+ (sqr dx) (sqr dy)))) ;; dir: Posn Posn -> Posn ;; The direction of a bounce between Ball and a Ping (define (dir p1 p2) (local ((define dx (- (posn-x p1) (posn-x p2))) (define dy (- (posn-y p1) (posn-y p2))) (define l (len dx dy))) (make-posn (/ dx l) (/ dy l)))) ;; dist: Posn Posn -> Number ;; The distance between two Posns (define (dist p1 p2) (len (- (posn-x p1) (posn-x p2)) (- (posn-y p1) (posn-y p2)))) ;; move-posn: Posn Posn Number -> Posn ;; Move the given Posn in the given direction () (define (move-posn p d s) (make-posn (+ (posn-x p) (* (posn-x d) s)) (+ (posn-y p) (* (posn-y d) s)))) ;; move: World-> World ;; Move the Ball based on (define (move w) (make-world (move-posn (world-ball w) (world-dir w) (world-speed w)) (world-dir w) (world-lop w) (world-speed w))) ;; mouse: World Number Number Symbol -> World ;; Create a new Ping when the mouse is pressed (define (mouse w x y sym) (cond [(symbol=? sym 'button-down) (make-world (world-ball w) (world-dir w) (cons (make-posn x y) (world-lop w)) (world-speed w))] [else w])) ;; draw-lop: (listof Posn) -> Scene ;; Draw a List of Pings.... (define (draw-lop lop) (local ((define (draw-one p scn) (place-image (circle radius 'outline 'black) (posn-x p) (posn-y p) scn))) (foldl draw-one (empty-scene 400 400) lop))) ;; key: World Symbol-Or-Char -> World ;; In/De-crease the Speed on up/down key press (define (key w s/ch) (cond [(char? s/ch) w] [else (make-world (world-ball w) (world-dir w) (world-lop w) (cond [(symbol=? s/ch 'up) (+ (world-speed w) .5)] [(symbol=? s/ch 'down) (- (world-speed w) .5)] [else (world-speed w)]))])) ;; draw: World -> Scene ;; Draw the representation of the World (define (draw w) (place-image (circle radius 'solid 'red) (posn-x (world-ball w)) (posn-y (world-ball w)) (draw-lop (world-lop w)))) ;; tick: World -> World (define (tick w) (check (move w))) (big-bang 400 400 .08 (make-world (make-posn 200 200) (make-posn 1 0) '() 5)) (on-key-event key) (on-mouse-event mouse) (on-redraw draw) (on-tick-event tick)