BSL 中的编程突破
Programming Breakout in BSL
我目前正尝试在 BSL 中编码 'Breakout' 但我卡住了
不知道如何在我的代码中添加欢迎和游戏结束屏幕。这是
假设游戏从欢迎屏幕开始,当它是
用鼠标在屏幕上单击实际游戏应该开始。什么时候
球与屏幕的下边缘相撞屏幕游戏结束
应该出现。
感谢您提供的任何提示!
(define WIDTH 200)
(define HEIGHT 200)
(define BALL-RADIUS 10)
(define BALL-IMG (circle BALL-RADIUS "solid" "red"))
(define MT (empty-scene WIDTH HEIGHT))
(define GAME-OVER
(place-image (text "Game-over" 30 "black")
100 100
MT))
(define WELCOME
(place-image (text "Welcome" 30 "black")
100 100
MT))
(define-struct vel (delta-x delta-y))
; a Vel is a structure: (make-vel Number Number)
; interp. the velocity vector of a moving object
(define-struct ball (loc velocity))
; a Ball is a structure: (make-ball Posn Vel)
; interp. the position and velocity of a object
(define RACKET (rectangle 30 10 "solid" "grey"))
(define-struct world-state (ball racket))
; A WorldState is a structure. (make-world-state Ball Location of
Racket)
; interp. current velocity and location of ball, current location of
racket
; Posn Vel -> Posn
; applies q to p and simulates the movement in one clock tick
(check-expect (posn+vel (make-posn 5 6) (make-vel 1 2))
(make-posn 6 8))
(define (posn+vel p q)
(make-posn (+ (posn-x p) (vel-delta-x q))
(+ (posn-y p) (vel-delta-y q))))
; Ball -> Ball
; computes movement of ball in one clock tick
(define (move-ball ball)
(make-ball (posn+vel (ball-loc ball)
(ball-velocity ball))
(ball-velocity ball)))
; A Collision is either
; - "top"
; - "down"
; - "left"
; - "right"
; - "racket"
; - "none"
; interp. the location where a ball collides with a wall
; Posn -> Collision
; detects with which of the walls (if any) or the racket the ball
collides
(define (collision world-state)
(cond
[(<= (posn-x (ball-loc (world-state-ball world-state))) BALL-
RADIUS) "left"]
[(<= (posn-y (ball-loc (world-state-ball world-state))) BALL-
RADIUS) "top"]
[(>= (posn-x (ball-loc (world-state-ball world-state))) (- WIDTH
BALL-RADIUS)) "right"]
[(>= (posn-y (ball-loc (world-state-ball world-state))) (- HEIGHT
BALL-RADIUS)) "down"]
[(and (>= (posn-y (ball-loc (world-state-ball world-state))) (-
HEIGHT BALL-RADIUS 10))
(<= (- (posn-x (world-state-racket world-state)) 15)
(posn-x (world-state-racket world-state))
(+ (posn-x (world-state-racket world-state)) 15)))
"racket"]
[else "none"]))
; Vel Collision -> Vel
; computes the velocity of an object after a collision
(define (bounce vel collision)
(cond [(or (string=? collision "left")
(string=? collision "right"))
(make-vel (- (vel-delta-x vel))
(vel-delta-y vel))]
[(or (string=? collision "top")
(string=? collision "racket"))
(make-vel (vel-delta-x vel)
(- (vel-delta-y vel)))]
[else vel]))
; render
; WorldState -> Image
; renders ball and
racket at their position
(check-expect (image? (render INITIAL-STATE)) #true)
(define (render world-state)
(place-image BALL-IMG
(posn-x (ball-loc (world-state-ball world-state)))
(posn-y (ball-loc (world-state-ball world-state)))
(place-image RACKET
(posn-x (world-state-racket world-state))
195
(empty-scene WIDTH HEIGHT))))
;tick
; WorldState -> WorldState
; moves ball to its next location
(check-expect (tick INITIAL-STATE) (make-world-state (make-ball (make-posn 21 14) (make-vel 1 2)) (make-posn 20 195)))
(define (tick world-state)
(make-world-state (move-ball (make-ball (ball-loc (world-state-ball world-state))
(bounce (ball-velocity (world-state-ball world-state))
(collision world-state))))
(world-state-racket world-state)))
; A Location is a structure: (make-posn Number Number)
; interp. x and y coordinate of a location on screen.
(define Loc (make-posn 1 1))
; A MouseEvent is one of
; - "button-down"
; - "button-up"
; - "drag"
; - "move"
; - "enter"
; - "leave"
; interp. mouse events, e.g., mouse movements or mouse clicks
(define MOUSE-CLICK "button-down")
; mouse
;
; Game Number Number MouseEvent -> WorldState
; Update position of racket when the mouse moves
;mouse-template
(define (mouse-template world-state mouse-loc-x mouse-loc-y MouseEvent)
(cond
((string=? MouseEvent "button-down")...)
((string=? MouseEvent "button-up")...)
((string=? MouseEvent "drag")...)
((string=? MouseEvent "move")...)
((string=? MouseEvent "enter")...)
((string=? MouseEvent "leave")...)
(else ...)))
(define (mouse world-state mouse-loc-x mouse-loc-y MouseEvent)
(cond
[(and (string=? MouseEvent "move")
(>= mouse-loc-y 180))
(make-world-state (world-state-ball world-state)
(make-posn mouse-loc-x 195))]
[else world-state]))
(define INITIAL-BALL (make-ball (make-posn 20 12)
(make-vel 1 2)))
(define INITIAL-RACKET (make-posn 20 195))
(define INITIAL-STATE (make-world-state INITIAL-BALL INITIAL-RACKET))
; WorldState -> WorldState
; Starts the game
(define (main state)
(big-bang state
(on-tick tick 0.01)
(to-draw render)
(on-mouse mouse)))
; start with INITIAL-STATE
您现在拥有三种不同的状态:
- 欢迎
- 正在播放
- 游戏结束
到目前为止你只有 "playing" 并且你使用你的世界结构来表示它。
现在您需要引入两个新结构:欢迎和游戏结束。
重命名您的旧渲染函数 render-world
(或 render-playing
)。
然后这样写:
(define (render w)
(cond
[(welcome? w) (render-welcome w)]
[(world? w) (render-world w)]
[(game-over? w) (render-game-over w)]))
当然你的初始状态应该变成welcome的实例,你还需要三个不同的tick函数。
我目前正尝试在 BSL 中编码 'Breakout' 但我卡住了 不知道如何在我的代码中添加欢迎和游戏结束屏幕。这是 假设游戏从欢迎屏幕开始,当它是 用鼠标在屏幕上单击实际游戏应该开始。什么时候 球与屏幕的下边缘相撞屏幕游戏结束 应该出现。 感谢您提供的任何提示!
(define WIDTH 200)
(define HEIGHT 200)
(define BALL-RADIUS 10)
(define BALL-IMG (circle BALL-RADIUS "solid" "red"))
(define MT (empty-scene WIDTH HEIGHT))
(define GAME-OVER
(place-image (text "Game-over" 30 "black")
100 100
MT))
(define WELCOME
(place-image (text "Welcome" 30 "black")
100 100
MT))
(define-struct vel (delta-x delta-y))
; a Vel is a structure: (make-vel Number Number)
; interp. the velocity vector of a moving object
(define-struct ball (loc velocity))
; a Ball is a structure: (make-ball Posn Vel)
; interp. the position and velocity of a object
(define RACKET (rectangle 30 10 "solid" "grey"))
(define-struct world-state (ball racket))
; A WorldState is a structure. (make-world-state Ball Location of
Racket)
; interp. current velocity and location of ball, current location of
racket
; Posn Vel -> Posn
; applies q to p and simulates the movement in one clock tick
(check-expect (posn+vel (make-posn 5 6) (make-vel 1 2))
(make-posn 6 8))
(define (posn+vel p q)
(make-posn (+ (posn-x p) (vel-delta-x q))
(+ (posn-y p) (vel-delta-y q))))
; Ball -> Ball
; computes movement of ball in one clock tick
(define (move-ball ball)
(make-ball (posn+vel (ball-loc ball)
(ball-velocity ball))
(ball-velocity ball)))
; A Collision is either
; - "top"
; - "down"
; - "left"
; - "right"
; - "racket"
; - "none"
; interp. the location where a ball collides with a wall
; Posn -> Collision
; detects with which of the walls (if any) or the racket the ball
collides
(define (collision world-state)
(cond
[(<= (posn-x (ball-loc (world-state-ball world-state))) BALL-
RADIUS) "left"]
[(<= (posn-y (ball-loc (world-state-ball world-state))) BALL-
RADIUS) "top"]
[(>= (posn-x (ball-loc (world-state-ball world-state))) (- WIDTH
BALL-RADIUS)) "right"]
[(>= (posn-y (ball-loc (world-state-ball world-state))) (- HEIGHT
BALL-RADIUS)) "down"]
[(and (>= (posn-y (ball-loc (world-state-ball world-state))) (-
HEIGHT BALL-RADIUS 10))
(<= (- (posn-x (world-state-racket world-state)) 15)
(posn-x (world-state-racket world-state))
(+ (posn-x (world-state-racket world-state)) 15)))
"racket"]
[else "none"]))
; Vel Collision -> Vel
; computes the velocity of an object after a collision
(define (bounce vel collision)
(cond [(or (string=? collision "left")
(string=? collision "right"))
(make-vel (- (vel-delta-x vel))
(vel-delta-y vel))]
[(or (string=? collision "top")
(string=? collision "racket"))
(make-vel (vel-delta-x vel)
(- (vel-delta-y vel)))]
[else vel]))
; render
; WorldState -> Image
; renders ball and
racket at their position
(check-expect (image? (render INITIAL-STATE)) #true)
(define (render world-state)
(place-image BALL-IMG
(posn-x (ball-loc (world-state-ball world-state)))
(posn-y (ball-loc (world-state-ball world-state)))
(place-image RACKET
(posn-x (world-state-racket world-state))
195
(empty-scene WIDTH HEIGHT))))
;tick
; WorldState -> WorldState
; moves ball to its next location
(check-expect (tick INITIAL-STATE) (make-world-state (make-ball (make-posn 21 14) (make-vel 1 2)) (make-posn 20 195)))
(define (tick world-state)
(make-world-state (move-ball (make-ball (ball-loc (world-state-ball world-state))
(bounce (ball-velocity (world-state-ball world-state))
(collision world-state))))
(world-state-racket world-state)))
; A Location is a structure: (make-posn Number Number)
; interp. x and y coordinate of a location on screen.
(define Loc (make-posn 1 1))
; A MouseEvent is one of
; - "button-down"
; - "button-up"
; - "drag"
; - "move"
; - "enter"
; - "leave"
; interp. mouse events, e.g., mouse movements or mouse clicks
(define MOUSE-CLICK "button-down")
; mouse
;
; Game Number Number MouseEvent -> WorldState
; Update position of racket when the mouse moves
;mouse-template
(define (mouse-template world-state mouse-loc-x mouse-loc-y MouseEvent)
(cond
((string=? MouseEvent "button-down")...)
((string=? MouseEvent "button-up")...)
((string=? MouseEvent "drag")...)
((string=? MouseEvent "move")...)
((string=? MouseEvent "enter")...)
((string=? MouseEvent "leave")...)
(else ...)))
(define (mouse world-state mouse-loc-x mouse-loc-y MouseEvent)
(cond
[(and (string=? MouseEvent "move")
(>= mouse-loc-y 180))
(make-world-state (world-state-ball world-state)
(make-posn mouse-loc-x 195))]
[else world-state]))
(define INITIAL-BALL (make-ball (make-posn 20 12)
(make-vel 1 2)))
(define INITIAL-RACKET (make-posn 20 195))
(define INITIAL-STATE (make-world-state INITIAL-BALL INITIAL-RACKET))
; WorldState -> WorldState
; Starts the game
(define (main state)
(big-bang state
(on-tick tick 0.01)
(to-draw render)
(on-mouse mouse)))
; start with INITIAL-STATE
您现在拥有三种不同的状态:
- 欢迎
- 正在播放
- 游戏结束
到目前为止你只有 "playing" 并且你使用你的世界结构来表示它。
现在您需要引入两个新结构:欢迎和游戏结束。
重命名您的旧渲染函数 render-world
(或 render-playing
)。
然后这样写:
(define (render w)
(cond
[(welcome? w) (render-welcome w)]
[(world? w) (render-world w)]
[(game-over? w) (render-game-over w)]))
当然你的初始状态应该变成welcome的实例,你还需要三个不同的tick函数。