Please send questions to
st10@humboldt.edu .
; NOTE -- remember, all bird images below show up as . in this text version!
; CS 131 - Week 4, Lab, 10 am
(require 2htdp/universe)
(require 2htdp/image)
;----------
; defining your own struct type: the basic syntax and semantics
;
; (define-struct <struct-name> (<charac1> <charac2> ... <charac2>)
; creates a new struct type named <struct-name>,
; and a number of new functions:
; a constructor function, make-<struct-name>
; accessor/selector functions
; <struct-name>-<charac1>
; <struct-name>-<charac2>
; ...
; <struct-name>-<characn>
; a predicate function (to see if something is an instance
; of that type)
; <struct-name>?
; for example,
;(define-struct h-flier (image speed x y))
; I have a new struct type named h-flier that can be
; used in other functions (and in function signatures)
; I have make-h-flier to create instances of h-flier
; ...and h-flier-image gets me an h-flier's image,
; h-flier-speed gets me an h-flier's speed,
; h-flier-x gets me an h-flier's x,
; h-flier-y gets me an h-flier's y,
; ...and h-flier? can tell me if an expression is of type h-flier
; BUT!! a user can't tell the expected types of each struct
; characteristic, nor what it is intended to mean,
; JUST from the define-struct expression;
; we need some COMMENTS to FINISH the data definition
; for a struct type!
; Here's the CLASS STANDARD for such a data definition for a struct:
;----------
(define-struct h-flier (image speed x y))
; an h-flier is a:
; (make-h-flier image number number number)
; an h-flier has:
; an image depicting it,
; a speed in pixels per tick,
; if positive, it is pixels per tick going right,
; if negative, it is pixels per tick going left
; its current x-coordinate where its image is centered,
; and its current y-coordinate where its image is centered
; the template for a function uses-h-flier that expects
; an h-flier could be:
;
; (define (uses-h-flier an-h-flier)
; (... (h-flier-image an-h-flier)
; (h-flier-speed an-h-flier)
; (h-flier-x an-h-flier)
; (h-flier-y an-h-flier) ...)
; )
; the template for a function makes-h-flier that produces
; an h-flier could be:
; (notice that we put a ... for each expression the
; contructor function expects...)
;
; (define (makes-h-flier ...)
; (make-h-flier ... ... ... ...)
; )
(make-h-flier . 3 100 50)
(define FIRST-BIRD (make-h-flier . 3 100 50))
(h-flier-speed FIRST-BIRD)
(h-flier-image FIRST-BIRD)
(h-flier-x FIRST-BIRD)
(h-flier-y FIRST-BIRD)
(h-flier? FIRST-BIRD)
(h-flier? .)
;----------
; WHAT IF... big-bang's world type was an h-flier
; instead of a number?
; SO: big-bang's on-draw function would expect
; the name of a function that expects an h-flier and
; produces a scene
;
; ...its on-tick function would expect the name
; of a function that expects an h-flier, and produces
; the h-flier that should result 1 tick later
;
; ...its on-key function would expect the name
; of a function that expects an h-flier and a string
; representing a keystroke, and would produce
; the h-flier that should result from that keystroke
;
;----------
; I'm going to start with the function to give to
; big-bang's on-draw...
; signature: draw-h-flier: h-flier -> scene
; purpose: expects an h-flier, and produces a scene
; showing that h-flier's image centered at
; its x and y coordinates
(define WIDTH 300)
(define HEIGHT 200)
(define BACKDROP (empty-scene WIDTH HEIGHT))
; NOTE: REMEMBER, you write the check-expects BEFORE
; writing the function body!
; AND: in this case, after writing the check-expects,
; you can use the template for a function that expects an
; h-flier, and paste its body in here, and then edit it
; as suggested by your check-expects, being sure
; that THIS function's parameter(s) are being used
; appropriately in the result...!
; (we DID this in-class -- you are just seeing the final
; result here...)
(define (draw-h-flier an-h-flier)
(place-image (h-flier-image an-h-flier)
(h-flier-x an-h-flier)
(h-flier-y an-h-flier)
BACKDROP)
)
; reminder:
; (define FIRST-BIRD (make-h-flier . 3 100 50))
(check-expect (draw-h-flier FIRST-BIRD)
(place-image . 100 50 BACKDROP))
(check-expect (draw-h-flier
(make-h-flier (star 30 "solid" "purple")
-9 150 (/ HEIGHT 2)))
(place-image
(star 30 "solid" "purple")
150 (/ HEIGHT 2)
BACKDROP))
(draw-h-flier FIRST-BIRD)
(draw-h-flier (make-h-flier (star 30 "solid" "purple")
-9 150 (/ HEIGHT 2)))
;(big-bang FIRST-BIRD (on-draw draw-h-flier))
;(big-bang (make-h-flier (star 30 "solid" "purple")
; -9 150 (/ HEIGHT 2))
; (on-draw draw-h-flier))
;----------
; big-bang's on-key function expects a function that
; expects a world and a keystroke, and produces
; the resulting world
;----------
; DATA DEFINITION:
; an AltButton is a string, "u" or "d"
; this named constant defines the delta, or amount of
; altitude change, that should occur when "u" or "d"
; is pressed
(define ALT-DELTA 5)
;----------
; signature: handle-hf-keys: h-flier AltButton -> h-flier
; purpose: expects an h-flier and an AltButton keystroke,
; and produces a new h-flier whose y-coordinate (altitude) is:
; * ALT-DELTA smaller if "u" is pressed,
; * ALT-DELTA bigger if if "d" is pressed
; * unchanged if any other key is pressed
; (because in a scene, y is lower in the scene as y gets bigger)
; again: remember, you are seeing the final result here --
; in class, we followed the design recipe,
; first developing the check-expects,
; then using several templates to help develop the
; function body...
; (which? here, the template when a function has
; several cases, and (for several of the cond expression
; branch's actions) the template for a function
; that produces an h-flier and (!) the template for
; a function that produces an h-flier...
(define (handle-hf-keys an-h-flier a-key)
(cond
; make the new h-flier's altitude higher when "u" is pushed
; (requiring a smaller y...)
[(string=? a-key "u")
(make-h-flier
(h-flier-image an-h-flier)
(h-flier-speed an-h-flier)
(h-flier-x an-h-flier)
(- (h-flier-y an-h-flier) ALT-DELTA))]
; make the new h-flier's altitude lower when "d" is pushed
; (requiring a larger y...)
[(string=? a-key "d")
(make-h-flier
(h-flier-image an-h-flier)
(h-flier-speed an-h-flier)
(h-flier-x an-h-flier)
(+ (h-flier-y an-h-flier) ALT-DELTA))]
; for any other keystroke, produce an unchanged h-flier
[else an-h-flier]
)
)
; (define FIRST-BIRD (make-h-flier . 3 100 50))
(check-expect (handle-hf-keys FIRST-BIRD "u")
(make-h-flier .
3
100
45))
(check-expect (handle-hf-keys FIRST-BIRD "d")
(make-h-flier .
3
100
55))
(check-expect (handle-hf-keys FIRST-BIRD "x")
FIRST-BIRD)
;(big-bang FIRST-BIRD (on-draw draw-h-flier)
; (on-key handle-hf-keys))
;----------
; now: the function whose name can be given to big-bang's
; on-tick expression
; signature: move-h-flier: h-flier -> h-flier
; purpose: expects an h-flier, and produces the
; h-flier after the next clock tick, with
; the new h-flier's x changed by the amount of
; the speed
;(define (move-h-flier an-h-flier)
; ...
;)
;------------
; NEW STUFF STARTS HERE
;(define FIRST-BIRD (make-h-flier . 3 100 50))
(define LEFTY (make-h-flier (square 30 "solid" "yellow")
-5 90 40))
(define OUT-RIGHT (make-h-flier (circle 10 "solid" "black")
10 (+ WIDTH 3) 55))
(define OUT-LEFT (make-h-flier (star 25 "outline" "blue")
-7 -15 58))
; AUXILIARY FUNCTION!!!!
; signature: in-scene?: h-flier -> boolean
; purpose: expects an h-flier, and produces whether
; its x-coordinate in [0, WIDTH]
(define (in-scene? an-h-flier)
(and (>= (h-flier-x an-h-flier) 0)
(<= (h-flier-x an-h-flier) WIDTH))
)
(check-expect (in-scene? FIRST-BIRD) true)
(check-expect (in-scene? OUT-RIGHT) false)
(check-expect (in-scene? OUT-LEFT) false)
(check-expect (in-scene? (make-h-flier (circle 10 "solid" "black")
5 0 50))
true)
(check-expect (in-scene? (make-h-flier (circle 10 "solid" "black")
5 WIDTH 50))
true)
; case where flier is in the scene, going right
(check-expect (move-h-flier FIRST-BIRD)
(make-h-flier . 3 103 50))
; case where flier is in the scene, going left
(check-expect (move-h-flier LEFTY)
(make-h-flier (square 30 "solid" "yellow")
-5 85 40))
; IF an h-flier is OUT of the scene on the right and going
; right, THEN I want the new h-flier to have its
; speed reversed (negated) and its x to be the WIDTH
(check-expect (move-h-flier OUT-RIGHT)
(make-h-flier (circle 10 "solid" "black")
-10 WIDTH 55))
; and if it too far left going left, the new h-flier should
; have its speed reversed and its x to be 0
(check-expect (move-h-flier OUT-LEFT)
(make-h-flier (star 25 "outline" "blue")
7 0 58))
; 4 cases -- so I could start with a 4-case cond template...
(define (move-h-flier an-h-flier)
(cond
; flier is in the scene going either way
[(in-scene? an-h-flier)
(make-h-flier
(h-flier-image an-h-flier)
(h-flier-speed an-h-flier)
(+ (h-flier-x an-h-flier)
(h-flier-speed an-h-flier))
(h-flier-y an-h-flier))]
; flier is outside to the right going right
[(and (> (h-flier-speed an-h-flier) 0)
(> (h-flier-x an-h-flier) WIDTH))
(make-h-flier
(h-flier-image an-h-flier)
(* -1 (h-flier-speed an-h-flier))
WIDTH
(h-flier-y an-h-flier))]
; flier is outside to the left going left
[(and (< (h-flier-speed an-h-flier) 0)
(< (h-flier-x an-h-flier) 0))
(make-h-flier
(h-flier-image an-h-flier)
(* -1 (h-flier-speed an-h-flier))
0
(h-flier-y an-h-flier))]
)
)
(big-bang FIRST-BIRD
(on-draw draw-h-flier)
(on-key handle-hf-keys)
(on-tick move-h-flier))