Skip to content

Instantly share code, notes, and snippets.

@gabrii
Created December 23, 2013 17:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabrii/8101073 to your computer and use it in GitHub Desktop.
Save gabrii/8101073 to your computer and use it in GitHub Desktop.
Particles simualtion with Coulomb's Law and cubic gravitational law ( like the normal gravitation law, but with r³ instead of r²). This simulation does not have any phisical meaning, it's just for fun. See some captures at: http://sta.sh/21s1a54ox37m
#! /usr/bin/env python
'''
Controls:
Adding particles (and it's charges):
left button -> (+)
right button -> (-)
middle button -> ( )
SPACE : Play/pause
r : restart game
'''
import pygame, time, random
from pygame import gfxdraw
# Physical Variables
k = 4000000.0
G = 30000000.0
flim = 100000
# Game vars
size = 900
scale = 1
speed = 0.1
bold =0
trans = 1
def uni(v, lim=1):
mod = (v[0]**2+v[1]**2)**0.5
if mod > lim:
m= lim/mod
return (v[0]*m, v[1]*m)
else:
return v
class p():
def __init__(self, Q, pos, vel=[0.0,0.0]):
self.Q = Q
self.pos = pos
self.vel = vel
self.F = [0,0]
def interact(self, ps):
self.F = [0.0, 0.0]
for p in ps:
if p == self:
continue
d = (self.pos[0]-p.pos[0])**2 + (self.pos[1]-p.pos[1])**2
d = d**0.5
try:
u = ((p.pos[0]-self.pos[0])/d , (p.pos[1]-self.pos[1])/d)
self.F[0] -= k * self.Q * p.Q * u[0] / (d**2)
self.F[1] -= k * self.Q * p.Q * u[1] / (d**2)
self.F[0] += G / (abs(d)**3) * u[0]
self.F[1] += G / (abs(d)**3) * u[1]
except ZeroDivisionError:
p.pos[0]+=1
def update_vel(self, At):
F = uni(self.F, flim)
self.vel[0] += F[0]*At
self.vel[1] += F[1]*At
def update_pos(self, At):
self.pos[0] += self.vel[0]*At
self.pos[1] += self.vel[1]*At
def redraw():
bg = [20,20,20]
screen.fill(bg)
#pygame.draw.line(screen, (255,255,255), (size-20, 30), (size-20, size-30), 2)
#pygame.draw.rect(screen, (255,255,255), (size/4, size/4, size/2, size/2), 1)
screen = pygame.display.set_mode((size, size))
ps = []
redraw()
simulating = False
lt = time.time()
while True:
At = (time.time()-lt)*speed
lt = time.time()
At = 0.001
if simulating:
for pa in ps:
pa.interact(ps)
for pa in ps:
pa.update_vel(At)
pa.update_pos(At)
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise SystemExit()
elif event.type == pygame.MOUSEBUTTONDOWN:
pres = pygame.mouse.get_pressed()
pos = pygame.mouse.get_pos()
ps.append(
p(+1*pres[0]+0*pres[1]-1*pres[2], [pos[0]-size/2,pos[1]-size/2], [0,0])
)
elif event.type == pygame.KEYDOWN:
key = event.dict['key']
if key == pygame.K_ESCAPE:
raise SystemExit()
elif key == pygame.K_SPACE:
simulating = not simulating
elif key == pygame.K_r:
redraw()
ps = []
simulating = 0
elif key == pygame.K_b:
bold = not bold
if not trans:
pygame.gfxdraw.box(screen, (0,0,size,size), bg+[255])
for pa in ps:
col = pa.Q == 0 and (0,255,0) or pa.Q < 0 and (255,0,0) or (100,100,255)
x = int(size/2 +(pa.pos[0])/scale)
y = int(size/2 +(pa.pos[1])/scale)
pygame.gfxdraw.pixel(screen, x, y, col)
if bold:
pygame.gfxdraw.pixel(screen, x+1, y, col)
pygame.gfxdraw.pixel(screen, x, y+1, col)
pygame.gfxdraw.pixel(screen, x+1, y+1, col)
pygame.display.flip()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment