#| Design a program that moves a colored ball back and forth across the canvas. It should not start until the "player" presses any ket and it should pause when the "player" presses a key again. |# ;; STEP 1: global constants (define RADIUS 150) (define SPEED (quotient RADIUS 5)) (define BALL (circle RADIUS "solid" "red")) (define WIDTH (* 8 RADIUS)) (define MID RADIUS) (define BACKGROUND (empty-scene WIDTH (* 2 RADIUS))) (define TXT (text "press any key" 33 "black")) ;; STEP 2: data definitions that represent the varying parts of the state (define-struct running (x dir)) (define-struct resting (x dir)) ;; SG is one of: ;; -- "press any key" ;; -- (make-resting Number Direction) ;; -- (make-running Number Direction) ;; interpretation: "press any key" means the game hasn't started, ;; (make-resting x d) means the ball is resting and will move in ;; direction d when restarted, and ;; (make-running x d) means the ball is at x moving in d ;; Direction is one of: ;; -- -1 ;; -- +1 ;; interpretation: -1 means right to left, +1 is left to right ;; STEP 4: the "main" function ;; Anything -> State (define (stop-and-go _) (big-bang "press any key" [to-draw render-ball] [on-tick next-ball] [on-key start-pause])) ;; STEP 3: the wish list, implemented and finished ;; SG -> Image ;; render the current stop-and-go state as an image (define (render-ball s) (cond [(string? s) (place-image TXT (image-width TXT) MID BACKGROUND)] [(resting? s) (place-image BALL (resting-x s) MID BACKGROUND)] [(running? s) (place-image BALL (running-x s) MID BACKGROUND)])) ;; SG KeyEvent -> SG ;; start or pause or re-start ball (define (start-pause s k) (cond [(string? s) (make-running 1 +1)] [(resting? s) (make-running (resting-x s) (resting-dir s))] [(running? s) (make-resting (running-x s) (running-dir s))])) ;; SG -> SG ;; move a running ball in the appropriate direction or flip it, ;; leave others alone (define (next-ball s) (cond [(string? s) s] [(resting? s) s] [(running? s) (if (<= 0 (running-x s) WIDTH) (move-ball s) (flip-direction s))])) ;; ------------------------------------------------------------- ;; students can design these functions on their own ;; MB is (make-running X D) ;; MB -> MB ;; move a running ball in the appropriate direction (define (move-ball s) (make-running ;; This is tricky. Programmer vs Program designer. (+ (running-x s) (* (running-dir s) SPEED)) (running-dir s))) ;; MB -> MB ;; flip a ball's direction when it went beyond one of the boundaries (define (flip-direction s) (cond [(<= (running-x s) 0) (make-running 0 +1)] [(>= (running-x s) WIDTH) (make-running WIDTH -1)]))