如何在Breakout(球拍)中使球与砖块相撞 [英] How to have ball collide with bricks in Breakout (racket)

查看:76
本文介绍了如何在Breakout(球拍)中使球与砖块相撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been trying to get Breakout to work in Racket, so far the ball bounces from the paddle (paddle is controlled by mouse) and the bricks are present

以下是完整的代码:

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

舞会直接飞过砖头.我已将以下代码添加到其中:

The Ball just flies straight through the bricks. I've added this following code to it:

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

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

,但似乎对任何事物都没有影响.我现在被困住了,不胜感激任何改进的提示!

but it does not seem to make an impact on anything. I'm stuck now and would appreciate any tips to improve!

推荐答案

您可能能够解决这个问题而又不陷入速度跳跃的另一种方法是计算球沿其直线的交点当前正在行驶,并且桨的边界线(大概是桨的前部).然后,您只需确定该点实际上是否在桨的线段上以及球的先前位置与假设位置之间的线段上,即可确定在框架之间"是否会发生碰撞并处理该反射.更彻底的检查是对桨的边缘执行相同的操作,因为该游戏确实允许桨从侧面击球.

One way you might be able to address this problem without falling into a velocity-jump in the other answer is to calculate the intersection of the line along which the ball is currently traveling and the bounding line of (presumably the front of) the paddle. Then you just determine if this point is actually on the line segment of the paddle and the line segment between the ball's previous position and it's hypothetical position to determine if a collision would have happened "between" frames and handle that reflection. A more thorough check would be to do the same thing with the edge of the paddle since that game did allow the paddle to hit the ball from the side.

计算示例:

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

这篇关于如何在Breakout(球拍)中使球与砖块相撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