Pygame中的动画故障

时间:2019-07-06 07:14:21

标签: python algorithm animation pygame

我正在使用 pygame创建碰撞模拟两个块的模拟,其质量比为100的幂,要清楚,这意味着较大块与较小块的比率可以为{{1} },100**0100**1等。我在必要的地方添加了注释和文档字符串,以使逻辑易于理解。

100**2

问题1:

对于较小的import pygame # from collisions import * pygame.init() s1, s2 = 100, 50 # block sides x1, y1 = 1000, 250 # bigger block coords x2, y2 = 500, y1 + s1 - s2 # smaller block coords power = int(input('enter: ')) # mass ratio v1 = (-0.5) # initial velocity of block 1 m1, m2 = 100 ** (power - 1), 1 # mass of blocks v2 = 0 # initial velocity of block 2 # temp_x1 = 0 red = (255, 0, 0) blue = (0, 0, 255) def message_to_print(msg, color): font = pygame.font.SysFont(None, 40) text = font.render(msg, True, color) win.blit(text, [10, 10]) def reverse_vel(vel): ''' reversing velocity of block ''' vel *= -1 return vel def exchange_vel(v1, m1, v2, m2): ''' this function is calculating the new velocity of the block after collision, based on law of conservation of momentum and kinetic energy ''' v1 = ((m1 - m2) / (m1 + m2)) * v1 + ((2 * m2) / (m1 + m2)) * v2 return v1 # returning new velocity after collision win = pygame.display.set_mode((1200, 500)) win.fill((255, 255, 255)) pygame.display.set_caption('simulation') Collisions = 0 # counting number of collisions run = True while run: # click_sound = pygame.mixer.Sound("rss/click.wav") # pygame.time.delay(10) # sound_collide, sound_reverse = True, True message_to_print('collision ' + str(Collisions), (0, 0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False # biger block x1 += v1 # changing block coordinates according to velocity if x1 > s2: # this prevents block 1 from moving out of window t = x1 if not x2 + s2 < x1 or x1 + s1 < x2: ''' changing velocity after collision, storing them in temp variable for each block, then assiging new velocity ''' v2_temp = exchange_vel(v2, m2, v1, m1) v1_temp = exchange_vel(v1, m1, v2, m2) # if sound_collide: # click_sound.play() # sound = False v2, v1 = v2_temp, v1_temp # assigning new velocities Collisions += 1 # smaller Block x2 += v2 if x2 <= 0: ''' if block 1 touch left wall, its velocity reverses, ''' v2 = reverse_vel(v2) # if sound_reverse: # click_sound.play() # sound_reverse = False Collisions += 1 pygame.draw.rect(win, blue, (x2, y2, s2, s2)) pygame.draw.rect(win, red, (t, y1, s1, s1)) pygame.display.update() win.fill((255, 255, 255)) pygame.quit() ,模拟工作正常。但是,对于power值,第2块(蓝色块)的动画变得很奇怪(如图所示),我无法找到原因并解决。 enter image description here

从图像中可以看到,蓝色块始终是该位置,并且不断消失并不断消失。

更新:发生碰撞的次数是该程序的组成部分。无论如何,不​​应影响发生的碰撞次数

2 个答案:

答案 0 :(得分:2)

如果速度(v1v2)大于1,则碰撞不会恰好在对象的新位置发生(分别在v1之后{{1 }})已添加到该职位。碰撞发生在从v2x1x1+v1x2的轨道上。

拆分计算int步,其中每个步小于1(像素)并循环执行计算。请注意,计算是使用浮点值而不是整数值完成的:

x2+v2

限制碰撞后小块的位置:

steps = max(abs(int(v1))+1, int(abs(v2))+1)
for i in range(steps):

    # biger block
    step_v1 = v1 / steps
    x1 += step_v1
    # [...]

    # smaller Block
    step_v2 = v2 / steps
    x2 += step_v2
    # [...]
if x1 <= x2+s2:
    x2 = x1-s2

由于块的坐标是浮点值,因此在round()中使用之前,必须pygame.draw.rect()为整数值:

if x2 <= 0:
    x2 = 0

主循环和带有pygame.draw.rect(win, blue, (round(x2), round(y2), s2, s2)) pygame.draw.rect(win, red, (round(x1), round(y1), s1, s1)) 的示例

enter: 4

答案 1 :(得分:1)

我了解您在做什么。您可以通过在停止块1移出窗口时简单地添加else语句来实现此目的。

if x1 >= s2:
    t = x1
    t2 = x2
else:
    t2 = 0

并更改

pygame.draw.rect(win, blue, (t2, y2, s2, s2)) # x2-> t2

说明:当您的block1坐标大于s2时,它们将具有正常运动,但是如果不是这种情况,只需将较小的块的坐标固定为0。

推荐: 由于实际上在这段时间内会发生碰撞,因此要在仿真中显示这一点,您可以执行以下操作。

    if x1 >= s2 +2:   # this prevents block 1 from moving out of window
    t = x1
    t2 = x2
else:
    t2 = z%2
z+=1

这将创建一个迷你碰撞效果。我曾经使用2是任意选择。还要在主循环之前初始化z=0