我试图在pygame中编写一个粒子模拟程序,但是在编写粒子之间的碰撞时遇到了困难。所有的碰撞都是弹性的,所以动能应该守恒。然而,我遇到了两个主要问题:
我真的很感激任何有助于解决这些问题的见解。在
我用这个文件(http://www.vobarian.com/collisions/2dcollisions2.pdf)来帮助计算碰撞后粒子的新速度。所有粒子的质量都是一样的,所以我在计算中忽略了它们的质量。 以下是我目前为止的代码:
import pygame
pygame.init()
import random
import numpy
HEIGHT = 500
WIDTH = 500
NUM_BALLS = 2
#setup
win = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("Simulation")
class Particle(object):
def __init__(self, x, y , radius):
self.x = x
self.y = y
self.radius = radius
self.xvel = random.randint(1,5)
self.yvel = random.randint(1,5)
def Draw_circle(self):
pygame.draw.circle(win, (255,0,0), (self.x, self.y), self.radius)
def redrawGameWindow():
win.fill((0,0,0))
for ball in balls:
ball.Draw_circle()
pygame.display.update()
balls = []
for turn in range(NUM_BALLS):
balls.append(Particle(random.randint(20,WIDTH-20),random.randint(20,HEIGHT-20),20))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
for ball in balls:
if (ball.x + ball.radius) <= WIDTH or (ball.x - ball.radius) >= 0:
ball.x += ball.xvel
if (ball.x + ball.radius) > WIDTH or (ball.x - ball.radius) < 0:
ball.xvel *= -1
ball.x += ball.xvel
if (ball.y + ball.radius) <= HEIGHT or (ball.y - ball.radius) >= 0:
ball.y += ball.yvel
if (ball.y + ball.radius) > HEIGHT or (ball.y - ball.radius) < 0:
ball.yvel *= -1
ball.y += ball.yvel
#code for collision between balls
for ball in balls:
for i in range(len(balls)):
for j in range (i+1, len(balls)):
d = (balls[j].x-balls[i].x)**2 + (balls[j].y-balls[i].y)**2
if d < (balls[j].radius + balls[i].radius)**2:
print("collision")
n = (balls[i].x-balls[j].x, balls[i].y-balls[j].y) #normal vector
un = n/ numpy.sqrt((balls[i].x-balls[j].x)**2 + (balls[i].y-balls[j].y)**2) #unit normal vector
ut = numpy.array((-un[1],un[0])) #unit tangent vector
u1n = numpy.vdot(un, (balls[j].xvel, balls[j].yvel)) #initial velocity in normal direction for first ball
v1t = numpy.vdot(ut, (balls[j].xvel, balls[j].yvel)) #initial velocity in tangent direction (remains unchanged)
u2n = numpy.vdot(un, (balls[i].xvel, balls[i].yvel)) #second ball
v2t = numpy.vdot(ut, (balls[i].xvel, balls[i].yvel))
v1n = u2n
v2n = u1n
v1n *= un
v2n *= un
v1t *= ut
v2t *= ut
v1 = v1n + v1t #ball 1 final velocity
v2 = v2n + v2t #ball 2 final velocity
balls[j].xvel = int(numpy.vdot(v1, (1,0))) #splitting final velocities into x and y components again
balls[j].yvel = int(numpy.vdot(v1, (0,1)))
balls[i].xvel = int(numpy.vdot(v2, (1,0)))
balls[i].yvel = int(numpy.vdot(v2, (0,1)))
redrawGameWindow()
pygame.time.delay(20)
pygame.quit()
在}是一个标量。在
v1 = v1n + v1t
中,v1n
是一个向量,而{因此,值
v1t
被加到v1n
向量的两个分量中,这将导致错误。在要将切向速度添加为向量,因此应该像对法向速度所做的那样:
注意,对两个完全不同的东西使用同一个变量,向量和它的范数,会使代码更难理解,并可能导致错误——就像刚才一样。您可能应该以更一致的方式重命名变量,以便使差异更清楚。在
另外,
ut
必须是一个numpy数组,但您将其设置为tuple。考虑一下区别:用元组
^{pr2}$带着np.数组公司名称:
^{3}$所以,你必须改变
进入
物体粘在一起的问题很简单,即使你总是检查碰撞情况,它真正意识到的时候,是当这些圆越过接触,但又稍微相互接触的时候。这些圆现在反弹并移动一点。然而,它们还没有移动到完全不接触的程度,这意味着再次反弹,它会循环。我做了一些代码来修复这个问题,但是你必须改变bounce函数并使用你的代码,因为我的代码不是那么完美,而是功能性的。在
相关问题 更多 >
编程相关推荐