Using mode 15 (220x176, 16 colors) I noticed a strange behavior with frame rate. If I set the frame rate at 30, the FPS counter displays 25. If I set the frame rate at 60, the FPS counter displays 50. I tried to look a bit in the Pokitto lib but nothing obvious explains that.
My guess is that the display is 50Hz and there is some vsync?
It could be because in the update-function there is nextFrameMillis = getTime()+timePerFrame (and not nextFrameMillis += timePerFrame). So the next frame gets rendered timePerFrame milliseconds from when the previous update actually started, which could be a few milliseconds late.
Indeed there is a rounding error but in the ‘other direction’. At 60 FPS the interval should be 16.666666 but because of the integer division the interval is 16. So it should be even a bit faster.
Indeed this seems to be the issue. Applying your proposed fix the FPS is correct.
I do believe it’s important to have the correct frame rate so I think it should be fixed. The issue is that this breaks compatibility fix existing games as they will run faster My proposal is to use a per-processor variable so that in My_settings.h it’s possible to add something like ‘#define ACCURATE_FPS’ to have the correct behavior. If you guys think it’s worth it I could do a pull request for that.
There is at least one thing to consider before doing this change.
When the game starts, (nextFrameMillis initialized to 0) if it takes for example 5 seconds for the game to start running the update-loop, then the first 150+ frames are rendered in one burst until nextFrameMillis catches up with the timer. Same thing later during excecution if the game pauses updates while loading resources from sd card or something.
Adding a simple check might be sufficient:
if nextFrameMillis is lagging more than one frame, then use the current method and set its value to now+timePerFrame.
I tend to disagree. This is mostly true for ‘modern’ games that use a floating point delta time. Personally even in this case I sometime makes assumption based on the frame, for example when applying friction to an entity (e.g. multiply velocity by 0.9 each frame).
But for retro game based on integer I think it’s critical to have known frame rate. If the players moves by 1 pixel every frame it should always result to the same movement speed. Another issue is related to the low resolution. Generally you need to move the entities at a constant speed (e.g. 2 pixel each frame) to prevent jaggerness. If you take delta time (that is constant between frames) into consideration the multiplication might result in entities not moving constantly (e.g. 2 pixel, 2 pixel, 3 pixel, 2 pixel, 2 pixel).
Not sure it can be fixed. The issue is that it seems we only have time in milliseconds, so we need to round the interval into a number of milliseconds. Oh do you mean rounding 16.666… into 17 instead of 16?
This is the first thing I noticed after patching the code. When the game started, it was super fast for few seconds before going to normal. To solve that I currently use a flag to know the first frame. When the first frame is played nextFrameMillis is set to current time.
Last issue, which I’m not sure about,it feels like after the patch movement is a bit jaggier than before. I will need to investigate further. I think what happens is the delta slowly drifts and suddenly two frames are played to catch up. I’m afraid this is not the end of the story.
The correct rounding to milliseconds would improve the situation. But to get rid of the cumulative error (or reducenit significantly) in the calculation “nextFrameMillis += timePerFrame” would require to save those times in microseconds. Thought, I cannot say how much it really affects to FPS accuracy which however is in integer resolution.
You don’t need to avoid float on the Pokitto,
unless you’ve measured and it definitely isn’t fast enough for your game.
Don’t forget the Cortex-M0 is a 32-bit processor,
and memory isn’t as much of an issue as on certain other systems.
But even then you only need it to accumulate time,
you don’t have to use it for physics calculations.
You can have a fixed-time update step, e.g. 1 update every 10 milliseconds),
accumulate the delta time and only run an update step every time 10ms has elapsed.
(If 20ms has accumulated, do two update steps.)
(This is the ‘semi-fixed timestep’ approach described in the famous fix your timestep article.)
Fixed point arithmetic is also an option if floating point won’t suffice.
That exactly the solution I’m aiming for. Do anybody know how to get microseconds time?
Looking at the code currently getTime() use systick interrupt to increment an internal counter. The actual precision is not even milliseconds. The interrupt rate is 100Hz and the counter is increased by 10 each tick. Not sure why.