Video Games and Time
23rd October 2015
Creating video games is both fun and complex, yet the simple things are often poorly or incorrectly implemented. Many games, especially those coming to PC for the first time are created in the mind-set that framerate is king, much to the dismay of many a player. By making sure you implement a small number of these key principles you can prevent your game from operating inadequately, and from it being received in a pit of social flames.
Start at the Delta
Delta time is one of the most important principles to understand when developing video games, poor implementations of delta time can have adverse effects while a complete lack of it will bind your logic to your frame rate (which is REALLY bad). The function of delta time is to report how many milliseconds that it took for the previous frame to process, thus allowing you to work with a percentage of what should have been accomplished over a specific time frame. By using the delta time for game logic rather than a counter or ticker (based on the current frame count) you remove any issues that may arise with the processing power on the user's machine, thus keeping animation and movement consistent across frames.
The above code is an example of how to implement delta time into your game, however there are a number of simple variations on the procedure. For example, if you are using SDL with your game then you can take advantage of the "SDL_GetTicks()" function which operates in a similar fashion, however it reports the integer number of ticks, rather than the milliseconds. You can then be assured that the functions will work across platforms without hiccups.
Engines such as Unity already have delta time built into them and use larger selections of functions for time. Calling such functions within Unity is as simple as using "Time.deltaTime" and is available within any script you create for it (even if it is C#).
Keep It Together
One of the easiest things to do when controlling time within the world of your game, rather than just differences in time, is to unify exactly where you're getting your current time value from. Making sure you keep the original time value and allowing it to be accessed is good practice as it prevents discrepancies between game logic updates. Only update the overall value in one base class, this'll will not only be easier to manage but will prevent any variations in time when using functions between classes (if a class updates before one another then the time values they have could be different and thus timed logic would be inconsistent).
A usage example would be expiring status effects for a player where you would generate them by getting the current time from the time class and then adding the duration time value, thus reporting the expiration time. This would then be handled once the time value reaches the expiration time.
This is less so much about time being the issue but more of a tip for both organisation sanity. Your time class doesn't have to be limited to a few functions either, you could even pass in the delta time directly to it, thus removing the need to constantly pass float values to functions and class update functions.
Not all of the game logic will need to update on a constant, frame by frame, basis meaning you can defer some of your logic to specified intervals. Simple modular maths can be used to perform a function every X number of seconds based upon the original time value that you get from your time class. Keeping it as a difference between time, rather than an incrementing counter will prevent unwanted increases or decreases in logic speed when the frame rate may dip.
Sure at some point if the game hangs for slightly longer then it may cause issues with repeated commands being issued, this can be simply fixed by changing it from modular maths to an integer division. If the value is yet to reach what should have been the correct number of updates then it will continue to do so until it catches up or can allow you to make it skip stages (if unnecessary).
Note this doesn't mean you should bind all of your logic to specified update intervals or the implementation of delta time becomes meaningless. Games such as "Need for Speed: Rivals" used a strange approach in that the player logic and frame rate were bound to two different variables of exactly the same value. This meant that as soon as you changed the frame rate limiter it would cause the player logic (physics, speed, acceleration, etc.) to become a multiple of that, however nothing else within the world would be affected. Obviously this was incredibly well received in the gaming community.