1 module armos.app.runner; 2 import armos.app; 3 import armos.utils; 4 import armos.events; 5 import armos.graphics; 6 7 /++ 8 armosのアプリケーションの更新を行うclassです. 9 +/ 10 class Runner { 11 public{ 12 /++ 13 +/ 14 this(){ 15 _fpsCounter = new FpsCounter; 16 _events = new CoreEvents; 17 } 18 19 /++ 20 イベントループに入ります. 21 Params: 22 app = 更新されるアプリケーションです. 23 +/ 24 void run(WindowType)(BaseApp app, WindowConfig config){ 25 _application = app; 26 addListener(events.setup, app, &app.setup); 27 addListener(events.update, app, &app.update); 28 addListener(events.draw, app, &app.draw); 29 addListener(events.exit, app, &app.exit); 30 31 createWindow!(WindowType)(app, config); 32 33 loop(); 34 }; 35 36 /++ 37 現在のFPS(Frame Per Second)の使用率を返します. 38 +/ 39 double fpsUseRate(){ 40 return _fpsCounter.fpsUseRate; 41 } 42 43 /++ 44 FPS(Frame Per Second)を指定します. 45 +/ 46 void targetFps(in double fps){ 47 _fpsCounter.targetFps = fps; 48 } 49 50 /// 51 double targetFps()const{ 52 return _fpsCounter.targetFps; 53 } 54 55 /// 56 double currentFps()const{ 57 return _fpsCounter.currentFps; 58 } 59 60 /// 61 Renderer renderer(){return _renderer;} 62 63 /// 64 CoreEvents events(){return _events;}; 65 66 /// 67 Window window(){return _window;} 68 }//public 69 70 private{ 71 BaseApp _application; 72 CoreEvents _events; 73 Renderer _renderer; 74 Window _window; 75 76 bool _isLoop = true; 77 FpsCounter _fpsCounter; 78 79 void createWindow(WindowType)(BaseApp app, WindowConfig config){ 80 _window = new WindowType(app, _events, config); 81 82 static if(WindowType.hasRenderer){ 83 _renderer = new Renderer; 84 } 85 86 assert(_window); 87 88 if(_renderer){ 89 _renderer.setup(); 90 } 91 }; 92 93 void loop(){ 94 _application.initHeldKeys; 95 96 _events.notifySetup(); 97 while(_isLoop){ 98 loopOnce(); 99 _fpsCounter.adjust(); 100 _fpsCounter.newFrame(); 101 _isLoop = !_window.shouldClose&&!_application.shouldClose; 102 } 103 _events.notifyExit(); 104 _window.close(); 105 } 106 107 void loopOnce(){ 108 _events.notifyUpdate(); 109 if(_renderer){ 110 _renderer.startRender(); 111 } 112 _events.notifyDraw(); 113 if(_renderer){ 114 _renderer.finishRender(); 115 } 116 _application.updateKeys; 117 _window.pollEvents(); 118 _window.update(); 119 } 120 121 }//private 122 } 123 private Runner mainLoop_; 124 Runner mainLoop() @property 125 { 126 return mainLoop_; 127 // static __gshared Runner instance; 128 // import std.concurrency : initOnce; 129 // return initOnce!instance(new Runner); 130 } 131 132 /++ 133 armosのアプリケーションを実行します. 134 Params: 135 WindowType = 立ち上げるWindowの型を指定します.省略可能です. 136 app = 立ち上げるアプリケーションを指定します. 137 +/ 138 void run(WindowType = GLFWWindow)(BaseApp app, WindowConfig config = null){ 139 mainLoop_ = new Runner; 140 if(!config){ 141 config = new WindowConfig(); 142 with(config){ 143 glVersion = SemVer(3, 3, 0); 144 width = 640; 145 height = 480; 146 } 147 } 148 mainLoop.run!(WindowType)(app, config); 149 } 150 151 /++ 152 現在のFPS(Frame Per Second)の使用率を返します. 153 +/ 154 double fpsUseRate(){ 155 return mainLoop.fpsUseRate; 156 } 157 158 /++ 159 FPS(Frame Per Second)を指定します. 160 +/ 161 void targetFps(in double fps){ 162 mainLoop.targetFps(fps); 163 } 164 165 double targetFps(){ 166 return mainLoop.targetFps; 167 } 168 169 CoreEvents currentEvents(){ 170 return mainLoop.events; 171 } 172 173 double currentFps(){ 174 return mainLoop.currentFps; 175 }