【问题标题】:How to make ball bounce off wall with PyGame?如何用 PyGame 让球从墙上反弹?
【发布时间】:2021-05-31 09:44:58
【问题描述】:

在您批评我没有在询问之前使用 Google 搜索或进行研究之前,我事先进行了研究但无济于事。

我正在尝试创建 Atari Breakout 游戏。我目前坚持让球从墙上反弹。我对此进行了研究,发现很多博客和 YouTube 视频(以及 Stack Overflow 问题:thisthis)都在谈论 PyGame 的 vector2 类。我还阅读了有关 vector2 的 PyGame 文档,但我不知道如何使它工作。

我目前正在编写一个脚本来让球从墙上反弹。一开始,要求玩家按下空格键,球会自动向东北方向移动。当它撞到它时,它应该从顶墙上反弹,但相反,它进入了里面。这是我的方法:

import pygame
pygame.init()

screenWidth = 1200
screenHeight = 700

window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')

class Circle():

    def __init__(self, x, y, radius):
        self.x = x
        self.y = y
        self.radius = radius
        self.vel_x = 1
        self.vel_y = 1


def check_hit():
    global hit
    if (((screenWidth-box.x)<=box.radius) or ((box.x)<=box.radius) or ((box.y)<=box.radius) or ((screenHeight-box.y)<=box.radius)):
        # meaning  hit either four walls
        if (((screenWidth-box.x)<=box.radius) or ((box.x)<=box.radius)):
            # hit right, left
            print('hit right, left')
            hit = True
        elif (((box.y)<=box.radius) or ((screenHeight-box.y)<=box.radius)):
            # hit top, bottom
            print('hit top, bottom')
            hit = True
            

# main loop
run = True
box = Circle(600,300,10)
hit = False
                                                  # (screenWidth-box.x)<=box.radius     hit right wall
while run:                                        # (box.x)<=box.radius                 hit left wall
                                                  # (box.y)<=box.radius                 hit top wall                        
    pygame.time.Clock().tick(60)                  # (screenHeight-box.y)<=box.radius    hit bottom wall

    for event in pygame.event.get():
        if event == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE] and (box.y)>box.radius:
        while True:
            box.y -= box.vel_y        
            box.x += box.vel_x

            window.fill((0,0,0))
            pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
            pygame.display.update()

            check_hit()
            if hit == False:
                continue
            elif hit == True:
                break

        if (box.y)<=box.radius or (screenHeight-box.y)<=box.radius:
            # hit top, bottom
            box.vel_x *= 1
            box.vel_y *= -1
            print('changed')

            if (box.y)<=box.radius:
                # hit top
                print('hi')
                while True:
                    box.x += box.vel_x               # <-- myguess is this is the problem
                    box.y += box.vel_y


                    window.fill((0,0,0))
                    pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
                    pygame.display.update()
                



        elif (screenWidth-box.x)<=box.radius or (box.x)<=box.radius:
            # hit right, left
            box.vel_x *= -1
            box.vel_y *= 1






    window.fill((0,0,0))
    pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
    pygame.display.update()


    print('Where are you going')

pygame.quit()

我想问题出在我标记的地方。这是这里:

        if (box.y)<=box.radius or (screenHeight-box.y)<=box.radius:
            # hit top, bottom
            box.vel_x *= 1
            box.vel_y *= -1
            print('changed')

            if (box.y)<=box.radius:
                # hit top
                print('hi')
                while True:
                    box.x += box.vel_x               # <-- myguess is this is the problem
                    box.y += box.vel_y


                    window.fill((0,0,0))
                    pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
                    pygame.display.update()

但我不知道为什么。我的理论是:球向上运动,它撞到顶壁,check_hit() 踢进来并使hit = True,然后 vel_xvel_y 相应地改变(如果撞到顶壁,vel_x 应该保持不变,而 vel_y 应乘以 -1)。然后它会向下移动,因此会从顶墙上“反弹”。

注意:目前我只有顶墙在工作。等我弄清楚如何先从顶墙上反弹后,其他三个就完成了。

你能帮我看看有什么问题吗?而如果这种操作需要用到vector2类,能不能给我解释一下,或者给我一个学习的地方?

【问题讨论】:

  • 为什么你的 if 语句中有这么多括号?
  • 我认为它看起来会更好,哈哈。原来是一团糟
  • 还有,if ... == True: --> if ... :.

标签: python pygame collision-detection python-3.8


【解决方案1】:

问题在于多个嵌套循环。您有一个应用程序循环,因此请使用它。
在循环中连续移动球:

box.y -= box.vel_y        
box.x += box.vel_x

通过pygame.Rect 对象为球定义一个矩形区域:

bounds = window.get_rect() # full screen

bounds = pygame.Rect(450, 200, 300, 200)  # rectangular region

球出界时改变运动方向:

if box.x - box.radius < bounds.left or box.x + box.radius > bounds.right:
    box.vel_x *= -1 
if box.y - box.radius < bounds.top or box.y + box.radius > bounds.bottom:
    box.vel_y *= -1 

看例子:

box = Circle(600,300,10)

run = True
start = False
clock = pygame.time.Clock()

while run:                     
    clock.tick(120)  

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_SPACE]:
        start = True

    bounds = pygame.Rect(450, 200, 300, 200)
    if start:
        box.y -= box.vel_y        
        box.x += box.vel_x

        if box.x - box.radius < bounds.left or box.x + box.radius > bounds.right:
            box.vel_x *= -1 
        if box.y - box.radius < bounds.top or box.y + box.radius > bounds.bottom:
            box.vel_y *= -1 

    window.fill((0,0,0))
    pygame.draw.rect(window, (255, 0, 0), bounds, 1)
    pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
    pygame.display.update()

【讨论】:

  • 什么时候可以使用.top.bottom等方法?
  • .top .bottom 是虚拟属性。见pygame.Rect。您每次都可以在pygame.Rect 的任何实例上使用它们。
猜你喜欢
  • 2013-11-30
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多