PasteRack.org
Paste # 26840
2016-12-09 12:42:26

Fork as a new paste.

Paste viewed 88 times.


Embed:

  1. #lang racket
  2.  
  3. ; ctrl+f "AN-IMAGE" and fix those
  4.  
  5. ;; Alina Christenbury
  6. ;; Brian Phillips
  7.  
  8. ;; Project 2b: Asteroids [130 pts]
  9. ;; Based on the classic video game. My feelings are that the essential features are the player
  10. ;; movement (there is loss of momentum) and firing, and the asteroids themselves; representing
  11. ;; these as circles is fine (i.e. a large circle when hit may break into 2-4 medium circles, which
  12. ;; break into 2-3 small circles which then can be destroyed, and scoring.
  13.  
  14. (require 2htdp/image)
  15. (require 2htdp/universe)
  16.  
  17.  
  18. ; CONSTANTS AND STRUCTURES
  19.  
  20.  
  21. ;; Width of the world
  22. (define WIDTH 600)
  23.  
  24. ;; Height of the world
  25. (define HEIGHT 400)
  26.  
  27. ;; The world's background
  28. (define BACKGROUND (rectangle WIDTH HEIGHT "solid" "Midnight Blue"))
  29.  
  30.  
  31. ;; The player's apperance
  32. (define PLAYER (overlay (polygon (list (make-posn 0 0) (make-posn -25 10)
  33.                                        (make-posn -18 0) (make-posn -25 -10))
  34.                                  "solid"
  35.                                  "Azure")
  36.                         (circle 16 "outline" "Midnight Blue")))
  37.  
  38. ;;Initial Player Speed
  39. (define INITIAL-PLAYER-SPEED 0)
  40.  
  41. ;; Degrees player rorates on keypress
  42. (define PLAYER-ROTATION 45)
  43. (define REVERSE-PLAYER-ROTATION -45)
  44.  
  45. ;; Bullet apperance
  46. (define BULLET (square 5 "solid" "red"))
  47.  
  48. ;; Initial Bullet Speed
  49. (define INITIAL-BULLET-SPEED 5)
  50.  
  51. ;; Number of ticks the bullets last
  52. (define BULLET-AGE 50)
  53.  
  54.  
  55. ;; Initial Number of Rocks
  56. (define INITIAL-NUM-ROCKS 5)
  57.  
  58. ;; A large rock's appereance
  59. (define LARGE-ROCK (polygon (list (make-posn 0 0) (make-posn 20 10) (make-posn 25 15)
  60.                                   (make-posn 30 30) (make-posn 20 35) (make-posn 5 40)
  61.                                   (make-posn -10 40) (make-posn -25 25) (make-posn -20 15)
  62.                                   (make-posn -5 5))
  63.                             "outline"
  64.                             "white"))
  65.  
  66. ;; A small rock's appereance
  67. (define SMALL-ROCK (scale 0.5 LARGE-ROCK))
  68.  
  69.  
  70. #|
  71. (make-posn x y)  posn
  72.   x : any/c
  73.   y : any/c
  74. Constructs a posn from two arbitrary values.
  75.  
  76. (posn-x p)  any
  77.   p : posn
  78. Extracts the x component of a posn.
  79.  
  80. (posn-y p)  any
  81.   p : posn
  82. Extracts the y component of a posn.
  83.  
  84. (posn? x)  boolean?
  85.   x : any/c
  86. Determines if its input is a posn.
  87. |#
  88.  
  89. (define-struct player (pos vel rotation))
  90. #|
  91. A Player is a (make-player Number Number Number)
  92.    Posn pos : the player's coordinates
  93.    Number vel : the player's velocity
  94.    Number rotation : The angle the player is rotated
  95.  
  96.    player-pos : player -> Posn
  97.    player-vel : player -> Number
  98.    player-rotation : player -> Number
  99.  
  100. player? : Any -> Boolean
  101. |#
  102. (define PLAYER0 (make-player (make-posn 0 0) 0 0))
  103. (define PLAYER1 (make-player (make-posn 300 240) 0 90))
  104.  
  105. ;; Template for function consuming a player :
  106. #;(define (player-fun aplayer)
  107.     ... (player-pos aplayer) ...
  108.     ... (player-vel aplayer) ...
  109.     ... (player-rotation aplayer) ...)
  110.  
  111.  
  112. ;; A PlayerSelector is one of
  113. (define pos "pos")
  114. (define vel "vel")
  115. (define rotation "rotation")
  116.  
  117.  
  118. ;; A RockSize is one of
  119. ; 0 (destroyed)
  120. ; 1 (small)
  121. ; 2 (medium)
  122. ; 3 (large)
  123.  
  124. #|
  125. update-posn : player String [Number or Boolean] -> player
  126. Consumes:
  127.    player aplayer : a player
  128.    PlayerSelector selector : a PlayerSelector, the old thing to be changed
  129.    [Number or Boolean] value : the new value
  130. Produces a player exactly like the old player, but with the selected value changed.
  131. |#
  132.  
  133.  
  134. (define-struct rock (pos vel size))
  135. #|
  136. A rock is a (make-rock Posn Posn Number)
  137.    Posn pos : the rock's coordinate
  138.    Posn vel : the rock's velocity
  139.    RockSize size : the size of the rock
  140.  
  141.    rock-pos : rock -> Posn
  142.    rock-vel : rock -> Posn
  143.    rock-size : rock -> Number
  144.  
  145. rock? : Any -> Boolean
  146. |#
  147. (define ROCK0 (make-rock (make-posn  0  0) (make-posn 0 0) 0))
  148. (define ROCK1 (make-rock (make-posn 50 50) (make-posn 1 1) 1))
  149. (define ROCK2 (make-rock (make-posn 60 60) (make-posn 2 2) 2))
  150. (define ROCK3 (make-rock (make-posn 75 75) (make-posn 5 5) 3))
  151.  
  152. ;; Template for function consuming a rock :
  153. #;(define (rock-fun arock)
  154.     ... (rock-pos arock) ...
  155.     ... (rock-vel arock) ...
  156.     ... (rock-size arock) ...)
  157.  
  158. ;; A RockSelector is one of
  159. ;(define pos "pos")
  160. ;(define vel "vel")
  161. (define size "size")
  162.  
  163.  
  164. ;; A ListOfRocks [LORocks] is one of:
  165. ; empty
  166. ; (cons Rock LORocks)
  167.  
  168.  
  169.  
  170. (define-struct bullet (pos vel age))
  171. #|
  172. A Bullet is a (make-bullet Posn Posn PosInt)
  173.     Posn pos : the pos of the Bullet
  174.     Posn vel : the x/y velocity of the Bullet
  175.     PosInt age : the remaining number of ticks that the bullet will exist for
  176.  
  177.     bullet-pos : Bullet -> Posn
  178.     bullet-vel : Bullet -> Posn
  179.     bullet-age : Bullet -> PosInt
  180.  
  181. bullet? : Any -> Boolean
  182. |#
  183.  
  184. ;; Template
  185. #;(define (bullet-fun abullet)
  186.     ... (bullet-pos abullet) ...
  187.     ... (bullet-vel abullet) ...
  188.     ... (bullet-age abullet) ...)
  189.  
  190.  
  191. ;; A ListOfBullets [LOBullets] is one of:
  192. ; empty
  193. ; (cons Bullet LOBullets)
  194.  
  195.  
  196.  
  197. (define-struct world (player rocks bullets lives level score))
  198. #|
  199. A World is a (make-world Player ListOfRocks ListOfBullets Number Number Number)
  200.     Player player : the Player
  201.     LORocks rocks : a List of the Rocks in the World
  202.     LOBullets bullets : a List of the Bullets in the World
  203.     PosInt lives : the number of lives the user has remaining
  204.     PosInt level : the level that the user is on
  205.     PosInt score : the score of the user
  206.  
  207.     world-player : World --> Player
  208.     world-rocks : World --> LORocks
  209.     world-bullets : World --> LORocks
  210.     world-lives : World --> PosInt
  211.     world-level : World --> PosInt
  212.     world-score : World --> PosInt
  213.  
  214. world? : ANY --> Boolean
  215. |#
  216. ;; TEMPLATE
  217. #;(define (world-fun aworld)
  218.     ... (world-player aworld) ;Player
  219.     ... (world-rocks aworld) ;LORocks
  220.     ... (world-bullets aworld) ;LOBullets
  221.     ... (world-lives aworld) ;PosInt
  222.     ... (world-level aworld) ;PosInt
  223.     ... (world-score aworld)) ;PosInt
  224.  
  225.  
  226. ; FUNCTIONS
  227.  
  228. ;; large? : Rock --> Boolean
  229. ;; Checks if an rock is large or not
  230. (define (large? arock) (string=? (rock-size arock) "large"))
  231. (check-expect (large? (make-rock (make-posn 237 68) (make-posn 1 1) "large")) true)
  232.  
  233.  
  234. ;;
  235. ;; small? : Rock --> Boolean
  236. ;; Checks if an rock is small or not
  237. (define (small? anrock) (string=? (rock-size anrock) "small"))
  238. (check-expect (small? (make-rock (make-posn 371 360) (make-posn 2 -4) "small")) true)
  239.  
  240. ;;
  241. ;; add-pos : Posn Posn --> Posn
  242. ;; Given 2 Posns, returns the sum of the Posns. This also helps with screen wrapping.
  243. (define (add-pos posa posb) (make-posn (modulo (+ (posn-x posa) (posn-x posb)) WIDTH)
  244.                                        (modulo (+ (posn-y posa) (posn-y posb)) HEIGHT)))
  245. (check-expect (add-pos (make-posn 540 240) (make-posn 5 0)) (make-posn 545 240))
  246. ;;
  247. ;; multiply-pos : Posn Number --> Posn
  248. ;; Given a Posn and a Number(n), returns the product of the Posn and the Number in Posn form
  249. (define (multiply-pos apos n) (make-posn (modulo (* (posn-x apos) n) WIDTH)
  250.                                          (modulo (* (posn-y apos) n) HEIGHT)))
  251. (check-expect (multiply-pos (make-posn 5 0) 5) (make-posn 25 0))
  252. ;;
  253. ;; rotation->pos : Number --> Posn
  254. ;; Given an rotation, returns a pos
  255. (define (rotation->pos rotation) (make-posn (inexact->exact (round (cos (* rotation pi 1/180))))
  256.                                             (* -1 (inexact->exact (round (sin (* rotation pi 1/180)))))))
  257. (check-expect (rotation->pos 90) (make-posn 0 -1))
  258. ;;
  259. ;; move-player : Player --> Player
  260. ;; Given a Player, moves the player forward using its direction and its vel
  261. (define (move-player aplayer) (make-player (add-pos (player-pos aplayer)
  262.                                                     (multiply-pos (rotation->pos (player-rotation aplayer))
  263.                                                                   (player-vel aplayer)))
  264.                                            (if (zero? (player-vel aplayer)) 0 (- (player-vel aplayer) 1))
  265.                                            (player-rotation aplayer)))
  266. (check-expect (move-player (make-player (make-posn 300 240) 0 0)) (make-player (make-posn 300 240) 0 0))
  267. ;;
  268. ;; move-rocks : LORocks --> LORocks
  269. ;; Given a LORocks, moves all of the rocks.
  270. (define (move-rocks alorocks)
  271.   (local [(define (move-roid anrock) (make-rock (add-pos (rock-pos anrock)
  272.                                                          (rock-vel anrock))
  273.                                                 (rock-vel anrock)
  274.                                                 (rock-size anrock)))]
  275.     (map move-roid alorocks)))
  276. (check-expect (move-rocks (list (make-rock (make-posn 202 245) (make-posn -4 -4) "small")
  277.                                 (make-rock (make-posn 527 191) (make-posn 1 3) "small")))
  278.               (list (make-rock (make-posn 198 241) (make-posn -4 -4) "small")
  279.                     (make-rock (make-posn 528 194) (make-posn 1 3) "small")))
  280. ;;
  281. ;; move-bullets : LOBullets --> LOBullets
  282. ;; Given a LOBullets, moves every bullet in accordance to its velocity and reduces its age.
  283. (define (move-bullets alobullets)
  284.   (local [(define (move-bullet bullet) (make-bullet (add-pos (bullet-pos bullet)
  285.                                                              (bullet-vel bullet))
  286.                                                     (bullet-vel bullet)
  287.                                                     (- (bullet-age bullet) 1)))]
  288.     (map move-bullet alobullets)))
  289. (check-expect (move-bullets (list (make-bullet (make-posn 566 222) (make-posn 0 5) 23)))
  290.               (list (make-bullet (make-posn 566 227) (make-posn 0 5) 22)))
  291. ;;
  292. ;; hit? : Rock Bullet -> Boolean
  293. ;; Given an Rock and a Bullet, checks if they have collided.
  294. (define (hit? anrock abullet)
  295.   (local [(define A-WIDTH  (cond [(large? anrock) (* 0.5 (image-width  LARGE-ROCK))]
  296.                                  [(small? anrock) (* 0.5 (image-width  SMALL-ROCK))]))
  297.           (define A-HEIGHT (cond [(large? anrock) (* 0.5 (image-height LARGE-ROCK))]
  298.                                  [(small? anrock) (* 0.5 (image-height SMALL-ROCK))]))]
  299.     (and (< (- (posn-x (rock-pos anrock)) A-WIDTH)
  300.             (posn-x (bullet-pos abullet))
  301.             (+ (posn-x (rock-pos anrock)) A-WIDTH))
  302.          (< (- (posn-y (rock-pos anrock)) A-HEIGHT)
  303.             (posn-y (bullet-pos abullet))
  304.             (+ (posn-y (rock-pos anrock)) A-HEIGHT)))))
  305. (check-expect (hit? (make-rock (make-posn 134 357) (make-posn 1 -1) "small")
  306.                     (make-bullet (make-posn 300 155) (make-posn 0 395) 33)) false)
  307. ;;
  308. ;; filter-small-rocks : LORocks LOBullets --> LORocks
  309. ;; Given a list of Rocks and a list of Bullets, filters out all small rocks that have been hit by bullets.
  310. (define (filter-small-rocks alorocks alobullets)
  311.   (local [(define (not-hit? anrock) (not (ormap (lambda (abullet) (hit? anrock abullet))
  312.                                                 alobullets)))
  313.           (define (keep? anrock) (cond [(large? anrock) true]
  314.                                        [(small? anrock) (not-hit? anrock)]))]
  315.     (filter keep? alorocks)))
  316. (check-expect (filter-small-rocks (list (make-rock (make-posn 530 280) (make-posn -3 3) "small"))
  317.                                   (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  318.               (list (make-rock (make-posn 530 280) (make-posn -3 3) "small")))
  319. ;;
  320. ;; filter-large-rocks : LORocks LOBullets --> LORocks
  321. ;; Given a list of Rocks and a list of Bullets, breaks apart any large rocks that have been hit by bullets into small rocks.
  322. (define (filter-large-rocks alorocks alobullets)
  323.   (local [(define (make-smalls pos num) (cond [(zero? num) empty]
  324.                                               [else (cons (make-rock pos
  325.                                                                      (make-posn (- (random 8) 4)
  326.                                                                                 (- (random 8) 4))
  327.                                                                      "small")
  328.                                                           (make-smalls pos (- num 1)))]))
  329.           (define (break? anrock) (and (large? anrock)
  330.                                        (ormap (lambda (abullet) (hit? anrock abullet)) alobullets)))
  331.           (define (break-if alorocks) (cond [(empty? alorocks) empty]
  332.                                             [(cons? alorocks) (cond [(break? (first alorocks)) (append (make-smalls (rock-pos (first alorocks)) 3)
  333.                                                                                                        (break-if (rest alorocks)))]
  334.                                                                     [(not (break? (first alorocks))) (cons (first alorocks)
  335.                                                                                                            (break-if (rest alorocks)))])]))]
  336.     (break-if alorocks)))
  337. (check-expect (filter-large-rocks (list (make-rock (make-posn 530 280) (make-posn -3 3) "small"))
  338.                                   (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  339.               (list (make-rock (make-posn 530 280) (make-posn -3 3) "small")))
  340. ;;
  341. ;; filter-rocks : LORocks LOBullets --> LORocks
  342. ;; Function composes filter-small-rocks and filter-large-rocks
  343. (define (filter-rocks alorocks alobullets) (filter-large-rocks (filter-small-rocks alorocks alobullets) alobullets))
  344. (check-expect (filter-rocks (list (make-rock (make-posn 530 280) (make-posn -3 3) "small"))
  345.                             (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  346.               (list (make-rock (make-posn 530 280) (make-posn -3 3) "small")))
  347. ;;
  348. ;; filter-hit-bullets : LORocks LOBullets --> LOBullets
  349. ;; Filters out any bullets that have hit an rock.
  350. (define (filter-hit-bullets alorocks alobullets)
  351.   (local [(define (has-not-hit? abullet) (not (ormap (lambda (anrock) (hit? anrock abullet)) alorocks)))]
  352.     (filter has-not-hit? alobullets)))
  353. (check-expect (filter-hit-bullets (list (make-rock (make-posn 530 280) (make-posn -3 3) "small"))
  354.                                   (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  355.               (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  356. ;;
  357. ;; filter-dead-bullets : LOBullets --> LOBullets
  358. ;; Filters out any dead bullets from a LOBullets
  359. (define (filter-dead-bullets alobullets) (filter (λ (abullet) (> (bullet-age abullet) 0)) alobullets))
  360. (check-expect (filter-dead-bullets (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  361.               (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)))
  362. ;;
  363. ;; make-rocks : PosInt --> LORocks
  364. ;; Given a PosInt, returns a randomly generated list of the given length of large Rocks.
  365. (define (make-rocks num)
  366.   (cond [(zero? num) empty]
  367.         [else (cons (make-rock (make-posn (random WIDTH)
  368.                                           (random HEIGHT))
  369.                                (make-posn (- (random 8) 4)
  370.                                           (- (random 8) 4))
  371.                                "large")
  372.                     (make-rocks (- num 1)))]))
  373. (check-expect (length (make-rocks 5)) 5)
  374. ;;
  375. ;; check-lives : World --> World
  376. ;; When a player collides with a rocks, loses a life and returns player to the center
  377. (define (check-lives aworld)
  378.   (local [(define player-bullet (make-bullet (player-pos (world-player aworld))
  379.                                              (make-posn 0 0)
  380.                                              100))]
  381.     (if (ormap (lambda (anrock) (hit? anrock player-bullet)) (world-rocks aworld))
  382.         (make-world (make-player (make-posn (* WIDTH 0.5)
  383.                                             (* HEIGHT 0.6))
  384.                                  INITIAL-PLAYER-SPEED
  385.                                  90)
  386.                     (make-rocks INITIAL-NUM-ROCKS)
  387.                     empty
  388.                     (sub1 (world-lives aworld))
  389.                     (world-level aworld)
  390.                     (- (world-score aworld) 20))
  391.         aworld)))
  392. (check-expect (check-lives (make-world PLAYER1
  393.                                        (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  394.                                        (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  395.               (make-world PLAYER1
  396.                           (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  397.                           (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  398. ;;
  399. ;; award-points : LORocks LORocks LORocks --> Number
  400. ;; Calculates the number of points the user has obtained. Large Rocks are worth 5 points and small Rocks are worth 10 points.
  401. (define (award-points alorocks1 alorocks2 alorocks3)
  402.   (local [(define (count-roids size alorocks) (foldl (λ (anrock count) (if (string=? size (rock-size anrock))
  403.                                                                            (add1 count)
  404.                                                                            count))
  405.                                                      0
  406.                                                      alorocks))]
  407.     (+ (* 5  (- (count-roids "large" alorocks1)
  408.                 (count-roids "large" alorocks2)))
  409.        (* 10 (- (count-roids "small" alorocks2)
  410.                 (count-roids "small" alorocks3))))))
  411. ;;CHECK-EXPECTED THROUGH OTHER FUNCTIONS
  412. ;;
  413. ;; ticks : World --> World
  414. ;; Given a world, function composes multiple previous functions to create a tick-handler
  415. (define (ticks aworld)
  416.   (local [(define alorocks1 (world-rocks aworld))
  417.           (define alobullets1 (filter-dead-bullets (world-bullets aworld)))
  418.           (define alorocks2 (filter-large-rocks alorocks1 alobullets1))
  419.           (define alobullets2 (filter-hit-bullets (filter large? alorocks1) alobullets1))
  420.           (define alorocks3 (filter-small-rocks alorocks2 alobullets2))
  421.           (define alobullets3 (filter-hit-bullets (filter small? alorocks3) alobullets2))
  422.           (define rocks (move-rocks alorocks3))
  423.           (define bullets (move-bullets alobullets3))
  424.           (define score (+ (world-score aworld) (award-points alorocks1 alorocks2 alorocks3)))]
  425.     (check-lives (make-world (move-player (world-player aworld))
  426.                              rocks
  427.                              bullets
  428.                              (world-lives aworld)
  429.                              (world-level aworld)
  430.                              score))))
  431. (check-expect(ticks (make-world PLAYER1
  432.                                 (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  433.                                 (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  434.              (make-world PLAYER1
  435.                          (list (make-rock (make-posn 231 10) (make-posn -3 -4) "small"))
  436.                          (list (make-bullet (make-posn 300 200) (make-posn 0 395) 42)) 4 1 235))
  437. ;;
  438. ;; turn : Number World --> World
  439. ;; Given a degree of turn and a World, turns the player within the world in accordance to degree of turn
  440. (define (turn degree aworld) (make-world (make-player (player-pos (world-player aworld))
  441.                                                       (player-vel (world-player aworld))
  442.                                                       (modulo (+ degree (player-rotation (world-player aworld))) 360))
  443.                                          (world-rocks aworld)
  444.                                          (world-bullets aworld)
  445.                                          (world-lives aworld)
  446.                                          (world-level aworld)
  447.                                          (world-score aworld)))
  448. (check-expect (turn 10 (make-world PLAYER1
  449.                                    (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  450.                                    (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  451.               (make-world (make-player (make-posn 300 240) 0 100)
  452.                           (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  453.                           (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  454. ;;
  455. ;; boost-player : World --> World
  456. ;; Given a world, increases the player's vel
  457. (define (boost-player aworld) (make-world (make-player (player-pos (world-player aworld))
  458.                                                        (+ 7 (player-vel (world-player aworld)))
  459.                                                        (player-rotation (world-player aworld)))
  460.                                           (world-rocks aworld)
  461.                                           (world-bullets aworld)
  462.                                           (world-lives aworld)
  463.                                           (world-level aworld)
  464.                                           (world-score aworld)))
  465. (check-expect (boost-player (make-world PLAYER1
  466.                                         (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  467.                                         (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  468.               (make-world (make-player (make-posn 300 240) 7 90)
  469.                           (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  470.                           (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  471. ;;
  472. ;; shoot : World --> World
  473. ;; Given a world, adds a new bullet to a World based on the players pos and rotation
  474. (define (shoot aworld) (make-world (world-player aworld)
  475.                                    (world-rocks aworld)
  476.                                    (cons (make-bullet (player-pos (world-player aworld))
  477.                                                       (multiply-pos (rotation->pos (player-rotation (world-player aworld))) INITIAL-BULLET-SPEED)
  478.                                                       BULLET-AGE)
  479.                                          (world-bullets aworld))
  480.                                    (world-lives aworld)
  481.                                    (world-level aworld)
  482.                                    (world-score aworld)))
  483. (check-expect (shoot (make-world PLAYER1
  484.                                  (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  485.                                  (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  486.               (make-world PLAYER1
  487.                           (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  488.                           (list (make-bullet (make-posn 300 240) (make-posn 0 395) 50)
  489.                                 (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  490.  
  491.  
  492. ;; key-handler: World KeyEvent --> World
  493. ;; Key-handler for the world, uses up/left/right for directional movement and space to fire.
  494. (define (key-handler aworld akey)
  495.   (cond [(key=? akey "up") (boost-player aworld)]
  496.         [(key=? akey "left") (turn  PLAYER-ROTATION aworld)]
  497.         [(key=? akey "right") (turn REVERSE-PLAYER-ROTATION aworld)]
  498.         [(key=? akey " ") (shoot aworld)]
  499.         [else aworld]))
  500. (check-expect (key-handler (make-world PLAYER1
  501.                                        (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  502.                                        (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235)
  503.                            "q")
  504.               (make-world PLAYER1
  505.                           (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  506.                           (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235))
  507. ;;
  508. ;; print-text: String Number --> Image
  509. ;; Outputs an image of a given string in a given font size
  510. (define (print-text astring num) (text/font astring num "white" #f 'modern 'italic 'normal #f))
  511. #;(check-expect (print-text "Rocks" 12) AN-IMAGE)
  512.  
  513. ;;
  514. ;; place-player : Player Image --> Image
  515. ;; Places a player onto the image.
  516. (define (place-player aplayer animage) (place-image (rotate (player-rotation aplayer) PLAYER)
  517.                                                     (posn-x (player-pos aplayer))
  518.                                                     (posn-y (player-pos aplayer))
  519.                                                     animage))
  520. ;;CHECK-EXPECTED BY CHECKING display-world
  521. ;;
  522. ;; place-rocks : LORocks Image --> Image
  523. ;; Places all rocks within the LORocks onto the image.
  524. (define (place-rocks alorocks animage)
  525.   (local [(define (place-roid anrock base)
  526.             (place-image (cond [(large? anrock) LARGE-ROCK]
  527.                                [(small? anrock) SMALL-ROCK])
  528.                          (posn-x (rock-pos anrock))
  529.                          (posn-y (rock-pos anrock))
  530.                          base))]
  531.     (foldr place-roid animage alorocks)))
  532. ;;CHECK-EXPECTED BY CHECKING display-world
  533. ;;
  534. ;; place-bullets : LOBullets Image --> Image
  535. ;; Places all bullets within the LOBullets onto the images.
  536. (define (place-bullets alobullets animage)
  537.   (local [(define (place-bullet abullet base)
  538.             (place-image BULLET
  539.                          (posn-x (bullet-pos abullet))
  540.                          (posn-y (bullet-pos abullet))
  541.                          base))]
  542.     (foldr place-bullet animage alobullets)))
  543. ;;CHECK-EXPECTED BY CHECKING display-world
  544. ;;
  545. ;; score-lives : World Image -> Image
  546. ;; Appends the score and lives and places them onto the image
  547. (define (score-lives aworld animage)
  548.   (local [(define score/lives (print-text (string-append "Score: " (number->string (world-score aworld)) "  "
  549.                                                          "Lives: " (number->string (world-lives aworld)))
  550.                                           15))]
  551.     (place-image score/lives
  552.                  (/ WIDTH 2) (image-height score/lives)
  553.                  animage)))
  554. ;;CHECK-EXPECTED BY CHECKING display-world
  555. ;;
  556. ;; display-world : World --> Image
  557. ;; Draws the world by function composing multiple previous functions
  558. (define (display-world aworld) (score-lives aworld (place-bullets (world-bullets aworld) (place-rocks (world-rocks aworld) (place-player (world-player aworld) BACKGROUND)))))
  559. #;
  560. (check-expect (display-world (make-world PLAYER1
  561.                                          (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  562.                                          (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235)) AN-IMAGE)
  563. ;;
  564. ;; stop?: World -> Boolean
  565. ;; Returns true if there are no rocks or lives left.
  566. (define (stop? aworld) (or (zero? (world-lives aworld))
  567.                            (zero? (length (world-rocks aworld)))))
  568. (check-expect (stop? (make-world PLAYER1
  569.                                  (list (make-rock (make-posn 234 14) (make-posn -3 -4) "small"))
  570.                                  (list (make-bullet (make-posn 300 205) (make-posn 0 395) 43)) 4 1 235)) false)
  571.  
  572. ;; END : World --> Image
  573. ;; The end game screen.
  574. (define (END-SCREEN aworld)
  575.   (local [(define W/L (cond [(zero? (world-lives aworld)) "YOU LOSE"]
  576.                             [(zero? (length (world-rocks aworld))) "YOU WIN"]))]
  577.     (overlay (above (print-text W/L 36)
  578.                     (print-text (string-append "Score: " (number->string (world-score aworld)))
  579.                                 24))
  580.              BACKGROUND)))
  581. #;(check-expect (END-SCREEN (make-world PLAYER1
  582.                                         (list (make-rock (make-posn 125 273) (make-posn 3 2) "large")
  583.                                               (make-rock (make-posn 150 244) (make-posn -1 2) "large")
  584.                                               (make-rock (make-posn 11 273) (make-posn -4 -2) "large")
  585.                                               (make-rock (make-posn 133 362) (make-posn 3 3) "large")
  586.                                               (make-rock (make-posn 426 375) (make-posn 3 0) "large"))
  587.                                         empty 0 1 -100))
  588.                 AN-IMAGE)
  589.  
  590. ;; Starting world
  591. (define start (make-world (make-player (make-posn (* WIDTH 0.5)
  592.                                                   (* HEIGHT 0.6))
  593.                                        INITIAL-PLAYER-SPEED
  594.                                        90)
  595.                           (make-rocks INITIAL-NUM-ROCKS)
  596.                           empty
  597.                           5
  598.                           1
  599.                           0))
  600.  
  601. ;; big-bang
  602. (big-bang start
  603.           (on-tick ticks)
  604.           (on-key key-handler)
  605.           (on-draw display-world)
  606.           (stop-when stop? END-SCREEN)
  607.           (state false))

=>