I wrote some games years ago, and they were always in sync with the main thread. So, for example if the monitor refresh rate is 60 Hz it would look like below.
OnPaint =
Advance game 1/60th of a second
Render at 60 FPS
This works well for arcade type games, but not necessarily for other game types.
I want to run something more like this:
Game logic at 10 FPS
Render at 60 FPS
This is mainly because the "game logic" takes much longer than 16 ms now.
I still want to render at 60 FPS, because the animations run faster than 10 FPS, and also the moving of sprites needs to be smooth. I don't see the point in moving a sprite from 0 to 10 to 20, etc. It should move at a higher constant rate, e.g. from 0 to 1 to 2, etc.
So, I was thinking of adding a game logic thread:
Game thread =
Setup animations
Setup physics, e.g. move object to x/y at some speed, and direction, etc
OnPaint =
Update animations and sprite positions
Render
This then means there has to be some kind of sprite object between the two threads.
ISprite = interface
x/y: integer
width/height: integer;
image: PImage;
end;
So, the game logic then sets up the x/y, the image (or animation), and the OnPaint then renders it to the screen. The OnPaint also advances the x/y according to the direction and speed, which makes for smooth moving.
So, the game logic might say "animate sequence X on sprite Z", or "move sprite Z to x/y at speed/direction" (the physics), and the OnPaint then takes whatever frames to complete that smoothly.
I would need to add a lock for accessing the sprite data.
ISprite = interface
BeginUpdate(); // acquire lock
x/y: integer
width/height: integer;
image: PImage;
EndUpdate(); // release lock
end;
The idea is to lock the entire object, so there won't be any glitches where the sprite appears at the wrong location temporarily, because the render came after setting X, but before setting Y, etc.
I will also have to be extremely careful with other objects, e.g. the list of sprites needed in both threads, etc.
Is all that even right?!? Is there an easier way to achieve all this? Am I missing something obvious here? :)
Maybe I should just compromise and run the game logic, and the rendering all at say 40 FPS. Or 30. At least then, I won't need any threads...
Any thoughts on this? :)