我正在使用一些TImage控件并控制它们的位置和角度,在Firemonkey中为我的Android手机制作2D游戏,就这么简单。我尝试使用在Windows上运行良好/无缺陷的常规循环方式,但在Android上失败了。
方法#1:“无限”循环(不好)
我的主要问题是想避免使用像这样的“无限循环”导致的不必要或意外的行为,在此循环中必须调用
问题在于当我陷入循环并调用处理消息的过程时,我可能会遇到许多问题。而且,我认为这不是一个好方法。
第二种方法:TTimer(甚至别想了;-))
由于TTimer在很多方面都很糟糕,而且并不适合用于这种情况,所以我放一个最小间隔的TTimer的方法不行。虽然我从未尝试过其他计时器,但如果有一种真正适用于游戏的计时器,我当然会尝试它 :)
第三种方法:OnIdle-我在Windows上通常都是这么做的
在Windows上,我可以使用Application.OnIdle事件。
每当应用程序在Windows消息上空闲时,它就被称为“OnIdle”。相比于方法#1,性能似乎相同或略差,但总体架构更可靠,这也是我通常使用此方法的原因。然而,在Android上,当与TForm.MouseMove结合使用时,它似乎被以不同的方式调用。在Windows上,OnIdle仍然工作得很完美,但在Android上,当TForm.MouseMove从触摸输入中调用时,它会出现滞后/停止(RAD Studio将其自动编译为触摸事件)。
然而,我可以通过在MouseMove事件中调用“Application.DoIdle”来手动触发OnIdle,并协助“Loop”,其中我认为它被遗漏了,但这也效果很差,并且在处理触摸输入时会带来不良行为和性能下降。
这使我回到了方法#1,并且现在看起来在Android上工作得最好。是否有任何其他可靠的方式(例如像OnIdle这样不断快速调用的事件),可以创建这样的循环或任何避免我在方法#3中遇到的问题与MouseMove事件相结合?似乎Android手机没有足够的“空闲时间”来处理表单事件和世界更新之间的切换。
此外,我是否可以考虑在我的主线程/线程上使用方法#1来更新渲染,并在旁边使用一个线程处理世界逻辑?使用无限循环(带有Application.ProcessMessages())更新表单控件并从另一个工作在世界、对象等的线程中获取显示数据是否安全?
方法#1:“无限”循环(不好)
我的主要问题是想避免使用像这样的“无限循环”导致的不必要或意外的行为,在此循环中必须调用
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;
问题在于当我陷入循环并调用处理消息的过程时,我可能会遇到许多问题。而且,我认为这不是一个好方法。
第二种方法:TTimer(甚至别想了;-))
由于TTimer在很多方面都很糟糕,而且并不适合用于这种情况,所以我放一个最小间隔的TTimer的方法不行。虽然我从未尝试过其他计时器,但如果有一种真正适用于游戏的计时器,我当然会尝试它 :)
第三种方法:OnIdle-我在Windows上通常都是这么做的
在Windows上,我可以使用Application.OnIdle事件。
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;
每当应用程序在Windows消息上空闲时,它就被称为“OnIdle”。相比于方法#1,性能似乎相同或略差,但总体架构更可靠,这也是我通常使用此方法的原因。然而,在Android上,当与TForm.MouseMove结合使用时,它似乎被以不同的方式调用。在Windows上,OnIdle仍然工作得很完美,但在Android上,当TForm.MouseMove从触摸输入中调用时,它会出现滞后/停止(RAD Studio将其自动编译为触摸事件)。
然而,我可以通过在MouseMove事件中调用“Application.DoIdle”来手动触发OnIdle,并协助“Loop”,其中我认为它被遗漏了,但这也效果很差,并且在处理触摸输入时会带来不良行为和性能下降。
这使我回到了方法#1,并且现在看起来在Android上工作得最好。是否有任何其他可靠的方式(例如像OnIdle这样不断快速调用的事件),可以创建这样的循环或任何避免我在方法#3中遇到的问题与MouseMove事件相结合?似乎Android手机没有足够的“空闲时间”来处理表单事件和世界更新之间的切换。
此外,我是否可以考虑在我的主线程/线程上使用方法#1来更新渲染,并在旁边使用一个线程处理世界逻辑?使用无限循环(带有Application.ProcessMessages())更新表单控件并从另一个工作在世界、对象等的线程中获取显示数据是否安全?