Created
May 10, 2012 02:53
-
-
Save davesmylie/2650711 to your computer and use it in GitHub Desktop.
H2DP2E: Exercise 171
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Constants | |
(define WORM-SIZE 10) | |
(define WORM-MOVE WORM-SIZE) | |
(define WIDTH 800) ; width of the game | |
; these structs will hold the current position of the worm, the direction | |
; the worm is travelling in, and our world object | |
(define-struct worm(x-pos y-pos)) | |
(define-struct direction(x y)) | |
(define-struct world(worm direction)) | |
; To save repeating these directions in tests and code, we'll define them here | |
(define DOWN (make-direction 0 1)) | |
(define UP (make-direction 0 -1)) | |
(define RIGHT (make-direction 1 0)) | |
(define LEFT (make-direction -1 0)) | |
(define HEIGHT 500) ; height of the game | |
; Functions | |
; draw worm in its current location on the screen | |
(define (draw-worm background worm) | |
(place-image (circle WORM-SIZE "solid" "red") | |
(worm-x-pos worm) (worm-y-pos worm) background)) | |
; check if the snake has hit the edge of the world. | |
; return true if collision detected, false otherwise | |
(define (collision-detected world) | |
(collision-detected-helper (move-worm world))) | |
; helper function for collision detection. Operates directly | |
; on a worm, rather than world object. | |
(define (collision-detected-helper worm) | |
(cond [(> 0 (worm-x-pos worm)) true] ; exceeding left edge | |
[(> 0 (worm-y-pos worm)) true] ; exceeding top edge | |
[(< WIDTH (worm-x-pos worm)) true] ; exceeding right edge | |
[(< HEIGHT (worm-y-pos worm)) true] ; exceeding bottom edge | |
[else false])) | |
; Draw our final scene with the worm departing the board | |
; Displays a "Game Over" type message. We should probably be calculating the | |
; width and height of the image to calculate the offsets, but it's simpler just | |
; to arbitrarily put it somewhere in the bottom right of the screen | |
(define (final-scene world) | |
(draw-worm | |
(place-image (text "worm hit border" 20 "red") | |
(- WIDTH 100) | |
(- HEIGHT 50) | |
(empty-scene WIDTH HEIGHT)) | |
(world-worm world))) | |
; Draws the current world. Currently this just consists of the snake. | |
(define (show world) | |
(draw-worm (empty-scene WIDTH HEIGHT) (world-worm world)) ) | |
; Move the worm in the current direction. | |
; This function is called on each clock tick and moves the worm in the | |
; last direction that was pressed. It is also called from collision-detection | |
; to determine where the worm will be next turn. | |
(define (move-worm world) | |
(make-worm (+ (worm-x-pos (world-worm world)) | |
(* WORM-MOVE (direction-x (world-direction world)))) | |
(+ (worm-y-pos (world-worm world)) | |
(* WORM-MOVE (direction-y (world-direction world))))) | |
) | |
; On each clock tick, move the world further in time. This is a new function | |
; that takes part of the responsibily of the old move-worm function. It just | |
; moves the worm and creates a new world based on it. | |
(define (progress-world world) | |
(make-world | |
(move-worm world) | |
(world-direction world)) | |
) | |
; handle keyboard events. | |
(define (handle-key-events ws ke) | |
(cond | |
[(string=? "left" ke) (change-direction ws LEFT)] | |
[(string=? "right" ke) (change-direction ws RIGHT)] | |
[(string=? "up" ke) (change-direction ws UP )] | |
[(string=? "down" ke) (change-direction ws DOWN)] | |
[else ws] | |
)) | |
; create a new world with the direction the worm is travelling in changed. | |
(define (change-direction world direction) | |
(make-world (world-worm world) direction)) | |
; This is the big bang function that drives the game. | |
(define (worm-main rate) | |
(big-bang (make-world (make-worm (/ WIDTH 2) (/ HEIGHT 2)) | |
(make-direction 1 0)) | |
(to-draw show) | |
(stop-when collision-detected final-scene) | |
(on-key handle-key-events) | |
(on-tick progress-world rate) )) | |
; start the game off! | |
;(worm-main 0.1) | |
; ### NEW TESTS ### | |
; exceeding the bottom of the screen | |
(check-expect (collision-detected (make-world | |
(make-worm (- WIDTH 10) (+ HEIGHT 10)) RIGHT)) | |
true) | |
; exceeding the right side of the scren | |
(check-expect (collision-detected (make-world | |
(make-worm (+ WIDTH 10) (- HEIGHT 10)) RIGHT)) | |
true) | |
; exceeding the top of the screen | |
(check-expect (collision-detected (make-world | |
(make-worm -10 (- HEIGHT 10)) LEFT)) | |
true) | |
; exceeding the left side of the screen | |
(check-expect (collision-detected (make-world | |
(make-worm (- WIDTH 10) -10) LEFT)) | |
true) | |
;in the middle of the screen - should not collide | |
(check-expect (collision-detected (make-world | |
(make-worm (- WIDTH 10) (- HEIGHT 10)) LEFT)) | |
false) | |
; ### OLD TESTS | |
; Test our worm draws as we expect it. | |
(check-expect (draw-worm (empty-scene 100 100) (make-worm 50 50)) | |
(place-image (circle WORM-SIZE "solid" "red") 50 50 (empty-scene 100 100))) | |
; Test our worm moves in the direction we expect | |
(check-expect (move-worm (make-world (make-worm 50 50) DOWN)) | |
(make-worm 50 60)) | |
(check-expect (move-worm (make-world (make-worm 50 50) UP)) | |
(make-worm 50 40)) | |
(check-expect (move-worm (make-world (make-worm 50 50) LEFT)) | |
(make-worm 40 50)) | |
(check-expect (move-worm (make-world (make-worm 50 50) RIGHT)) | |
(make-worm 60 50)) | |
; Test our change-direction function changes the direction, but doesn't impact the postion | |
(check-expect (change-direction (make-world (make-worm 50 50) DOWN) UP) | |
(make-world (make-worm 50 50) UP)) | |
(check-expect (change-direction (make-world (make-worm 50 50) DOWN) RIGHT) | |
(make-world (make-worm 50 50) RIGHT)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment