如何用Pygame使球从墙上弹起? [英] How to make ball bounce off wall with Pygame?

查看:57
本文介绍了如何用Pygame使球从墙上弹起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在您批评我没有进行谷歌搜索或在询问之前进行研究之前,我先进行了 研究但无济于事.

我正在尝试创建Atari Breakout游戏.我目前停留在使球弹起墙壁的部分上.我对此进行了研究,发现了很多博客和YouTube视频(还有Stackoverflow

  box = Circle(600,300,10)运行=真开始=假时钟= pygame.time.Clock()运行时:clock.tick(120)对于pygame.event.get()中的事件:如果event.type == pygame.QUIT:运行=错误键= pygame.key.get_pressed()如果键[pygame.K_SPACE]:开始=真界限= pygame.Rect(450,200,300,200)如果开始:box.y-= box.vel_ybox.x + = box.vel_x如果box.x-box.radius<bounds.left或box.x + box.radius>bounds.right:box.vel_x * = -1如果box.y-box.radius<bounds.top或box.y + box.radius>bounds.bottom:box.vel_y * = -1window.fill((0,0,0))pygame.draw.rect(窗口,(255,0,0),bounds,1)pygame.draw.circle(窗口,(44,176,55),(box.x,box.y),box.radius)pygame.display.update() 

Before you criticize me for not googling or do research before asking, I did research beforehand but to no avail.

I am trying to create the Atari Breakout game. I am currently stucked at the part to make the ball bounce off walls. I did research on this and I found a lot of blogs and youtube videos (and also Stackoverflow this and this) talking about pygame's vector2 class. I also read the pygame documentation on vector2 but I can't figure out how to make it work.

I am currently writing a script to make the ball bounce off walls. In the beginning, the player is requested to press the spacebar and the ball will automatically move towards the north-east direction. It should bounce off the top wall when it hits it but instead, it went inside. This is my approach:

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

I guess the problem is where I marked. Which is here:

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

but I don't know why. My theory is: the ball travels upwards, it hit the top wall, check_hit() kicks in and make hit = True, then the vel_x and vel_y is changed accordingly (if hit top wall, vel_x should remain the same while vel_y should be multiplied by -1). Then it will move down, hence "bounce" off the top wall.

Note: for now I only have the top wall working. The other three will be done when I can figure out how to bounce off the top wall first.

Can you help me see what's the problem? And if this kind of operation requires the use of the vector2 class, can you explain it to me or give me a place to learn it?

Thank you.

解决方案

The issue are the multiple nested loops. You have an application loop, so use it.
Continuously move the ball in the loop:

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

Define a rectangular region for the ball by a pygame.Rect object:

bounds = window.get_rect() # full screen

or

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

Change the direction of movement when the ball hits the bounds:

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 

See the example:

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

这篇关于如何用Pygame使球从墙上弹起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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