Time
Time is an essential thing. It is utilized in every computer game, it is used in game logic, animations, visual effects and user input handling.
But how exactly time is measured on WOWCube device?
As we already know, the WOWCube device is built out of eight modules with its own CPU and memory. Each runs CubiOS operating system that hadles hardware components of the module. One of the components is a clock, a device that produces ticks at some very high, constant frequency. Once module is started, it begins to do these ticks and it never stops. So knowing the number of ticks passed between two moments we can actually see how long it took or how much time passed.
Time ticks are very important for all CubiOS internal function too. Graphics on screens, memory, sensors and power - all this obeys the rhythm set by the internal clock. All ongoing processes that run insinde WOWCube use time. If internal clock stops, device turns unresponsive.
So in order to create a cubeapp that implements any kind of dynamics, we would want to use the time as well, right?
But how do we know that tick has elapsed? How do we know how fast this happened?
For that, on_Tick(uint32_t currentTime, uint32_t deltaTime) callback is used. It is called by CubiOS every time new tick passes, as frequent as device can do.
Using this callback, we can do multiple useful things with time. Most typical tasks are to calculate time elapsed from the last iteration of game logic (i.e last frame) and implement a timer that ticks with given periodicity.
Let's take a look at the example.
Getting elapsed time
Firstly, we would want to know time elapsed between two calls of on_Tick() callback.
This is extremely simple thing to do since the value we're looking for is already provided as a second parameter of the callback, deltaTime. Its value is measured in milliseconds.
A millisecond (from milli- and second; symbol: ms) is a thousandth (0.001 or 1/1000) of a second.
Pay attention!
The calling frequency of
on_Tick()callback is not guaranteed to be constant, may vary and depends on the actual CPU load of the module. The load, in turn, depends on a complexity of a codeon_Tick()callback implements. More complex the code is, more CPU load is put.
Implementing a programmable timer
Timer is a specialized type of clock used for measuring specific time intervals.
Programmable Timer is a software object that is used for measuring equal time intervals, which can be uniquely identified, started or put on hold or destroyed.
As we know, each cubeapp is derived from Cubios::Application application class. This class provide the following functions to manage programmable timers:
Using programmable timers it is very easy to implement recurrent in-game actions that happen each 1, or 5, or 10 seconds.
Let's see the code. First, a timer must be created and initialized. This is done in InitializeResources() function that is called from OnInit() callback when cubeapp is started:
The timer delay is initialized with 1000 milliseconds or 1 second. This means the on_Timer(uint8_t timerID) callback will be called every second as long as the timer is running:
Measuring FPS
Frame rate (expressed in frames per second or FPS) is the frequency (rate) at which consecutive images (frames) are displayed on module screens.
FPS is one of the most important metrics of any computer game with graphics. It is essential to keep it at acceptable rates while the game plays. Sudden drops of FPS value may get user dissatisfied with the game.
The way of calculation of FPS is rather trivial: as long as we know deltaTime, the FPS value would be calculated as
Rendering results
It's a final part of the excercise, and it is quite simple.
In order to render time values, three simple steps are taken inside on_Render() callback:
-
Clear the screen
-
Render the text with values
-
Commit changes
Time and TimersCPPWrapped for easier reading. Turn wrap off to inspect exact line lengths.