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 {}