scheme - 如何在 Breakout 中让球与砖 block 碰撞( Racket )

标签 scheme lisp racket breakout racket-student-languages

我一直在尝试让 Breakout 在 Racket 中工作,到目前为止,球从桨上弹起(桨由鼠标控制)并且砖 block 存在

完整代码如下:

(require 2htdp/image)
(require 2htdp/universe)

(define WIDTH 400)
(define HEIGHT 400)
(define BALL-RADIUS 10)
(define BALL-IMG (circle BALL-RADIUS "solid" "red"))

(define REC-WIDTH 50)
(define REC-HEIGHT 10)
(define REC-IMG (rectangle REC-WIDTH REC-HEIGHT "solid" "grey"))

(define BRICK-IMG0 (rectangle 60 30 "solid" "blue"))
(define BRICK-IMG1 (rectangle 60 30 "solid" "green"))

(define SCENE (empty-scene WIDTH HEIGHT))

(define STARTGAME
  (text "CLICK TO START" 60 "purple"))

(define GAMEOVER
 (text "GAMEOVER" 60 "red"))

(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-struct rec (pos))
;
;

(define-struct brick (pos))
;
;

; 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
(check-expect (move-ball (make-ball (make-posn 20 30)
                                    (make-vel 5 10)))
              (make-ball (make-posn 25 40)
                         (make-vel 5 10)))
(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"
; - "none"
; interp. the location where a ball collides with a wall

; Posn -> Collision
; detects with which of the bricks the ball collides
;(check-expect (collision (make-posn 0 12))  "left")
;(check-expect (collision (make-posn 15 HEIGHT)) "down")
;(check-expect (collision (make-posn WIDTH 12))  "right")
;(check-expect (collision (make-posn 15 0)) "top")
;(check-expect (collision (make-posn 55 55)) "none")

(define (collision ball rec)
  (cond
    [(<= (posn-x ball) BALL-RADIUS) "left"]
    [(<= (posn-y ball) BALL-RADIUS)  "top"]
    [(>= (posn-x ball) (- WIDTH BALL-RADIUS)) "right"]
    [(>= (posn-y ball) (- HEIGHT BALL-RADIUS)) "GAMEOVER"]
    [(and (>= (posn-x ball) (- (posn-x (rec-pos rec)) (/ REC-WIDTH 2)))
          (<= (posn-x ball) (+ (posn-x (rec-pos rec)) (/ REC-WIDTH 2)))
          (= (posn-y ball) (posn-y (rec-pos rec)))) "down"]
    [else "none"]))




; Vel Collision -> Vel  
; computes the velocity of an object after a collision
(check-expect (bounce (make-vel 3 4) "left")
              (make-vel -3 4))
(check-expect (bounce (make-vel 3 4) "top")
              (make-vel 3 -4))
(check-expect (bounce (make-vel 3 4) "none")
              (make-vel 3 4))

(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 "down")
             (string=? collision "top"))
         (make-vel (vel-delta-x vel)
                   (- (vel-delta-y vel)))]
        [else vel]))


; WorldState is a Ball
; interp. the current state of the ball

