from itertools import combinations from superturtle.movement import fly, no_delay from superturtle.animation import animate from simulation.gravity import get_gravity_force from simulation.collision import collide2d from simulation.drawing import draw_boundary class Simulation: def __init__(self, objects, g=None, e=None, boundary=None): self.objects = objects self.g = g self.e = e self.boundary = boundary self.collisions = set() def run(self, *args): for frame in animate(*args): for a, b in combinations(self.objects, 2): if self.g is not None: force = get_gravity_force(a, b, self.g) a.acceleration += force / a.mass b.acceleration -= force / b.mass if self.e is not None: if a.collided_with(b): self.collide(a, b) else: self.clear_collision(a, b) for obj in self.objects: if self.boundary: draw_boundary(self.boundary) self.bounce_object_if_outside_boundary(obj) obj.update() fly(obj.position.x, obj.position.y) obj.draw() def collide(self, a, b): if not self.currently_colliding(a, b): self.collisions.add((a, b)) av, bv = collide2d(a, b, self.e) a.velocity = av b.velocity = bv def currently_colliding(self, a, b): return (a, b) in self.collisions or (b, a) in self.collisions def clear_collision(self, a, b): if (a, b) in self.collisions: self.collisions.remove((a, b)) if (b, a) in self.collisions: self.collisions.remove((b, a)) def bounce_object_if_outside_boundary(self, obj): if obj.position.x + obj.radius > self.boundary: obj.velocity.x = -abs(obj.velocity.x) if obj.position.x - obj.radius < -self.boundary: obj.velocity.x = abs(obj.velocity.x) if obj.position.y + obj.radius > self.boundary: obj.velocity.y = -abs(obj.velocity.y) if obj.position.y - obj.radius < -self.boundary: obj.velocity.y = abs(obj.velocity.y)