Skip to content

Instantly share code, notes, and snippets.

@davesmylie
Created May 10, 2012 02:53
Show Gist options
  • Save davesmylie/2650711 to your computer and use it in GitHub Desktop.
Save davesmylie/2650711 to your computer and use it in GitHub Desktop.
H2DP2E: Exercise 171
; 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