如何在Breakout(球拍)中将球与砖碰撞

时间:2017-12-30 19:55:49

标签: scheme lisp racket breakout racket-student-languages

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

以下是完整的代码:

(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)

球直接飞过砖块。我已将以下代码添加到其中:

;--------------------------------------------------------------------------------------------------
(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))))))

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

但似乎没有对任何事情产生影响。我现在被困住,并希望有任何改进的提示!

2 个答案:

答案 0 :(得分:0)

我在我的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)))))

这里球拍和球是一个&#34;身体&#34;,这是一个矩形 使用和(x,y)位置以及宽度,w和高度h。

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

注意:如果你的球碰巧移动的速度非常快,那么可能会发生跳过&#34;跳过&#34;桨。这可以通过具有最大速度来修复。

答案 1 :(得分:0)

你可能能够解决这个问题,而不是在另一个答案中遇到速度跳跃的一种方法是计算球当前行进的线与(可能是前面)的边界线的交点桨。然后,您只需确定此点是否实际位于球拍的线段和球的先前位置之间的线段以及它的假设位置,以确定是否会发生碰撞&#34;在&之间#34;框架和处理反射。更彻底的检查是对桨的边缘做同样的事情,因为那场比赛确实允许球拍从侧面击球。

示例计算:

#lang racket/base
(require racket/struct)
(struct line (a b c) #:transparent) ; ax+by=c
(struct pos (x y) #:transparent)
(define (meet l1 l2)
  (let-values (((a b c) (apply values (struct->list l1)))
               ((d e f) (apply values (struct->list l2))))
    (let ((denominator (- (* a e) (* b d))))
      (if (zero? denominator)
          'parallel ;probably impossible in your game
          (let ((x* (- (* c e) (* b f)))
                (y* (- (* a f) (* c d))))
            (pos (/ x* denominator)
                 (/ y* denominator)))))))