mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
151 lines
5.1 KiB
Python
151 lines
5.1 KiB
Python
from __future__ import division
|
|
|
|
import json
|
|
import os
|
|
from collections import OrderedDict
|
|
|
|
import six
|
|
|
|
from punyverse import texture
|
|
from punyverse.camera import Camera
|
|
from punyverse.entity import *
|
|
|
|
try:
|
|
from punyverse._model import model_list, load_model
|
|
except ImportError:
|
|
from punyverse.model import model_list, load_model
|
|
|
|
|
|
def load_world(file, callback=lambda message, completion: None):
|
|
return World(file, callback)
|
|
|
|
|
|
class World(object):
|
|
def __init__(self, file, callback):
|
|
self.tracker = []
|
|
self.x = None
|
|
self.y = None
|
|
self.z = None
|
|
self.tick_length = 0
|
|
self.tick = 0
|
|
self.asteroids = AsteroidManager()
|
|
self.cam = Camera()
|
|
|
|
self.callback = callback
|
|
self._parse(file)
|
|
del self.callback # So it can't be used after loading finishes
|
|
|
|
self._time_accumulate = 0
|
|
|
|
for entity in self.tracker:
|
|
entity.update()
|
|
|
|
def evaluate(self, value):
|
|
return eval(str(value), {'__builtins__': None}, self._context)
|
|
|
|
@property
|
|
def length(self):
|
|
return self._length
|
|
|
|
@property
|
|
def au(self):
|
|
return self._au
|
|
|
|
def _parse(self, file):
|
|
self.callback('Parsing configuration...', 'Loading configuration file...', 0)
|
|
with open(os.path.join(os.path.dirname(__file__), file)) as f:
|
|
root = json.load(f, object_pairs_hook=OrderedDict)
|
|
self._au = root.get('au', 2000)
|
|
self._length = root.get('length', 4320)
|
|
self._context = {'AU': self._au, 'TEXTURE': texture.max_texture, 'KM': 1.0 / self._length}
|
|
|
|
self.tick_length = root.get('tick', 4320) # How many second is a tick?
|
|
|
|
# Need to know how many objects are being loaded
|
|
self._objects = 0
|
|
self._current_object = 0
|
|
|
|
def count_objects(bodies):
|
|
for body in six.itervalues(bodies):
|
|
self._objects += 1
|
|
count_objects(body.get('satellites', {}))
|
|
count_objects(root['bodies'])
|
|
|
|
if 'start' in root:
|
|
info = root['start']
|
|
self.cam.x = self.evaluate(info.get('x', 0))
|
|
self.cam.y = self.evaluate(info.get('y', 0))
|
|
self.cam.z = self.evaluate(info.get('z', 0))
|
|
self.cam.pitch = self.evaluate(info.get('pitch', 0))
|
|
self.cam.yaw = self.evaluate(info.get('yaw', 0))
|
|
self.cam.roll = self.evaluate(info.get('roll', 0))
|
|
|
|
for planet, info in six.iteritems(root['bodies']):
|
|
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
|
'Loading %s.' % planet, self._current_object / self._objects)
|
|
self._body(planet, info)
|
|
self._current_object += 1
|
|
|
|
if 'belts' in root:
|
|
belt_count = len(root['belts'])
|
|
for i, (name, info) in enumerate(six.iteritems(root['belts']), 1):
|
|
self.callback('Loading belts (%d of %d)...' % (i, belt_count),
|
|
'Loading %s.' % name, i / belt_count)
|
|
self.tracker.append(Belt(name, self, info))
|
|
|
|
if 'sky' in root:
|
|
self.callback('Loading sky...', 'Loading sky.', 0)
|
|
self.tracker.append(Sky(self, root['sky']))
|
|
|
|
if 'asteroids' in root:
|
|
asteroids = root['asteroids']
|
|
for i, file in enumerate(asteroids):
|
|
self.callback('Loading asteroids...', 'Loading %s...' % file, i / len(asteroids))
|
|
self.asteroids.load(file)
|
|
|
|
def _body(self, name, info, parent=None):
|
|
if 'texture' in info:
|
|
body = SphericalBody(name, self, info, parent)
|
|
elif 'model' in info:
|
|
body = ModelBody(name, self, info, parent)
|
|
else:
|
|
raise ValueError('Nothing to load for %s.' % name)
|
|
|
|
if parent:
|
|
parent.satellites.append(body)
|
|
else:
|
|
self.tracker.append(body)
|
|
|
|
for satellite, info in six.iteritems(info.get('satellites', {})):
|
|
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
|
'Loading %s, satellite of %s.' % (satellite, name), self._current_object / self._objects)
|
|
self._body(satellite, info, body)
|
|
self._current_object += 1
|
|
|
|
def spawn_asteroid(self):
|
|
if self.asteroids:
|
|
c = self.cam
|
|
dx, dy, dz = c.direction()
|
|
speed = abs(self.cam.speed) * 1.1 + 5
|
|
self.tracker.append(self.asteroids.new((c.x, c.y - 3, c.z + 5), (dx * speed, dy * speed, dz * speed)))
|
|
|
|
def update(self, dt, move, tick):
|
|
c = self.cam
|
|
c.update(dt, move)
|
|
|
|
if tick:
|
|
delta = self.tick_length * dt
|
|
update = int(delta + self._time_accumulate + 0.5)
|
|
if update:
|
|
self._time_accumulate = 0
|
|
self.tick += update
|
|
|
|
for entity in self.tracker:
|
|
entity.update()
|
|
collision = entity.collides(c.x, c.y, c.z)
|
|
if collision:
|
|
c.speed *= -1
|
|
c.move(c.speed * 12 * dt)
|
|
else:
|
|
self._time_accumulate += delta
|