; WorldState -> Image
; renders ball at its position
;(check-expect (image? (render INITIAL-BALL)) #true)
(define (render a-world)
  (draw-ball (world-ball a-world)
             (draw-bricklist (world-bricks a-world)
                             (draw-rect (world-rec a-world)))))


(define (draw-ball ball img)
  (place-image BALL-IMG
               (posn-x (ball-loc ball))
               (posn-y (ball-loc ball))
               img))

(define (draw-rect rec)
  (place-image REC-IMG
               (posn-x (rec-pos rec))
               (posn-y (rec-pos rec))
                SCENE))


(define (draw-bricklist list img)
  [cond ((empty? list) img)
        ((cons? list) (draw-bricklist (rest list) (draw-brick (first list) img)))])

(define (draw-brick brick image) 
  (place-image (choice BRICK-IMG0 BRICK-IMG1)
               (posn-x (brick-pos brick))
               (posn-y (brick-pos brick))
               image))


(define (choice a b )
  (if (zero? (random 1)) a b ))

; WorldState -> WorldState
; moves ball to its next location
;(check-expect (tick (make-ball (make-posn 20 12) (make-vel 1 2)))
;              (make-ball (make-posn 21 14) (make-vel 1 2)))
;(define (tick ball)
;  (move-ball (make-ball (ball-loc ball)
;                        (bounce (ball-velocity ball)
;                                (collision (ball-loc ball))))))

(define (tick world)
  (make-world (move-ball (make-ball (ball-loc (world-ball world))
                                    (bounce (ball-velocity (world-ball world))
                                            (collision (ball-loc (world-ball world))
                                                       (world-rec world)))))
  (world-rec world)
  (world-bricks world)))



(define (mouse world mouse-x mouse-y mouse-event)
  (cond
    [(string=? mouse-event "move") (make-world (world-ball world)
                                               (make-rec (make-posn mouse-x REC-Y-POS))
                                               (world-bricks world))]
    [else world]))



(define INITIAL-BALL (make-ball (make-posn 20 12)
                                (make-vel 1 2)))

(define REC-Y-POS (- HEIGHT (+ 20 REC-HEIGHT)))
(define INITIAL-REC (make-rec (make-posn 100 REC-Y-POS)))
(define INITIAL-BRICKS (list
                        (make-brick (make-posn 50 100))
                        (make-brick (make-posn 111 100))           
                        (make-brick (make-posn 172 100))
                        (make-brick (make-posn 233 100))
                        (make-brick (make-posn 294 100))
                        (make-brick (make-posn 355 100))
                        (make-brick (make-posn 50 131))
                        (make-brick (make-posn 111 131))           
                        (make-brick (make-posn 172 131))
                        (make-brick (make-posn 233 131))
                        (make-brick (make-posn 294 131))
                        (make-brick (make-posn 355 131))
                        (make-brick (make-posn 50 162))
                        (make-brick (make-posn 111 162))           
                        (make-brick (make-posn 172 162))
                        (make-brick (make-posn 233 162))
                        (make-brick (make-posn 294 162))
                        (make-brick (make-posn 355 162))))






(define-struct world (ball rec bricks))

(define INITIAL-WORLD-STATE (make-world INITIAL-BALL INITIAL-REC INITIAL-BRICKS))

(define (main state)
  (big-bang state (on-mouse mouse) (on-tick tick 0.01) (to-draw render)))

(main INITIAL-WORLD-STATE)

球直接穿过砖 block 。我向其中添加了以下代码:

;--------------------------------------------------------------------------------------------------
(define (overlap?
          brick-one-x brick-one-y brick-one-width brick-one-height
          brick-two-x brick-two-y brick-two-width brick-two-height)
          (cond
            [(and
                (and
                 (>= (+ brick-one-x brick-one-width) brick-two-x); within right bounds
                 (<= brick-one-x (+ brick-two-x brick-two-width)); within left bounds
                )
                (and
                 (>= (+ brick-one-y brick-one-height) brick-two-y) ;within top bounds
                 (<= brick-one-y (+ brick-two-y brick-two-height)) ; within bottom bounds
                ))
                #t]
             [else ;not overlapping
                #f]))



(define (brick-collide-ball? brick ball)
  (if
    (overlap?
       ;balls dimensions and location
        (posn-x (ball-loc ball))
        (posn-y (ball-loc ball))
        10
        10
     ;first brick in list
        (posn-x (brick-pos brick))
        (- (posn-y (brick-pos brick)) 10)
        60
        30)
         #t 
         #f))

(define (delete-bricks bricklist ball)
  (cond
    [(empty? bricklist) empty]
     ((cons? bricklist)
      (if (brick-collide-ball? (first bricklist) ball)
          (delete-bricks (rest bricklist) ball)
          (cons (first bricklist)(delete-bricks (rest bricklist) ball))))))

;--------------------------------------------------------------------------------------------------------

但似乎并没有对任何事情产生影响。我现在被困住了,如果有任何改进建议,我将不胜感激!

最佳答案

我在我的 Atari 经典版本中使用了以下内容:

(define (colliding? b1 b2)
  (match-define (body x1 y1 w1 h1) b1)
  (match-define (body x2 y2 w2 h2) b2)
  (not (or (eq? b1 b2)
           (< (+ x1 w1) x2) (> x1 (+ x2 w2))
           (< (+ y1 h1) y2) (> y1 (+ y2 h2)))))

这里 Racket 和球都是一个“ body ”,是一个长方形 具有 (x,y) 位置和宽度 w 以及高度 h。

(struct body (x y w h) #:transparent)

注意:如果您的球碰巧移动得非常快,它可能会“跳过” Racket 。这可以通过设置最大速度来解决。

关于scheme - 如何在 Breakout 中让球与砖 block 碰撞( Racket ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48037371/

相关文章:

scheme - 有关于 "yin-yang puzzle"的详细历史背景吗?

scheme - 在Scheme中将AND与apply函数一起使用

floating-point - 方案中的浮点精度和去除舍入误差

lisp - 元素未添加到列表

arrays - Racket:宏输出一些奇怪的东西而不是数组

lisp - Scheme(plt-scheme)中关于 "If.."

scheme - 学习载体

macros - 宏想在 clojure 中使用符号而不是字符串

compiler-errors - Lisp 非法函数调用,

settings - 如何在 DrRacket 中将方括号键盘键更改为括号?