Design a complete Space Invaders Game - Part 2
For the second iteration I am going to add a big-bang function to the game and draw the game as a game world. The game world current consists of a collection of ufos and our tank.
As adding the game code here for drawing the world is pretty simple I have also added a function that will programatically generate a collection of ufos. This is to save specifying the initial position of each ufo by hand. To start with I am drawing 3 rows of how ever many ufos will currently fit.
Code
(require racket/base)
(define-struct ufo (x y) #:transparent)
(define-struct tank (x y) #:transparent)
(define-struct world (ufos tank))
; physical constants
(define WIDTH 300) ; the maximal number of blocks horizontally
(define HEIGHT 300) ; the maximal number of blocks horizontally
; graphical constants
(define SIZE 10) ; the size of the block making up the ufo
(define UFO-WIDTH 50)
(define BLOCK ; they are rendered as red squares with black rims
(overlay (rectangle (- SIZE 1) (- SIZE 1) "solid" "red")
(rectangle SIZE SIZE "outline" "black")))
(define TEST-UFO (make-ufo 30 30)) ; for testing
(define TEST-UFOS (list (make-ufo 30 30)
(make-ufo 80 30)
(make-ufo 130 30))); for testing
; initial tank position should be middle of the screen, one block up from
; the bottom
(define TANK (make-tank (/ WIDTH 2) (- HEIGHT (* SIZE 2))))
; Creates a row of ufos on the supplied y-cordinate
; Integer Ufos -> Ufos
(define (make-ufos-for-y y-cordinate ufos)
(cond ((empty? ufos) (make-ufos-for-y y-cordinate
(cons (make-ufo 20 y-cordinate) ufos)))
((> (+ (ufo-x (first ufos)) UFO-WIDTH) WIDTH) ufos)
(else (make-ufos-for-y y-cordinate
(cons (make-ufo (+ (ufo-x (first ufos)) UFO-WIDTH)
y-cordinate) ufos )))))
; create a complete collection of rows of ufos
; Integer Ufos -> Ufos
(define (make-ufos rows ufos)
(cond ((= 0 rows) ufos)
(else (make-ufos (- rows 1)
(append ufos (make-ufos-for-y ( * rows 30) empty))))))
; draw a triangular shaped alien
(define (draw-ufo ufo background)
(place-image/align BLOCK (ufo-x ufo) (ufo-y ufo) "left" "bottom"
(place-image/align BLOCK (- (ufo-x ufo) SIZE) (ufo-y ufo) "left" "bottom"
(place-image/align BLOCK (+ (ufo-x ufo) SIZE) (ufo-y ufo) "left" "bottom"
(place-image/align BLOCK (ufo-x ufo) (+ (ufo-y ufo) SIZE) "left" "bottom"
background)))))
; draw a tank shaped tank
(define (draw-tank tank background)
(place-image/align BLOCK (tank-x tank) (tank-y tank) "left" "bottom"
(place-image/align BLOCK (- (tank-x tank) SIZE) (tank-y tank) "left" "bottom"
(place-image/align BLOCK (+ (tank-x tank) SIZE) (tank-y tank) "left" "bottom"
(place-image/align BLOCK (tank-x tank) (+ (tank-y tank) SIZE)
"left" "bottom"
(place-image/align BLOCK (- (tank-x tank) SIZE) (+ (tank-y tank) SIZE )
"left" "bottom"
(place-image/align BLOCK (+ (tank-x tank) SIZE) (+ (tank-y tank) SIZE)
"left" "bottom"
(place-image/align BLOCK (tank-x tank) (- (tank-y tank) SIZE)
"left" "bottom"
background))))))))
; draw the collection of ufos on to the background.
; a simple recursive function
; Ufos Scene -> Scene
(define (draw-ufos ufos background)
(cond ((empty? ufos) background)
(else (draw-ufo (first ufos) (draw-ufos (rest ufos)
background)))))
; Draws the world as a scene
; World -> Scene
(define (render-scene world)
(draw-ufos (world-ufos world)
(draw-tank (world-tank world) (empty-scene WIDTH HEIGHT))))
; This is the big bang function that drives the game.
(define (space-invaders-main rate)
(big-bang (make-world (make-ufos 3 empty) TANK)
(to-draw render-scene)))
(space-invaders-main 0.2)
; tests
; simple example - a single block in an empty landscape
(check-expect (draw-ufo TEST-UFO (empty-scene WIDTH HEIGHT))
(place-image/align BLOCK (ufo-x TEST-UFO) (ufo-y TEST-UFO) "left" "bottom"
(place-image/align BLOCK (- (ufo-x TEST-UFO) SIZE) (ufo-y TEST-UFO)
"left" "bottom"
(place-image/align BLOCK (+ (ufo-x TEST-UFO) SIZE) (ufo-y TEST-UFO)
"left" "bottom"
(place-image/align BLOCK (ufo-x TEST-UFO) (+ (ufo-y TEST-UFO) SIZE)
"left" "bottom"
(empty-scene WIDTH HEIGHT))))))
; test drawing three ufo's via the draw-ufos function
(check-expect (draw-ufos TEST-UFOS (empty-scene WIDTH HEIGHT))
(draw-ufo (first TEST-UFOS)
(draw-ufo (second TEST-UFOS)
(draw-ufo (third TEST-UFOS) (empty-scene WIDTH HEIGHT)))))
; test the tank drawing works
(check-expect (draw-tank TANK (empty-scene WIDTH HEIGHT))
(place-image/align BLOCK (tank-x TANK) (tank-y TANK) "left" "bottom"
(place-image/align BLOCK (- (tank-x TANK) SIZE) (tank-y TANK) "left" "bottom"
(place-image/align BLOCK (+ (tank-x TANK) SIZE) (tank-y TANK) "left" "bottom"
(place-image/align BLOCK (tank-x TANK) (+ (tank-y TANK) SIZE) "left" "bottom"
(place-image/align BLOCK (- (tank-x TANK) SIZE) (+ (tank-y TANK) SIZE )
"left" "bottom"
(place-image/align BLOCK (+ (tank-x TANK) SIZE) (+ (tank-y TANK) SIZE)
"left" "bottom"
(place-image/align BLOCK (tank-x TANK) (- (tank-y TANK) SIZE)
"left" "bottom"
(empty-scene WIDTH HEIGHT)))))))))
No comments:
Post a Comment