我正试图在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()
这些东西粘在一起的问题很简单,即使你总是检查有没有碰撞,但它能真正识别的时间是圆圈相互接触但轻微接触的时候。圆圈现在会弹跳和移动一点。然而,他们没有移动到完全不接触,这意味着反弹,它在一个循环。我做的代码修复了这个问题,但你必须改变弹跳函数,并使用你的代码,因为我的不是那么完美,但功能。
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)
self.colideCheck = []
def Draw_circle(self):
pygame.draw.circle(win, (255,0,0), (int(self.x), int(self.y)), self.radius)
def redrawGameWindow():
win.fill((0,0,0))
for ball in balls:
ball.Draw_circle()
pygame.display.update()
def bounce(v1,v2, mass1 = 1, mass2 = 1):
#i Tried my own bouncing mechanism, but doesn't work completly well, add yours here
multi1 = mass1/(mass1+mass2)
multi2 = mass2/(mass1+mass2)
deltaV2 = (multi1*v1[0]-multi2*v2[0],multi1*v1[1]-multi2*v2[1])
deltaV1 = (multi2*v2[0]-multi1*v1[0],multi2*v2[1]-multi1*v1[1])
print("preVelocities:",v1,v2)
return deltaV1,deltaV2
def checkCollide(circ1Cord,circ1Rad,circ2Cord,circ2Rad):
tryDist = circ1Rad+circ2Rad
actualDist = dist(circ1Cord,circ2Cord)
if dist(circ1Cord,circ2Cord) <= tryDist:
return True
return False
def dist(pt1,pt2):
dX = pt1[0]-pt2[0]
dY = pt1[1]-pt2[1]
return (dX**2 + dY**2)**0.5
balls = []
for turn in range(NUM_BALLS):
balls.append(Particle(random.randint(60,WIDTH-60),random.randint(60,HEIGHT-60),60))
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 and (ball.x - ball.radius) >= 0:
ball.x += ball.xvel
else:
ball.xvel *= -1
ball.x += ball.xvel
if (ball.y + ball.radius) <= HEIGHT and (ball.y - ball.radius) >= 0:
ball.y += ball.yvel
else:
ball.yvel *= -1
ball.y += ball.yvel
for ball in balls:
for secBallCheck in balls:
if secBallCheck not in ball.colideCheck and ball!= secBallCheck and checkCollide((ball.x,ball.y),ball.radius,(secBallCheck.x,secBallCheck.y),secBallCheck.radius):
print("COLLIDE")
vel1,vel2 = bounce((ball.xvel,ball.yvel),(secBallCheck.xvel,secBallCheck.yvel))
print(vel1,vel2)
ball.xvel = vel1[0]
ball.yvel = vel1[1]
ball.colideCheck.append(secBallCheck)
secBallCheck.xvel = vel2[0]
secBallCheck.yvel = vel2[1]
secBallCheck.colideCheck.append(ball)
elif not checkCollide((ball.x,ball.y),ball.radius,(secBallCheck.x,secBallCheck.y),secBallCheck.radius):
if ball in secBallCheck.colideCheck:
secBallCheck.colideCheck.remove(ball)
ball.colideCheck.remove(secBallCheck)
redrawGameWindow()
pygame.time.delay(20)
pygame.quit()
为了计算x和y速度,我求解了一个动量守恒和动能守恒方程组。 顺便说一下,这些方程没有考虑圆的“形状”。 所以我通过求两个圆相交的切线来计算回弹角。 现在我有两个不同的最终速度方向:一个是用动量定律计算的,一个是用回弹计算的。 我不知道怎么把两种速度结合起来才能得到最后一种
提前感谢所有的帮助者
对于分子动力学的一门课,我要模拟一个有周期边界的盒子里的100个粒子。我必须考虑粒子与粒子的碰撞,因为墙壁是“透明的”,这些相互作用可以跨越边界发生。由于模拟应该包含50000个步骤,而且我希望将来会有越来越多的额外任务,所以我希望我的代码尽可能高效(尽管运行时间很长,但我必须使用python)。 该系统包括 null 按照我的理解,这种处理对整个数组的操作的技术比每次手动遍历它更有效。移动的粒子
我正在构建一个迷宫游戏,在这里我有一个简单的地图... 直到没有问题,但我的问题是碰撞 这是我的地图: 在这里,我用以下代码自己构建了地图: 此碰撞代码用于右上角矩形 我已经尝试了两种不同类型的碰撞代码,但都不起作用 碰撞码: 在这里,当玩家从左侧击中矩形时,玩家向下移动,当玩家从底部击中矩形时,玩家向左移动。 我用if, else if语句尝试过相同的代码,但仍然不起作用。当玩家点击左侧时,它可
有什么好主意吗?
我正在制作一个吃豆人风格的游戏,在pygame中使用蟒蛇。目前,我正在创造吃豆人必须在迷宫周围避免的幽灵/怪物。我已经创建了这些,并试图添加随机运动碰撞检测,以便它们在迷宫中移动,而不仅仅是整个屏幕。这些怪物的代码是波纹管。我的问题是,似乎有点跳来跳去,几乎一动不动,我怎么能像吃豆人幽灵一样顺利地穿过迷宫?任何帮助都非常感谢。