Add a game loop

alf
Alfred Melch 5 years ago
parent 34e61adbe8
commit 3ad7b61b7d

@ -5,9 +5,13 @@ from flask_cors import CORS
from ebermergen.models.game import Game
from .lib import generate_map
from .lib.ebermergen_game import EbermergenGame
app = Flask(__name__)
CORS(app)
games = {}
@app.route('/')
def index():
@ -29,3 +33,21 @@ def state():
a = Game()
a.seed_map()
return jsonify(a.serialize())
@app.route('/lala')
def lala():
return jsonify({k: v.state for (k, v) in games.items()})
@app.route('/new-game/<name>', methods=['GET', 'POST'])
def new_game(name):
games[name] = EbermergenGame()
games[name].start_game()
return jsonify({'message': 'success'})
@app.route('/action/<name>/<type>')
def action(name, type):
games[name].perform_action(type, {})
return jsonify({'message': 'success'})

@ -0,0 +1,50 @@
import atexit
import time
import threading
import queue
from .gameloop import GameLoop
def tick(dt, first, second):
print('%.2f' % dt, first, second)
pass
def worker(state, action_queue):
state['counter'] = 0
state['actions'] = []
loop = GameLoop(tick=tick, fps=1, fixed_dt=True, args=(1, 2))
while True:
item = action_queue.get()
if item['action'] == 'STOP':
loop.stop()
if item['action'] == 'START':
loop.start()
state['counter'] += 1
state['actions'].append(item['action'])
class EbermergenGame:
"""Runs a single game instance
Holds the serialized state.
Provides methods to perform actions.
"""
def __init__(self):
self.state = {}
self.actions = queue.Queue()
self.thread = threading.Thread(
target=worker, args=(self.state, self.actions))
def start_game(self):
self.thread.start()
atexit.register(self.interupt)
def interupt(self):
# handle gracefull shutdown
pass
def perform_action(self, action, payload={}):
self.actions.put({'action': action, 'payload': payload})

@ -0,0 +1,46 @@
import threading
import time
import random
class GameLoop():
"""Implements a loop that calls tick every 1/fps
tick gets called with the time delta to the last call as parameter
if fixed_dt is True the tick function gets called with 1/fps
"""
def __init__(self, fps=1, tick=None, fixed_dt=False, args=None):
self.fps = fps
self.tick = tick if tick is not None else self.default_tick
self.args = args or tuple()
self.fixed_dt = fixed_dt
self.running = False
self.last_frame_time = time.time()
self.thread = threading.Thread(target=self.loop)
def loop(self):
while self.running:
current_time = time.time()
dt = current_time - self.last_frame_time
self.last_frame_time = current_time
if self.fixed_dt:
self.tick(1 / self.fps, *self.args)
else:
self.tick(dt, *self.args)
sleep_time = (1 / self.fps) - (time.time() - self.last_frame_time)
if sleep_time > 0:
time.sleep(sleep_time)
def start(self):
self.running = True
self.thread.start()
def stop(self):
self.running = False
def default_tick(self, dt):
print('ticked. Last tick was %.2f seconds ago' % dt)
time.sleep(random.choice([0.4, 0.5, 0.6, 1.4, 2.1]) * 1/self.fps)

@ -5,6 +5,8 @@ from .player import Player
from .map import Map
from .entities import Town
from ebermergen.lib.gameloop import GameLoop
class Game:
def __init__(self):

Loading…
Cancel
Save