如何用 PyGame 让球从墙上弹起?

2025-02-08 08:52:00
admin
原创
48
摘要:问题描述:在您批评我提问之前没有先进行 Google 搜索或做研究之前,我事先已经做过研究,但无济于事。我正在尝试创建 Atari Breakout 游戏。目前我被困在让球从墙上弹起的问题上。我对此进行了研究,发现很多博客和 YouTube 视频(以及 Stack Overflow 问题:这个和这个)都在谈论...

问题描述:

在您批评我提问之前没有先进行 Google 搜索或做研究之前,我事先已经做过研究,但无济于事。

我正在尝试创建 Atari Breakout 游戏。目前我被困在让球从墙上弹起的问题上。我对此进行了研究,发现很多博客和 YouTube 视频(以及 Stack Overflow 问题:这个和这个)都在谈论 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 类,你能给我解释一下吗,或者给我一个学习它的地方吗?


解决方案 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 

请看示例:

IT科技

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()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用