;; Problem A2 ;; Key presses are translated into a rocket based on the ;; ascii code of the key pressed. (define-struct particle (loc vel color)) ;; A Particle = (make-particle Posn Posn Color) (define-struct explosion (loc vel r color)) ;; An Explosion = (make-explosion Posn Number Number Color) (define-struct rocket (loc vel color)) ;; A Rocket = (make-rocket Posn Number Color) ;; A Fireworks = Particle | Explosion | Rocket ;; A World = [Listof Fireworks] ;; lookup tables for sin and cos so they need not be ;; recalculated every explosion (define sin-list (build-list 12 (lambda(n) (sin (* n pi 1/6))))) (define cos-list (build-list 12 (lambda(n) (cos (* n pi 1/6))))) ;; color-equal? Color Color -> Boolean ;; determines if the two colors are the same (define (color-equal? x y) (and (= (color-red x) (color-red y)) (= (color-green x) (color-green y)) (= (color-blue x) (color-blue y)))) ;; color-fade: Color Number -> Color ;; fades the color by x amount (define (color-fade c x) (make-color (max 0 (- (color-red c) x)) (max 0 (- (color-green c) x)) (max 0 (- (color-blue c) x)))) ;; move-particle: Particle -> Particle ;; moves given particle and recalculates its velocity vector (define (move-particle p) (make-particle (make-posn (+ (posn-x (particle-loc p)) (posn-x (particle-vel p))) (- (posn-y (particle-loc p)) (posn-y (particle-vel p)))) (make-posn (posn-x (particle-vel p)) (- (posn-y (particle-vel p)) 1/5)) (color-fade (particle-color p) 16))) ;; draw-particle: Particle Scene -> Scene ;; draws particle in the scene (define (draw-particle p sc) (place-image (circle 3 'solid (particle-color p)) (floor (posn-x (particle-loc p))) (floor (posn-y (particle-loc p))) sc)) ;; grow-explosion: Explosion -> Explosion ;; makes the explosion larger (define (grow-explosion e) (make-explosion (make-posn (posn-x (explosion-loc e)) (- (posn-y (explosion-loc e)) (explosion-vel e))) (- (explosion-vel e) 1/5) (+ (explosion-r e) 4) (color-fade (explosion-color e) 16))) ;; draw-explosion: Explosion Scene -> Scene ;; draws explosion in the scene (define (draw-explosion e sc) (place-image (star 12 2 (explosion-r e) 'solid (explosion-color e)) (floor (posn-x (explosion-loc e))) (floor (posn-y (explosion-loc e))) sc)) ;; move-rocket: Particle -> Particle ;; moves given rocket and recalculates its velocity vector (define (move-rocket r) (make-rocket (make-posn (posn-x (rocket-loc r)) (- (posn-y (rocket-loc r)) (rocket-vel r))) (- (rocket-vel r) 1/5) (rocket-color r))) ;; draw-rocket: Rocket Scene -> Scene ;; draws rocket in the scene (define (draw-rocket r sc) (place-image (circle 8 'solid (rocket-color r)) (floor (posn-x (rocket-loc r))) (floor (posn-y (rocket-loc r))) sc)) ;; rocket-explode: Rocket -> [Listof Particle] ;; creates an explosion where the rocket was (define (rocket-explode r) (local ((define (fire n) (make-particle (rocket-loc r) (make-posn (* 4 (list-ref cos-list n)) (* 4 (list-ref sin-list n))) (rocket-color r)))) (cons (make-explosion (rocket-loc r) 0 3 (rocket-color r)) (build-list 12 fire)))) ;; next-world: World -> World ;; updates the world (define (next-world w) (local ((define (update x y) (cond [(particle? x) (if (color-equal? (particle-color x) (make-color 0 0 0)) y (cons (move-particle x) y))] [(explosion? x) (if (color-equal? (explosion-color x) (make-color 0 0 0)) y (cons (grow-explosion x) y))] [(rocket? x) (if (< (rocket-vel x) 8) (append (rocket-explode x) y) (cons (move-rocket x) y))])) (define new-world (foldl update empty w))) (if (empty? new-world) (end-of-time 'the-show-is-over) new-world))) ;; key-event: World KeyEvent -> World ;; responds to input, launches rockets (define (key-event w key) (cond [(symbol? key) w] [(char? key) (cons (make-rocket (make-posn (remainder (* (char->integer key) 31) 300) 300) (+ 10.5 (/ (char->integer key) 48)) (make-color (+ 128 (remainder (* 31 (char->integer key)) 127)) (+ 128 (remainder (* 10 (char->integer key)) 127)) (+ 128 (remainder (* 15 (char->integer key)) 127)))) w)])) ;; world-draw: World -> Image ;; draws given world (define (world-draw w) (local ((define (draw-object x sc) (cond [(explosion? x) (draw-explosion x sc)] [(particle? x) (draw-particle x sc)] [(rocket? x) (draw-rocket x sc)]))) (foldr draw-object (nw:rectangle 300 300 'solid 'black) w))) #| ;; tests 'color-equal?-test (equal? true (color-equal? (make-color 5 5 5) (make-color 5 5 5))) 'color-fade-test (equal? (make-color 5 5 5) (color-fade (make-color 10 10 10) 5)) 'move-particle-test (equal? (move-particle (make-particle (make-posn 20 20) (make-posn 5 -5) (make-color 32 15 216))) (make-particle (make-posn 25 25) (make-posn 5 -5.2) (make-color 16 0 200))) 'draw-particle-test (equal? (place-image (circle 3 'solid (make-color 255 0 0)) 200 200 (empty-scene 300 300)) (draw-particle (make-particle (make-posn 200 200) (make-posn 10 10) (make-color 255 0 0)) (empty-scene 300 300))) 'grow-explosion-test (equal? (grow-explosion (make-explosion (make-posn 50 50) 5 4 (make-color 255 255 255))) (make-explosion (make-posn 50 45) 4.8 8 (make-color 239 239 239))) 'draw-explosion-test (equal? (place-image (star 12 2 10 'solid (make-color 50 50 50)) 20 20 (empty-scene 300 300)) (draw-explosion (make-explosion (make-posn 20 20) 5 10 (make-color 50 50 50)) (empty-scene 300 300))) 'move-rocket-test (equal? (move-rocket (make-rocket (make-posn 50 50) 10 (make-color 255 0 0))) (make-rocket (make-posn 50 40) 9.8 (make-color 255 0 0))) 'draw-rocket-test (equal? (draw-rocket (make-rocket (make-posn 50 50) 10 (make-color 255 0 0)) (empty-scene 300 300)) (place-image (circle 8 'solid (make-color 255 0 0)) 50 50 (empty-scene 300 300))) 'rocket-explode-test (equal? (rocket-explode (make-rocket (make-posn 50 50) 10 (make-color 255 0 0))) (cons (make-explosion (make-posn 50 50) 0 3 (make-color 255 0 0)) (build-list 12 (lambda (n) (make-particle (make-posn 50 50) (make-posn (* 4 (list-ref cos-list n)) (* 4 (list-ref sin-list n))) (make-color 255 0 0)))))) 'next-world-tests (equal? (next-world (list (make-explosion (make-posn 20 20) 5 10 (make-color 50 50 50)) (make-particle (make-posn 70 70) (make-posn 4 5) (make-color 150 150 150)) (make-rocket (make-posn 50 50) 5 (make-color 100 100 100)))) (append (rocket-explode (make-rocket (make-posn 50 50) 5 (make-color 100 100 100))) (list (move-particle (make-particle (make-posn 70 70) (make-posn 4 5) (make-color 150 150 150))) (grow-explosion (make-explosion (make-posn 20 20) 5 10 (make-color 50 50 50)))))) (equal? (next-world empty) (end-of-time 'the-show-is-over)) 'key-event-test (equal? empty (key-event empty 'up)) (equal? (key-event empty (integer->char 96)) (list (make-rocket (make-posn 276 300) 12.5 (make-color 183 199 171)))) 'world-draw-test (equal? (world-draw (list (make-rocket (make-posn 50 50) 10 (make-color 255 0 0)) (make-particle (make-posn 20 30) (make-posn 5 5) (make-color 0 255 0)) (make-explosion (make-posn 70 90) 5 10 (make-color 0 0 255)))) (draw-rocket (make-rocket (make-posn 50 50) 10 (make-color 255 0 0)) (draw-particle (make-particle (make-posn 20 30) (make-posn 5 5) (make-color 0 255 0)) (draw-explosion (make-explosion (make-posn 70 90) 5 10 (make-color 0 0 255)) (nw:rectangle 300 300 'solid 'black))))) |# (define start-world (list (make-rocket (make-posn 150 300) 10 (make-color 255 0 0)))) (define (main w) (and (big-bang 300 300 1/50 w) (on-tick-event next-world) (on-key-event key-event) (on-redraw world-draw))) (main start-world)