如何反转矩形的运动方向?

1 投票
3 回答
1921 浏览
提问于 2025-04-15 11:14

我刚开始学习编程,学校刚刚把这个科目引入,我需要一些帮助。我被分配了一个任务,要让三个球(矩形图片)在屏幕上弹跳并相互碰撞。我已经把三个球和墙壁的弹跳做得很好了,但我不知道怎么让它们互相弹来弹去。任何帮助都非常感谢,我现在的代码如下:

import pygame
import random
import sys

if __name__ =='__main__':

    ball_image1 = 'beachball1.jpg'
    ball_image2 = 'beachball2.jpg'
    ball_image3 = 'beachball3.jpg'
    bounce_sound = 'thump.wav'
    width = 800
    top = 600
    x = 0
    y = 0
    background_colour = 0,0,0
    caption= 'Bouncing Ball animation'
    velocity1 = [-1,-1]
    velocity2 = [-1,1]
    velocity3 = [1,-1]
    pygame.init ()
    frame = pygame.display.set_mode ((width, top))
    pygame.display.set_caption (caption)
    ball1= pygame.image.load (ball_image1). convert()
    ball2= pygame.image.load (ball_image2). convert()
    ball3= pygame.image.load (ball_image3). convert()
    ball_boundary_1 = ball2.get_rect (center=(random.randint(50, 750),random.randint(50, 550)))
    ball_boundary_2 = ball2.get_rect (center=(random.randint(50, 750),random.randint(50, 550)))
    ball_boundary_3 = ball2.get_rect (center=(random.randint(50, 750),random.randint(50, 550)))
    sound = pygame.mixer.Sound (bounce_sound)
    while True:
        for event in pygame.event.get():
            print event 
            if event.type == pygame.QUIT: sys.exit(0)
        if ball_boundary_1.left < 0 or ball_boundary_1.right > width:
            sound.play()
            velocity1[0] = -velocity1[0]
        if ball_boundary_1.top < 0 or ball_boundary_1.bottom > top:
            sound.play()
            velocity1[1] = -velocity1[1]
        if ball_boundary_2.left < 0 or ball_boundary_2.right > width:
            sound.play()
            velocity2[0] = -velocity2[0]
        if ball_boundary_2.top < 0 or ball_boundary_2.bottom > top:
            sound.play()
            velocity2[1] = -velocity2[1]
        if ball_boundary_3.left < 0 or ball_boundary_3.right > width:
            sound.play()
            velocity3[0] = -velocity3[0]
        if ball_boundary_3.top < 0 or ball_boundary_3.bottom > top:
            sound.play()
            velocity3[1] = -velocity3[1]

        ball_boundary_1 = ball_boundary_1.move (velocity1)
        ball_boundary_2 = ball_boundary_2.move (velocity2)
        ball_boundary_3 = ball_boundary_3.move (velocity3)
        frame.fill (background_colour)
        frame.blit (ball1, ball_boundary_1)
        frame.blit (ball2, ball_boundary_2)
        frame.blit (ball3, ball_boundary_3)
        pygame.display.flip() 

3 个回答

1

我的老师在这个特定的评估中补充了以下内容:

当第二个球在画面中弹跳时,添加一些代码来改变球的方向,如果它们碰撞的话。PyGame提供了一个函数,可以用来检测两个矩形对象(Rect)之间是否发生了碰撞。这个函数叫做colliderect,使用方式如下。如果有两个矩形对象分别叫做ball_boundary_1和ball_boundary_2,你可以用以下代码来检查它们是否碰撞:

if ball_boundary_1.colliderect(ball_boundary_2):

    # alter the direction of the balls with the usual method

所以,这段代码用来检查“是否”发生了碰撞,如果发生了,就返回True,并执行一些代码来反转球的速度。祝你好运,:D 我自己还没做这一部分,正准备尝试。

1

其实你提供的代码里有一些线索。你检测小球是否碰到墙壁的方法是检查小球的顶部边界是否小于0,这意味着它碰到了顶部边界,需要反弹,所以你就改变了方向。

所以这段代码:

if ball_boundary_1.top < 0 or ball_boundary_1.bottom > top:
        sound.play()
        velocity1[1] = -velocity1[1]

基本上是当小球在地面或天花板上反弹时,改变小球的垂直运动方向。

要修改这个,你需要问自己,如果两个小球碰到了一起,这意味着什么呢?这就意味着它们的边界在某种程度上重叠了。例如,你可以检查小球1的左边或右边是否在小球2的水平范围内,并且小球1的顶部或底部是否在小球2的垂直范围内,如果是这样,那就说明两个小球碰到了,这时你需要改变两个小球的速度。

3

当两个物体“碰撞”时,它们基本上是在同一个物理空间里,所以你需要检查这个情况。在二维空间里,这个检查非常简单,尤其是对于矩形形状。你可以写一个叫做“overlap”的函数,如果两个球碰撞,就返回一个真值(true)。比如:

for (i = 0; i < numberOfBalls; i++) {
    for (j = i+1; j < numberOfBalls; j++) {
        if (overlap (ball_rect[i], ball_rect[j])) {
            // you will need to write this reverse velocity code differently
            // to comply with the code above but I recommend that the balls 
            // go in an array with three elements so that you can index 
            // them. (Useful in for loops as seen above)
            ball_xvelocity[i] *= -1;
            ball_xvelocity[j] *= -1;
            ball_yvelocity[i] *= -1;
            ball_yvelocity[j] *= -1;
        }
    }
}

我把“overlap”函数的具体实现留给你自己去做,但你可以在网上搜索“矩形碰撞检测”,你会找到相关的方法。你会发现其实这并没有那么复杂,这会让你相信自己可以通过研究和学习来掌握编程的概念。

注意:我特意没有给出Python代码。因为这是作业,所以写答案是你的任务。抱歉,这是StackOverflow的政策。希望这对你有帮助。:)

撰写回答