mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Added loading screen.
This commit is contained in:
parent
dc6d0c6c67
commit
55ee2ee3d2
|
@ -6,7 +6,7 @@ import time
|
|||
import random
|
||||
|
||||
from punyverse.camera import Camera
|
||||
from punyverse.world import load_world
|
||||
from punyverse.world import World
|
||||
from punyverse.glgeom import *
|
||||
from punyverse.entity import Asteroid
|
||||
from punyverse import texture
|
||||
|
@ -42,10 +42,33 @@ class Applet(pyglet.window.Window):
|
|||
super(Applet, self).__init__(*args, **kwargs)
|
||||
texture.init()
|
||||
|
||||
self.loaded = False
|
||||
self.__load_started = False
|
||||
self._loading_phase = pyglet.text.Label(font_name='Consolas', font_size=20, x=10, y=self.height - 100,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, halign='center',
|
||||
multiline=True, text='Punyverse is starting...')
|
||||
self._loading_label = pyglet.text.Label(font_name='Consolas', font_size=16, x=10, y=self.height - 200,
|
||||
color=(255, 255, 255, 255), width=self.width - 20, halign='center',
|
||||
multiline=True)
|
||||
pyglet.clock.schedule_once(self.load, 0)
|
||||
|
||||
def load(self, *args, **kwargs):
|
||||
if self.loaded or self.__load_started:
|
||||
return
|
||||
|
||||
self.__load_started = True
|
||||
|
||||
def callback(phase, message, progress):
|
||||
self.draw_loading(phase, message, progress)
|
||||
self.flip()
|
||||
self.dispatch_events()
|
||||
|
||||
start = clock()
|
||||
self.fps = 0
|
||||
self.world = load_world('world.json')
|
||||
print 'Initializing game...'
|
||||
self.world = World('world.json', callback)
|
||||
phase = 'Initializing game...'
|
||||
print phase
|
||||
callback(phase, '', 0)
|
||||
self.speed = INITIAL_SPEED
|
||||
self.keys = set()
|
||||
self.info = True
|
||||
|
@ -70,7 +93,6 @@ class Applet(pyglet.window.Window):
|
|||
self.__time_per_second_cache = None
|
||||
self.__time_per_second_value = None
|
||||
self.__time_accumulate = 0
|
||||
pyglet.clock.schedule(self.update)
|
||||
|
||||
def speed_incrementer(object, increment):
|
||||
def incrementer():
|
||||
|
@ -160,26 +182,35 @@ class Applet(pyglet.window.Window):
|
|||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, fv4(.5, .5, 1, 0))
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, fv4(.5, .5, 1, 1))
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, fv4(1, 0, .5, 0))
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
|
||||
|
||||
print 'Loading asteroids...'
|
||||
self.asteroid_ids = [model_list(load_model(r'asteroids/01.obj'), 5, 5, 5, (0, 0, 0)),
|
||||
model_list(load_model(r'asteroids/02.obj'), 5, 5, 5, (0, 0, 0)),
|
||||
model_list(load_model(r'asteroids/03.obj'), 5, 5, 5, (0, 0, 0)),
|
||||
]
|
||||
phase = 'Loading asteroids...'
|
||||
print phase
|
||||
|
||||
def load_asteroids(files):
|
||||
for id, file in enumerate(files):
|
||||
callback(phase, 'Loading %s...' % file, float(id) / len(files))
|
||||
yield model_list(load_model(file), 5, 5, 5, (0, 0, 0))
|
||||
|
||||
self.asteroid_ids = list(load_asteroids([r'asteroids/01.obj', r'asteroids/02.obj', r'asteroids/03.obj']))
|
||||
|
||||
c = self.cam
|
||||
c.x, c.y, c.z = self.world.start
|
||||
c.pitch, c.yaw, c.roll = self.world.direction
|
||||
|
||||
print 'Updating entities...'
|
||||
phase = 'Updating entities...'
|
||||
print phase
|
||||
callback(phase, '', 0)
|
||||
for entity in self.world.tracker:
|
||||
entity.update()
|
||||
|
||||
print 'Loaded in %s seconds.' % (clock() - start)
|
||||
self.loaded = True
|
||||
pyglet.clock.schedule(self.update)
|
||||
self.on_resize(self.width, self.height) # On resize handler does nothing unless it's loaded
|
||||
|
||||
def set_exclusive_mouse(self, exclusive):
|
||||
super(Applet, self).set_exclusive_mouse(exclusive)
|
||||
|
@ -196,6 +227,9 @@ class Applet(pyglet.window.Window):
|
|||
direction=(dx, dy, dz)))
|
||||
|
||||
def on_mouse_press(self, x, y, button, modifiers):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if not self.exclusive:
|
||||
self.set_exclusive_mouse(True)
|
||||
else:
|
||||
|
@ -203,10 +237,16 @@ class Applet(pyglet.window.Window):
|
|||
self.mouse_press_handler[button]()
|
||||
|
||||
def on_mouse_motion(self, x, y, dx, dy):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if self.exclusive: # Only handle camera movement if mouse is grabbed
|
||||
self.cam.mouse_move(dx * MOUSE_SENSITIVITY, dy * MOUSE_SENSITIVITY)
|
||||
|
||||
def on_key_press(self, symbol, modifiers):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if self.exclusive: # Only handle keyboard input if mouse is grabbed
|
||||
if symbol in self.key_handler:
|
||||
self.key_handler[symbol]()
|
||||
|
@ -214,10 +254,16 @@ class Applet(pyglet.window.Window):
|
|||
self.keys.add(symbol)
|
||||
|
||||
def on_key_release(self, symbol, modifiers):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
if symbol in self.keys:
|
||||
self.keys.remove(symbol)
|
||||
|
||||
def on_resize(self, width, height):
|
||||
if not self.loaded:
|
||||
return super(Applet, self).on_resize(width, height)
|
||||
|
||||
height = max(height, 1) # Prevent / by 0
|
||||
self.label.y = height - 20
|
||||
glViewport(0, 0, width, height)
|
||||
|
@ -228,6 +274,9 @@ class Applet(pyglet.window.Window):
|
|||
glMatrixMode(GL_MODELVIEW)
|
||||
|
||||
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
|
||||
if not self.loaded:
|
||||
return
|
||||
|
||||
self.speed += scroll_y * 50 + scroll_x * 500
|
||||
|
||||
def get_time_per_second(self):
|
||||
|
@ -267,9 +316,25 @@ class Applet(pyglet.window.Window):
|
|||
else:
|
||||
self.__time_accumulate += delta
|
||||
|
||||
def draw_loading(self, phase=None, message=None, progress=None):
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
if phase is not None:
|
||||
self._loading_phase.text = phase
|
||||
if message is not None:
|
||||
self._loading_label.text = message
|
||||
self._loading_phase.draw()
|
||||
self._loading_label.draw()
|
||||
if progress is not None:
|
||||
progress_bar(10, self.height - 300, self.width - 20, 50, progress)
|
||||
|
||||
def on_draw(self, glMatrix=GLfloat * 16):
|
||||
if not self.loaded:
|
||||
return self.draw_loading()
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||||
glLoadIdentity()
|
||||
|
||||
c = self.cam
|
||||
|
||||
x, y, z = c.x, c.y, c.z
|
||||
|
|
|
@ -5,7 +5,18 @@ from random import random, gauss, choice
|
|||
TWOPI = pi * 2
|
||||
|
||||
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'sphere', 'colourball', 'torus', 'belt',
|
||||
'flare', 'normal_sphere']
|
||||
'flare', 'normal_sphere', 'glSection', 'progress_bar']
|
||||
|
||||
|
||||
class glSection(object):
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
def __enter__(self):
|
||||
glBegin(self.type)
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
glEnd()
|
||||
|
||||
|
||||
def compile(pointer, *args, **kwargs):
|
||||
|
@ -289,4 +300,37 @@ except ImportError:
|
|||
glVertex3f(x1 * r, y1 * r, z)
|
||||
|
||||
glEnd()
|
||||
glPopAttrib()
|
||||
glPopAttrib()
|
||||
|
||||
|
||||
def progress_bar(x, y, width, height, filled):
|
||||
x1 = x
|
||||
x2 = x + width
|
||||
y1 = y
|
||||
y2 = y - height
|
||||
y3 = 0.65 * y1 + 0.35 * y2
|
||||
y4 = 0.25 * y1 + 0.75 * y2
|
||||
|
||||
glColor3f(0.6, 0.6, 0.6)
|
||||
with glSection(GL_LINE_LOOP):
|
||||
glVertex2f(x1, y1)
|
||||
glVertex2f(x1, y2)
|
||||
glVertex2f(x2, y2)
|
||||
glVertex2f(x2, y1)
|
||||
|
||||
x1 += 1
|
||||
y1 -= 1
|
||||
x2 = x + width * filled - 1
|
||||
|
||||
with glSection(GL_TRIANGLE_STRIP):
|
||||
glColor3f(0.81, 1, 0.82)
|
||||
glVertex2f(x1, y1)
|
||||
glVertex2f(x2, y1)
|
||||
glColor3f(0, 0.83, 0.16)
|
||||
glVertex2f(x1, y3)
|
||||
glVertex2f(x2, y3)
|
||||
glVertex2f(x1, y4)
|
||||
glVertex2f(x2, y4)
|
||||
glColor3f(0.37, 0.92, 0.43)
|
||||
glVertex2f(x1, y2)
|
||||
glVertex2f(x2, y2)
|
|
@ -73,23 +73,35 @@ class World(object):
|
|||
self.tick = 0
|
||||
|
||||
self.callback = callback
|
||||
self._phase = 'Parsing configuration...'
|
||||
self._parse(file)
|
||||
del self.callback # So it can't be used after loading finishes
|
||||
|
||||
def _eval(self, value):
|
||||
return eval(str(value), {'__builtins__': None}, self.context)
|
||||
return eval(str(value), {'__builtins__': None}, self._context)
|
||||
|
||||
def _parse(self, file):
|
||||
self.callback('Loading configuration file...', 0)
|
||||
self.callback(self._phase, '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._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}
|
||||
|
||||
tick = root.get('tick', 4320) # How many second is a tick?
|
||||
self.tick_length = tick
|
||||
|
||||
# Need to know how many objects are being loaded
|
||||
self._objects = 0
|
||||
self._current_object = 0
|
||||
|
||||
def count_objects(bodies):
|
||||
for body in bodies.itervalues():
|
||||
self._objects += 1
|
||||
count_objects(body.get('satellites', {}))
|
||||
count_objects(root['bodies'])
|
||||
print self._objects, 'objects to be loaded...'
|
||||
|
||||
if 'start' in root:
|
||||
info = root['start']
|
||||
x = self._eval(info.get('x', 0))
|
||||
|
@ -102,11 +114,21 @@ class World(object):
|
|||
self.direction = (pitch, yaw, roll)
|
||||
|
||||
for planet, info in root['bodies'].iteritems():
|
||||
print 'Loading %s.' % planet
|
||||
message = 'Loading %s.' % planet
|
||||
print message
|
||||
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
||||
message, float(self._current_object) / self._objects)
|
||||
self._body(planet, info)
|
||||
self._current_object += 1
|
||||
|
||||
for name, info in root['belts'].iteritems():
|
||||
print 'Loading %s.' % name
|
||||
if 'belts' in root:
|
||||
self._phase = 'Loading belts...'
|
||||
self._current_object = 0
|
||||
for name, info in root['belts'].iteritems():
|
||||
message = 'Loading %s.' % name
|
||||
print message
|
||||
self.callback(self._phase, message, float(self._current_object) / len(root['belts']))
|
||||
self._belt(name, info)
|
||||
|
||||
def _belt(self, name, info):
|
||||
x = self._eval(info.get('x', 0))
|
||||
|
@ -143,9 +165,9 @@ class World(object):
|
|||
yaw = self._eval(info.get('yaw', 0))
|
||||
roll = self._eval(info.get('roll', 0))
|
||||
rotation = self._eval(info.get('rotation', 86400))
|
||||
radius = self._eval(info.get('radius', self.length)) / self.length
|
||||
radius = self._eval(info.get('radius', self._length)) / self._length
|
||||
background = info.get('background', False)
|
||||
orbit_distance = self._eval(info.get('orbit_distance', self.au))
|
||||
orbit_distance = self._eval(info.get('orbit_distance', self._au))
|
||||
division = info.get('division', max(min(int(radius / 8), 60), 10))
|
||||
|
||||
if 'texture' in info:
|
||||
|
@ -183,7 +205,7 @@ class World(object):
|
|||
speed = info.get('orbit_speed', 1)
|
||||
type = Satellite
|
||||
params.update(parent=parent, orbit_speed=speed,
|
||||
distance=distance / self.length, eccentricity=info.get('eccentricity', 0),
|
||||
distance=distance / self._length, eccentricity=info.get('eccentricity', 0),
|
||||
inclination=info.get('inclination', 0), longitude=info.get('longitude', 0),
|
||||
argument=info.get('argument', 0))
|
||||
|
||||
|
@ -240,5 +262,9 @@ class World(object):
|
|||
(pitch, yaw, roll), **params))
|
||||
|
||||
for satellite, info in info.get('satellites', {}).iteritems():
|
||||
print 'Loading %s, satellite of %s.' % (satellite, name)
|
||||
self._body(satellite, info, object)
|
||||
message = 'Loading %s, satellite of %s.' % (satellite, name)
|
||||
print message
|
||||
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
||||
message, float(self._current_object) / self._objects)
|
||||
self._body(satellite, info, object)
|
||||
self._current_object += 1
|
Loading…
Reference in a new issue