{"id":38,"date":"2013-08-18T20:15:52","date_gmt":"2013-08-18T20:15:52","guid":{"rendered":"https:\/\/blogs.scummvm.org\/richiesams\/?p=38"},"modified":"2022-05-22T20:11:35","modified_gmt":"2022-05-22T20:11:35","slug":"moving-through-time","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/richiesams\/2013\/08\/18\/moving-through-time\/","title":{"rendered":"Moving through time"},"content":{"rendered":"<div id=\"post-body-2729120286190087495\" class=\"post-body entry-content\">Before I start, I know it&#8217;s been a long time since my last post. Over the next couple days I&#8217;m going to write a series of posts about what I&#8217;ve been working on these last two weeks. So without further ado, here is the first one:<\/p>\n<p>While I was coding in the last couple of weeks, I noticed that every time I came back to the main game from a debug window, the whole window hung for a good 6 seconds. After looking at my run() loop for a bit, I realized what the problem was. When I returned from the debug window, the next frame would have a massive deltaTime, which in turn caused a huge frame delay. This was partially a problem with how I had structured my frame delay calculation, but in the end, I needed a way to know when the game was paused, and to modify my deltaTime value accordingly.<\/p>\n<p>To solve the problem, I came up with a pretty simple Clock class that tracks time, allows pausing, (and if you really wanted scaling\/reversing):<\/p>\n<pre class=\"brush:cpp\">\/* Class for handling frame to frame deltaTime while keeping track of time pauses\/un-pauses *\/\r\nclass Clock {\r\npublic:\r\n    Clock(OSystem *system);\r\n\r\nprivate:\r\n    OSystem *_system;\r\n    uint32 _lastTime;\r\n    int32 _deltaTime;\r\n    uint32 _pausedTime;\r\n    bool _paused;\r\n\r\npublic:\r\n    \/**\r\n     * Updates _deltaTime with the difference between the current time and\r\n     * when the last update() was called.\r\n     *\/\r\n    void update();\r\n    \/**\r\n     * Get the delta time since the last frame. (The time between update() calls)\r\n     *\r\n     * @return    Delta time since the last frame (in milliseconds)\r\n     *\/\r\n    uint32 getDeltaTime() const { return _deltaTime; }\r\n    \/**\r\n     * Get the time from the program starting to the last update() call\r\n     *\r\n     * @return Time from program start to last update() call (in milliseconds)\r\n     *\/\r\n    uint32 getLastMeasuredTime() { return _lastTime; }\r\n\r\n    \/**\r\n     * Pause the clock. Any future delta times will take this pause into account.\r\n     * Has no effect if the clock is already paused.    \r\n     *\/\r\n    void start();\r\n    \/**\r\n     * Un-pause the clock.\r\n     * Has no effect if the clock is already un-paused.    \r\n     *\/\r\n    void stop();\r\n};\r\n<\/pre>\n<p>I&#8217;ll cover the guts of the functions in a bit, but first, here is their use in the main run() loop:<\/p>\n<pre class=\"brush:cpp\">Common::Error ZEngine::run() {\r\n    initialize();\r\n\r\n    \/\/ Main loop\r\n    while (!shouldQuit()) {\r\n        _clock.update();\r\n        uint32 currentTime = _clock.getLastMeasuredTime();\r\n        uint32 deltaTime = _clock.getDeltaTime();\r\n\r\n        processEvents();\r\n\r\n        _scriptManager-&gt;update(deltaTime);\r\n        _renderManager-&gt;update(deltaTime);\r\n\r\n        \/\/ Update the screen\r\n        _system-&gt;updateScreen();\r\n\r\n        \/\/ Calculate the frame delay based off a desired frame time\r\n        int delay = _desiredFrameTime - int32(_system-&gt;getMillis() - currentTime);\r\n        \/\/ Ensure non-negative\r\n        delay = delay &lt; 0 ? 0 : delay;\r\n        _system-&gt;delayMillis(delay);\r\n    }\r\n\r\n    return Common::kNoError;\r\n}\r\n<\/pre>\n<p>And lastly, whenever the engine is paused (by a debug console, by the Global Main Menu, by a phone call, etc.), ScummVM core calls\u00a0<i>pauseEngineIntern(bool pause)<\/i>, which can be overridden to implement any engine internal pausing. In my case, I can call Clock::start()\/stop()<\/p>\n<pre class=\"brush:cpp\">void ZEngine::pauseEngineIntern(bool pause) {\r\n    _mixer-&gt;pauseAll(pause);\r\n\r\n    if (pause) {\r\n        _clock.stop();\r\n    } else {\r\n        _clock.start();\r\n    }\r\n}\r\n<\/pre>\n<p>All the work of the class is done by update(). update() gets the current time using getMillis() and subtracts the last recorded time from it to get \u00a0_deltaTime. If the clock is currently paused, it subtracts off the amount of time that the clock has been paused. Lastly, it clamps the value to positive values.<\/p>\n<pre class=\"brush:cpp\">void Clock::update() {\r\n    uint32 currentTime = _system-&gt;getMillis();\r\n\r\n    _deltaTime = (currentTime - _lastTime);\r\n    if (_paused) {\r\n        _deltaTime -= (currentTime - _pausedTime);\r\n    }\r\n\r\n    if (_deltaTime &lt; 0) {\r\n        _deltaTime = 0;\r\n    }\r\n\r\n    _lastTime = currentTime;\r\n}\r\n<\/pre>\n<p>If you wanted to slow down or speed up time, it would be a simple matter to scale _deltaTime. You could even make it negative to make time go backwards. The full source code can be found\u00a0<a href=\"https:\/\/github.com\/RichieSams\/scummvm\/blob\/zengine\/engines\/zengine\/clock.cpp\" target=\"_blank\" rel=\"noopener\">here<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/RichieSams\/scummvm\/blob\/zengine\/engines\/zengine\/clock.h\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Well that&#8217;s it for this post. Next up is a post about the rendering system. Until then, happy coding!<\/p>\n<p>-RichieSams<\/p>\n<div><\/div>\n<\/div>\n<div class=\"post-footer\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Before I start, I know it&#8217;s been a long time since my last post. Over the next couple days I&#8217;m going to write a series of posts about what I&#8217;ve been working on these last two weeks. So without further ado, here is the first one: While I was coding in the last couple of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-38","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/posts\/38","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/comments?post=38"}],"version-history":[{"count":1,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/posts\/38\/revisions"}],"predecessor-version":[{"id":39,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/posts\/38\/revisions\/39"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/media?parent=38"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/categories?post=38"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/richiesams\/wp-json\/wp\/v2\/tags?post=38"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}