1 /**
2  * Retrograde Engine
3  *
4  * Authors:
5  *  Mike Bierlee, m.bierlee@lostmoment.com
6  * Copyright: 2014-2021 Mike Bierlee
7  * License:
8  *  This software is licensed under the terms of the MIT license.
9  *  The full terms of the license can be found in the LICENSE.txt file.
10  */
11 
12 module retrograde.engine;
13 
14 import retrograde.game;
15 import retrograde.application;
16 import retrograde.stringid;
17 import retrograde.messaging;
18 
19 import std.datetime.stopwatch;
20 import std.stdio;
21 import std.string;
22 
23 const uint VERSION_MAYOR = 0;
24 const uint VERSION_MINOR = 0;
25 const uint VERSION_REVISION = 0;
26 
27 const uint COPYRIGHT_YEAR = 2017;
28 
29 public string getEngineName() {
30     return "Retrograde Engine";
31 }
32 
33 public string getEngineVersionText() {
34     return format("v%s.%s.%s", VERSION_MAYOR, VERSION_MINOR, VERSION_REVISION);
35 }
36 
37 public string getEngineCopyrightText() {
38     return format("Copyright Mike Bierlee %s", COPYRIGHT_YEAR);
39 }
40 
41 private void logStartupInfo(Game game) {
42     auto defaultContext = new RetrogradeDefaultApplicationContext();
43     auto logger = defaultContext.logger();
44     logger.infof("%s (%s)", game.name, game.copyright);
45     logger.infof("%s %s (%s)", getEngineName(), getEngineVersionText(), getEngineCopyrightText());
46 }
47 
48 public void loopWithFixedTimeStepVariableDrawRate(Game game) {
49     auto frameTimeStopWatch = new StopWatch();
50     auto lag = Duration.zero;
51     frameTimeStopWatch.start();
52 
53     while (!game.terminatable) {
54 
55         auto elapsedFrameTime = frameTimeStopWatch.peek();
56         frameTimeStopWatch.reset();
57         lag += elapsedFrameTime;
58 
59         auto targetFrameTime = dur!"msecs"(game.targetFrameTime);
60         auto lagCompensationFrames = 0L;
61         while (lag >= targetFrameTime) {
62             lagCompensationFrames++;
63             if (lagCompensationFrames > game.lagFrameLimit || game.terminatable) {
64                 break;
65             }
66 
67             game.update();
68             lag -= targetFrameTime;
69         }
70 
71         game.render(lag / targetFrameTime);
72     }
73 }
74 
75 public void start(Game game, void function(Game game) gameLoopFunction = &loopWithFixedTimeStepVariableDrawRate) {
76     alias executeGameLoop = gameLoopFunction;
77 
78     logStartupInfo(game);
79     game.initialize();
80     executeGameLoop(game);
81     game.cleanup();
82 }
83 
84 enum EngineCommand : StringId {
85     quit = sid("cmd_quit")
86 }
87 
88 public void registerEngineDebugSids(SidMap sidMap) {
89     sidMap.add("cmd_quit");
90 }
91 
92 class CoreEngineCommandChannel : CommandChannel {}