]运行模拟时,粒子可能会重叠并稍微变形。我认为,因为这是一个离散的模拟,当检测到碰撞时,粒子已经重叠,所以计算最终速度的部分不能正常工作
我为粒子和屏幕边界解决了同样的问题,但我不知道如何处理粒子碰撞。任何帮助都将不胜感激
import pygame
import random
import math
import numpy as np
width, height = 700, 450
screen = pygame.display.set_mode((width, height))
particles = []
no_particles = 10
tick_speed = 200
class Particle:
def __init__(self, x, y, r):
self.r = r
self.pos = np.array([x, y])
self.vel = np.array([random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5)])
self.acc = np.array([0, 0]) #tick_speed/(tick_speed * 10)
def display(self):
pygame.draw.circle(screen, (227, 53, 15), (int(self.pos[0]), int(self.pos[1])), self.r, 1)
def move(self):
self.vel = self.vel + self.acc
self.pos = self.pos + self.vel
def bounce(self):
if self.pos[1] > height - self.r:
self.pos[1] = 2*(height - self.r) - self.pos[1]
self.vel[1] = -self.vel[1]
elif self.pos[1] < self.r:
self.pos[1] = 2*self.r - self.pos[1]
self.vel[1] = -self.vel[1]
if self.pos[0] + self.r > width:
self.pos[0] = 2*(width - self.r) - self.pos[0]
self.vel[0] = -self.vel[0]
elif self.pos[0] < self.r:
self.pos[0] = 2*self.r - self.pos[0]
self.vel[0] = -self.vel[0]
@classmethod
def collision(cls, p1, p2):
dc = math.hypot((p1.pos[0]-p2.pos[0]), (p1.pos[1]-p2.pos[1]))
if dc <= p1.r + p2.r:
x1, y1 = p1.pos[0], p1.pos[1]
x2, y2 = p2.pos[0], p2.pos[1]
m1, m2 = p1.r**2, p2.r**2
n = np.array([x2-x1, y2-y1])
un = n / np.linalg.norm(n)
ut = np.array([-un[1], un[0]])
v1 = p1.vel
v2 = p2.vel
v1n = np.dot(un, v1)
v1t = np.dot(ut, v1)
v2n = np.dot(un, v2)
v2t = np.dot(ut, v2)
v1n_prime_s = (v1n * (m1 - m2) + 2*m2*v2n) / (m1 + m2)
v2n_prime_s = (v2n * (m2 - m1) + 2*m1*v1n) / (m1 + m2)
v1n_prime = v1n_prime_s * un
v1t_prime = v1t * ut
v2n_prime = v2n_prime_s * un
v2t_prime = v2t * ut
u1 = v1n_prime + v1t_prime
u2 = v2n_prime + v2t_prime
p1.vel = u1
p2.vel = u2
while len(particles) < no_particles:
r = random.randint(10, 20)
x = random.randint(r, width-r)
y = random.randint(r, height-r)
collide = False
for particle in particles:
d = (particle.pos[0] - x)**2 + (particle.pos[1] - y)**2
if d < (r + particle.r)**2:
collide = True
break
if not collide:
particles.append(Particle(x, y, random.randint(10, 20)))
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
for particle in particles:
particle.move()
particle.bounce()
for particle2 in [p for p in particles if p!= particle]:
particle.collision(particle, particle2)
particle.display()
pygame.display.flip()
clock.tick(tick_speed)
pygame.quit()
quit()
问题在于,您在一次迭代中多次检查并解决同一个球的碰撞问题
因为方向已经"反映"过一次了,这些网点产品,
在下一次碰撞分辨率中产生相反的方向,这会导致球彼此移动
每次球碰撞时,系统都会被添加“能量”,因此
这导致了你提到的那种反常
解决方案是只需检查并解决一次冲突:
正如拉比76所指出的,随着粒子数量的增加,这种方法会失败。如果先静态解决碰撞,一切都将正常,因为碰撞已经解决,动态解决代码将相应地设置速度
完整代码:
相关问题 更多 >
编程相关推荐