Reputation: 67
Working on a basic particle simulator where rules can be applied to groups of particles (eg. reds attract blues, blues repel yellows, etc). Using this video as a guide, I created a simple python application that works, but the particles don't behave as expected. The below code is an example where the blue particle starts attracted to the red particle but instead of oscillating, the blue particle bounces off the red particle and becomes chaotic.
import pygame
import random
class Particle():
def __init__(self, x, y, mass, color):
self.x = x
self.y = y
self.xvel = 0
self.yvel = 0
self.mass = mass
self.color = color
def main():
random.seed(1662443792)
# initialize screen
pygame.init()
width = 1000
height = 800
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
running = True
# spawn some particles
blue = []
for i in range(1):
x = random.randint(0, width)
y = random.randint(0, height)
p = Particle(x, y, 1, (0, 0, 255))
blue.append(p)
red = []
for i in range(1):
x = random.randint(0, width)
y = random.randint(0, height)
p = Particle(x, y, 10, (255, 0, 0))
red.append(p)
while running:
pygame.display.flip()
screen.fill((0, 0, 0))
draw_particles(screen, blue)
draw_particles(screen, red)
rule(blue, red, -1)
clock.tick(144)
# quit simulation
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
pygame.quit()
# PHYSICS FOR PARTICLES DONE HERE
def rule(set1, set2, g):
for a in set1:
fx = 0
fy = 0
for b in set2:
# calculate distance between particles
dx = a.x - b.x
dy = a.y - b.y
d = (dx * dx + dy * dy) ** .5
if (d > 0):
# calculate force between particles
force = (g * a.mass * b.mass) / (d*d)
fx += force * dx
fy += force * dy
# update force and position
a.xvel = (a.xvel + fx)
a.yvel = (a.yvel + fy)
a.x += a.xvel
a.y += a.yvel
# if particle wants to leave screen, flip velocity
if (a.x >= 1000 or a.x <= 0):
a.xvel *= -1
if (a.y >= 800 or a.y <= 0):
a.yvel *= -1
def draw_particles(screen, particle_set1):
for p in particle_set1:
pygame.draw.circle(screen, p.color, (p.x, p.y), 5, 2)
if __name__ == '__main__':
main()
Upvotes: 0
Views: 186
Reputation: 81
I believe your estimation of the force is ill-posed. You multiply it by dx
, I guess to get the "direction" of the force, but then you should divide by d
.
Also, regarding your velocity and position updates, I think you over-estimate variations of both, instead of a.xvel += fx
I would have expected a.xvel += fx*dt
, with dt
your integration step, here 0.144s I guess.
Upvotes: 1