im currently making a 2D game in Firemonkey for my Android phone using some TImage Controls and controling their positions and angles. Simple as that. I tried to use my normal way of looping, which works well/flawless in Windows but fails on Android.
Method #1: "End-less" loop (Bad)
My main problem is that I want to avoid unwanted/unexpected behaviour by using an "end-less loop" like this where I have to call Application.ProcessMessages()
:
while (Game.IsRunning()) do
begin
{ Update game objects and stuff }
World.Update();
{ Process window messages, or the window will not respond anymore obviously }
Application.ProcessMessages(); { And thats what i want to avoid }
end;
The problem is that as im stuck in the loop and also calling the procedure to process messages, I can run into many problems, and also I just don't think that it is a good way.
Method #2: TTimer (Dont even think about it ;-) )
Since TTimer is awful in many ways and not meant to be used for such thing, the approach where i just put a TTimer with a minimum interval falls off. Also I never tried other Timers than that, but if there is one truly for Games, I will try it of course :)
Method #3: OnIdle - How I normally do it on Windows
On Windows I can use the Application.OnIdle-Event.
procedure GameLoop(Sender: TObject; var Done: Boolean);
begin
{ Update game objects and stuff }
World.Update();
{ Set done to false }
Done := False;
end;
...
Application.OnIdle := GameLoop;
It is being called everytime the Application is Idling over the windows messages. The performance seems to be the same or a little worse, compared to #1, and the overall architecture much more reliable which is the reason why I normally use this method. On Android however it seems that it is being called differently when combined with TForm.MouseMove. Where on Windows OnIdle keeps working perfectly, on Android it will lag/stop while TForm.MouseMove is being called from a touch input (RAD Studio compiles it into touch events automaticlly)
I can however fire OnIdle by myself in the MouseMove Event by calling Application.DoIdle
and "assist" the "Loop" where i think it misses out beimg called but this works also really bad and brings again unwanted behavoir and a worse performance when working with touch input.
And this brings me back to method #1 and it seems to work the best on Android for now. Is there any other way of creating a reliable way (a constantly and fast called event like OnIdle or so) of creating such a loop or any way to avoid the problems im facing in method #3 combined with the MouseMove-Events? It seems like the Android phone isnt powerful enough to have enough "Idle-Time" next to the form-events and the world updates
Also, could I consider using a thread for the world logic and next to it the method #1 on my Main-Form/Thread to update the rendering? Is it safe to update the form controls by the endless loop (with Application.ProcessMessages()) and getting the to shown data from another thread working on the world, objects and so?