我想用 Python Arcade 和 Pymunk 实现粒子模拟。虽然 Arcade 即使在绘图/处理方面也非常快,例如。 10000 个粒子与 Pymunk 的碰撞处理变得非常慢。我假设 Pymunk 正在检查每个可能的粒子对是否发生碰撞。
在粒子碰撞模拟中,窗口上通常有一个网格,粒子碰撞只检查相邻网格单元中的粒子。这要快得多。
编辑:到目前为止,这是我的代码:
import arcade
import pymunk
import random
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 800
PARTICLE_COUNT = 3000
PARTICLE_RADIUS = 4
GRAVITY = (0, -981)
class Particle:
def __init__(self, space, position, velocity, weight):
self.body = pymunk.Body()
self.body.position = position
self.body.velocity = velocity
self.shape = pymunk.Circle(self.body, radius=PARTICLE_RADIUS)
self.shape.density = weight
self.shape.elasticity = 0.8
self.color = arcade.color.WHITE
if weight > 1:
self.color = arcade.color.RED
elif weight < 1:
self.color = arcade.color.BLUE
space.add(self.body, self.shape)
def draw(self):
x, y = self.body.position
arcade.draw_circle_filled(x, y, PARTICLE_RADIUS, self.color)
class Simulation(arcade.Window):
def __init__(self, width, height):
super().__init__(width, height, "Particle Simulation")
arcade.set_background_color(arcade.color.BLACK)
self.space = pymunk.Space()
self.space.gravity = GRAVITY
wThick = 50
dv = 49
walls = [
pymunk.Segment(self.space.static_body, (-dv, 0), (-dv, height), wThick),
pymunk.Segment(self.space.static_body, (0, height+dv), (width, height+dv), wThick),
pymunk.Segment(self.space.static_body, (width+dv, height), (width+dv, 0), wThick),
pymunk.Segment(self.space.static_body, (0, 0-dv), (width, 0-dv), wThick)
]
for wall in walls:
wall.elasticity = 1
wall.friction = 0.5
wall.color = arcade.color.RED
self.space.add(*walls)
walls = [
pymunk.Segment(self.space.static_body, (0,height//2-dv), (width//2, 0-dv), wThick),
]
for wall in walls:
wall.elasticity = 1
wall.friction = 1
wall.color = arcade.color.RED
self.space.add(*walls)
self.particles = []
for i in range(PARTICLE_COUNT):
position = random.uniform(PARTICLE_RADIUS, width//2 - PARTICLE_RADIUS), \
random.uniform(height//2+PARTICLE_RADIUS, height - PARTICLE_RADIUS)
velocity = random.uniform(-200, 200), random.uniform(-200, 200)
weight = random.uniform(0.1, 2)
self.particles.append(Particle(self.space, position, velocity, weight))
def on_draw(self):
arcade.start_render()
for particle in self.particles:
particle.draw()
# Draw the FPS counter in the bottom-left corner of the window
fps = arcade.get_fps()
fps_text = "FPS: %.2f" % (fps)
arcade.draw_text(fps_text, 10, 10, arcade.color.WHITE, 14)
def on_update(self, delta_time):
self.space.step(1/120)
def main():
sim = Simulation(SCREEN_WIDTH, SCREEN_HEIGHT)
arcade.enable_timings()
arcade.run()
if __name__ == '__main__':
main()
用Pymunk可以实现吗?