(define title "The Worm, Moving") ;; GOAL: get them to see the connectivity among the data definitions for design. ;; SHOW: the data definitions, the constant definitions ;; THEN: design the world-image function; time permitting also show world-move (define-struct world (worm food)) (define-struct food (x y)) (define-struct worm (dir seg)) #| ----------------------------------------------------------------------------- WORM WORLD World is a structure: (make-world Worm Food) Food is a structure: (make-food Number Number) Worm is a structure: (make-worm Direction Segments) Direction is one of the following symbols: -- 'up -- 'down -- 'left -- 'right Segements is one of: -- empty -- (cons Posn Segments) |# ;; Start with the world, when you make up a wish list, the others will fall ;; out. This should suggest something like that. ;; world-draw : World -> Image ;; world-move : World -> World ;; worm-draw : Worm -> Image ;; worm-move : Worm -> Worm ;; worm-change-direction : Worm Direction -> Worm ;; worm-eat : Worm Food -> Worm ;; food-draw : Food -> Image ;; Add purpose statements. Then pick a place and start. ;; --- CONSTANTS : DESCRIBE PROPERTIES THAT ARE ALWAYS THE SAME (define HIGHT 400) (define WIDTH 600) (define EMPTY-WORLD-IMAGE (empty-scene WIDTH HIGHT)) (define SEGMENT-SIZE 10) (define SEGMENT-IMAGE (circle SEGMENT-SIZE 'solid 'red)) (define FOOD-SIZE 10) (define FOOD-IMAGE (circle FOOD-SIZE 'solid 'green)) (define worm01 (make-worm 'right (cons (make-posn 10 10) empty))) (define world0 (make-world worm01 (make-food 10 50))) ;; --- FUNCTIONS ;; world->image : World -> Image ;; turn a given world into an image (define (world->image w) (worm-add-to-image (world-worm w) (food-add-to-image (world-food w) EMPTY-WORLD-IMAGE))) ;; world->next : World -> World ;; move everything movable in the world (define (world-next w) (make-world (worm-move (world-worm w)) (world-food w))) ;; worm-add-to-image : Worm Image -> Image ;; add an image of the worm to the given image (define (worm-add-to-image wrm img) (segments-add-to-image (worm-seg wrm) img)) ;; worm-move : Worm -> Worm ;; move the worm by one step in the appropriate direction (define (worm-move w) (make-worm (worm-dir w) (segments-move (worm-seg w) (worm-dir w)))) ;; segments-add-to-image : Segments Image -> Image ;; add images for the worm segments to the given image (define (segments-add-to-image seg img) (cond [(empty? seg) img] [else (place-image SEGMENT-IMAGE (posn-x (first seg)) (posn-y (first seg)) (segments-add-to-image (rest seg) img))])) ;; segments-move : Segments Direction -> Segements (define (segments-move seg dir) (cons (segment-make-new (first seg) dir) (segments-all-but-last seg))) ;; Segements -> Segments ;; remove last segment (define (segments-all-but-last seg) (cond [(empty? (rest seg)) empty] [else (cons (first seg) (segments-all-but-last (rest seg)))])) ;; Posn Direction -> Posn ;; translate posn along desired axis (define (segment-make-new s dir) (cond [(symbol=? 'up dir) (make-posn (posn-x s) (- (posn-y s) SEGMENT-SIZE))] [(symbol=? 'down dir) (make-posn (posn-x s) (+ (posn-y s) SEGMENT-SIZE))] [(symbol=? 'left dir) (make-posn (- (posn-x s) SEGMENT-SIZE) (posn-y s))] [(symbol=? 'right dir) (make-posn (+ (posn-x s) SEGMENT-SIZE) (posn-y s))])) ;; food-add-to-image : Food Image -> Image ;; add image of food to the given image (define (food-add-to-image f img) (place-image FOOD-IMAGE (food-x f) (food-y f) img)) ;; --- TESTS (equal? (food-add-to-image (make-food 10 10) EMPTY-WORLD-IMAGE) (place-image FOOD-IMAGE 10 10 EMPTY-WORLD-IMAGE)) (equal? (segment-make-new (make-posn 10 10) 'up) (make-posn 10 0)) (equal? (segments-all-but-last (cons (make-posn 10 10) empty)) empty) (equal? (segments-move (cons (make-posn 10 10) empty) 'up) (cons (make-posn 10 0) empty)) (equal? (segments-add-to-image (cons (make-posn 10 10) empty) EMPTY-WORLD-IMAGE) (place-image SEGMENT-IMAGE 10 10 EMPTY-WORLD-IMAGE)) (equal? (worm-add-to-image worm01 EMPTY-WORLD-IMAGE) (place-image SEGMENT-IMAGE 10 10 EMPTY-WORLD-IMAGE)) (equal? (world->image world0) (place-image FOOD-IMAGE 10 50 (place-image SEGMENT-IMAGE 10 10 EMPTY-WORLD-IMAGE))) (equal? (world-next (make-world (make-worm 'up (cons (make-posn 10 10) empty)) (make-food 50 50))) (make-world (make-worm 'up (cons (make-posn 10 0) empty)) (make-food 50 50))) ;; --- RUN PROGRAM RUN (big-bang WIDTH HIGHT .05 world0) (on-redraw world->image) (on-tick-event world-next)