Last active
May 22, 2017 11:07
-
-
Save mrzechonek/385c16207077e443f0279f69fd13e823 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3.4 | |
import pyglet | |
from vector import Vector | |
class Entity: | |
def __init__(self, name, *args, **kwargs): | |
self.name = name | |
super().__init__(*args, **kwargs) | |
class PositionComponent: | |
def __init__(self, position, speed, *args, **kwargs): | |
self.position = position | |
self.speed = speed | |
super().__init__(*args, **kwargs) | |
class MassComponent: | |
def __init__(self, mass, *args, **kwargs): | |
self.mass = mass | |
super().__init__(*args, **kwargs) | |
class RadiationComponent: | |
def __init__(self, intensity, *args, **kwargs): | |
self.intensity = intensity | |
super().__init__(*args, **kwargs) | |
class TailComponent: | |
def __init__(self, tail, *args, **kwargs): | |
self.tail = tail | |
super().__init__(*args, **kwargs) | |
class Planet(MassComponent, PositionComponent, Entity): | |
pass | |
class Star(MassComponent, PositionComponent, RadiationComponent, Entity): | |
pass | |
class Comet(MassComponent, PositionComponent, TailComponent, Entity): | |
pass | |
class Universe: | |
def __init__(self): | |
self._entities = set() | |
def add(self, entity): | |
self._entities.add(entity) | |
def find_by_components(self, *components): | |
for entity in self._entities: | |
if all(isinstance(entity, c) for c in components): | |
yield entity | |
class DisplaySystem: | |
def __init__(self, universe, window): | |
self.universe = universe | |
self.window = window | |
self._widgets = {} | |
self._center = Vector(self.window.width, self.window.height) / 2 | |
def _widget_for_entity(self, entity): | |
try: | |
return self._widgets[entity] | |
except KeyError: | |
image = pyglet.image.load('images/%s.png' % entity.name.lower()) | |
widget = pyglet.sprite.Sprite(image) | |
self._widgets[entity] = widget | |
return widget | |
def _project(self, entity): | |
widget = self._widget_for_entity(entity) | |
scaled = self._center + entity.position / (7.5 * 10**8) | |
widget.x = scaled.x - widget.width/2 | |
widget.y = scaled.y - widget.height/2 | |
return widget | |
def process(self, dt): | |
for entity in self.universe.find_by_components(PositionComponent): | |
widget = self._project(entity) | |
widget.draw() | |
class GravitySystem: | |
G = 6.67408 * 10**-11 | |
def __init__(self, universe, timescale=None): | |
self.universe = universe | |
self.timescale = timescale | |
def _acceleration(self, entity, other): | |
distance = entity.position - other.position | |
force = (self.G * entity.mass * other.mass) / abs(distance)**2 | |
direction = -distance / abs(distance) | |
return direction * force / entity.mass | |
def process(self, dt): | |
for entity in self.universe.find_by_components(PositionComponent, MassComponent): | |
acceleration = Vector(0, 0) | |
for other in self.universe.find_by_components(PositionComponent, MassComponent): | |
if entity is other: | |
continue | |
acceleration += self._acceleration(entity, other) | |
entity.speed += acceleration * dt * self.timescale | |
entity.position += entity.speed * dt * self.timescale | |
if __name__ == '__main__': | |
window = pyglet.window.Window() | |
universe = Universe() | |
universe.add( | |
Star( | |
name='Sol', | |
position=Vector(0, 0), | |
speed=Vector(0, 0), | |
mass=1.9884 * 10**30, | |
intensity=None, | |
) | |
) | |
universe.add( | |
Planet( | |
name='Earth', | |
position=Vector(0, 149.6 * 10**9), | |
speed=Vector(29.78 * 10**3, 0), | |
mass=5.9722 * 10**24, | |
) | |
) | |
display = DisplaySystem(universe, window) | |
gravity = GravitySystem(universe, 30 * 24 * 3600) | |
@window.event | |
def on_draw(): | |
window.clear() | |
display.process(pyglet.clock) | |
pyglet.clock.schedule_interval(gravity.process, 1/60) | |
pyglet.app.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
class Vector: | |
def __init__(self, x, y): | |
self.x = x | |
self.y = y | |
def __neg__(self): | |
return self * -1 | |
def __add__(self, vector): | |
return Vector(self.x + vector.x, self.y + vector.y) | |
def __sub__(self, vector): | |
return Vector(self.x - vector.x, self.y - vector.y) | |
def __mul__(self, number): | |
return Vector(self.x * number, self.y * number) | |
def __truediv__(self, number): | |
return Vector(self.x / number, self.y / number) | |
def __floordiv__(self, number): | |
return Vector(self.x // number, self.y // number) | |
def __abs__(self): | |
return math.sqrt(self.x ** 2 + self.y ** 2) | |
def __str__(self): | |
return '(%f, %f)' % (self.x, self.y) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment