我正在使用一些TImage控件并控制它们的位置和角度为我的Android手机制作Firemonkey中的2D游戏。就那么简单。我试图用我正常的循环方式,它在Windows中运行良好/无瑕,但在Android上失败。Android版Firemonkey中的游戏循环
方法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;
的问题是,作为即时通讯卡在循环,也要求来处理消息的程序,我可以碰到很多问题,而且我不认为这是一个很好的办法。
方法2:TTimer(甚至不想想;-))
由于TTimer在许多方面是可怕的,并不意味着用于这样的事情,该方法,即我只是把一个TTimer最小间隔下降。此外,我从来没有尝试过其他计时器比,但如果有一个真正的游戏,我会尽量当然:)
方法#3的是:的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消息上徘徊时都会调用它。与#1相比,性能似乎相同或更差,整体架构更加可靠,这就是我通常使用这种方法的原因。然而,在Android上,它与TForm.MouseMove结合起来似乎被称为不同的。 OnIdle在Windows OnIdle上一直保持正常工作,在Android上,它会在触摸输入中调用TForm.MouseMove时延迟/停止(RAD Studio自动将它编译为触摸事件)
但是我可以在MouseMove中自己触发OnIdle通过调用Application.DoIdle
和“协助”“循环”,我认为它错过了被称为beimg的事件,但这种方法也非常糟糕,并且在使用触摸输入时会带来不必要的行为和更糟的性能。
这让我回到方法#1,它似乎现在在Android上效果最好。有没有其他的方式来创建一个可靠的方法(像OnIdle这样一个持续而快速的被称为事件)创建这样一个循环或以任何方式来避免方法#3与MouseMove事件结合所面临的问题?看起来Android手机没有足够强大的功能,足以在格式事件和世界更新旁边拥有足够的“空闲时间”
此外,我可以考虑使用线程作为世界逻辑,并且在它旁边使用方法# 1在我的主窗体/线程上更新渲染?通过无限循环(使用Application.ProcessMessages())更新表单控件并从另一个处理世界上的线程,对象等获取所显示的数据是否安全?
您可以使用匿名线程(与之同步)来实现这一 – nolaspeaker
如果你想避免游戏循环滞后FireMonkey UI引起那么你最好的选择是将所有的游戏逻辑到辅助线程。但即便如此,如果目标设备只有一个处理核心,这可能会完全解决您的问题。您看到FireMonkey在处理UI消息时非常糟糕/缓慢。作为一项测试,只需创建一个新的FireMonkey应用程序,并在窗体上放置大约100个面板。然后对其进行编译并观察鼠标在您的表单上的移动速度如何会导致CPU使用率显着上升。 ... – SilverWarior
...这样的测试是能够最大限度地利用我的7岁笔记本电脑的CPU使用率,它不仅仅是一些弱电笔记本,因为我可以在媒体设置上播放Far Cry 3而不会有任何问题。现在我可以想象使用这种情况下FireMonkey在手机上会导致哪种CPU使用率。这就是为什么我不考虑使用FireMonkey进行任何游戏开发。 – SilverWarior