Here the bare bone of my project. Example above works with this code and my project.
pyscene.py
import os
import pygame
import tick_timer
class Screen:
set_scene = None
running = False
scenes = {}
@classmethod
def add_scene(cls, scene, name=None):
if name is None:
name = type(scene).__name__
cls.scenes[name] = scene
@staticmethod
def center():
os.environ['SDL_VIDEO_CENTERED'] = '1'
@classmethod
def open(cls, caption, size, flags=0, depth=0):
pygame.init()
cls.size = size
cls.current_scene = Scene()
pygame.display.set_caption(caption)
cls.surface = pygame.display.set_mode(size, flags, depth)
cls.clock = pygame.time.Clock()
cls.running = False
@classmethod
def close(cls):
cls.running = False
@classmethod
def loop(cls, start_scene=None, fps=60):
cls.fps = fps
cls.running = True
cls.set_scene = start_scene
while cls.running:
if cls.set_scene:
cls.current_scene.screen_drop()
cls.current_scene = cls.scenes[cls.set_scene]
cls.current_scene.screen_entrance()
cls.set_scene = None
for event in pygame.event.get():
cls.current_scene.screen_event(event)
cls.current_scene.screen_blit(cls.surface)
pygame.display.flip()
cls.clock.tick(Screen.fps)
pygame.quit()
class Font:
pass
# Scene flipping
class Scene:
font = Font()
screen = Screen
def __init__(self):
# builtins
self.font = Scene.font
self.timer = tick_timer.TickTimer(pygame.time.get_ticks())
def entrance(self):
pass
def drop(self):
pass
# pygame draw code here
def blit(self, surface):
pass
# pygame events code here
def event(self, event):
pass
# interface with screen
def screen_entrance(self):
self.entrance()
self.timer._time_elaspe()
def screen_drop(self):
self.timer._stop()
self.drop()
def screen_event(self, event):
self.event(event)
def screen_blit(self, surface):
self.timer._update(pygame.time.get_ticks())
self.blit(surface)
def get_screensize(self):
return Scene.screen.size
def get_screenrect(self):
return pygame.Rect(0, 0, *Scene.screen.size)
def get_screenmid(self):
return Scene.screen.size[0] / 2, Scene.screen.size[1] / 2
def add_scene(self, scene, name=None):
Scene.screen.add_scene(scene, name)
def close_screen(self):
Scene.screen.running = False
def set_scene(self, scene):
Scene.screen.set_scene = scene
def del_scene(self, scene):
del Scene.screen.scenes[scene]
tick_timer.py
class TickTimerInfo:
def __init__(self, interval, callback, pydata):
self.next_tick = TickTimer.ticks + interval
self.interval = interval
self.callback = callback
self.pydata = pydata
self.stop = False
class TickTimer:
ticks = 0
def __init__(self, ticks):
self.callbacks = {}
self.tick_stop = 0
TickTimer.ticks = ticks
def __getitem__(self, key):
return self.callbacks[key]
def __setitem__(self, key, value):
if isinstance(value, TickTimerInfo):
self.callbacks[key] = value
def add(self, key, interval, callback, pydata=None):
self.callbacks[key] = TickTimerInfo(interval, callback, pydata)
def reset(self, key, offset=None):
if offset:
self.callbacks[key].next_tick = TickTimer.ticks + offset
else:
self.callbacks[key].next_tick = TickTimer.ticks + self.callbacks[key].interval
# pyscene.Scene use only
def _stop(self):
self.tick_stop = TickTimer.ticks
def stop(self, key):
self.callbacks[key].stop = True
def start(self, key):
self.callbacks[key].stop = False
self.callbacks[key].next_tick = TickTimer.ticks + self.callbacks[key].interval
# pyscene.Scene use only
def _time_elaspe(self):
if self.tick_stop > 0:
elaspe = TickTimer.ticks - self.tick_stop
for info in self.callbacks.values():
info.next_tick += elaspe
# pyscene.Scene use only
def _update(self, ticks):
TickTimer.ticks = ticks
for key, item in self.callbacks.items():
if item.stop is False:
if ticks > item.next_tick:
item.interval = item.callback(item)
item.next_tick += item.interval
def pop(self, key):
self.callbacks.pop(key)
99 percent of computer problems exists between chair and keyboard.