gpt4 book ai didi

iphone - iOS 游戏和运行循环管理

转载 作者:IT王子 更新时间:2023-10-29 07:51:55 27 4
gpt4 key购买 nike

首先,我的问题是:您如何管理您的 iOS Run-Loop?

接下来是我的原因:我一直在用各种原型(prototype)(v. 早期开发)对此进行研究,并发现了许多令人困惑的问题。

  • 首先,输入问题和运行循环引导我尝试以下操作:
    • 在使用最推荐的系统 (CADisplayLink) 时,我注意到一旦 CPU 负载导致缓冲区翻转 (presentRenderBuffer) 必须等待一帧,某些触摸输入就会被丢弃。这只发生在设备上而不是模拟器中(令人讨厌的是 - 这似乎与等待主线程上的 vsync 阻塞以及应用程序运行循环处理触摸输入和吃消息的方式有关)
    • 在使用下一个最受推荐的系统 (NSTimer) 时,我注意到一旦 CPU 负载在模拟器中达到某个点但在设备中却没有(这也很烦人),某些触摸输入会被丢弃。 NSTimer 还会导致更新触发时的精度大大降低
    • 当使用最不推荐的系统时(在它自己的线程中运行运行循环,该线程使用从 mach_absolute_time 构建的高精度计时器在内部管理,我所有的触摸输入问题都消失了,但是我的 ASSERT 代码现在陷入了错误的线程并且只如果我在软件中断后 usleep。(我的断言代码类似于 http://iphone.m20.nl/wp/?p=1)我真的很喜欢让我的断言代码立即陷入导致问题的行,所以这个解决方案对我来说并不可行:更难调试。
  • 第二,浪费的时间:
    • 在调查系统时,我发现无论帧率如何(很奇怪,但我认为统计上它仍然有意义 w/vsync)我大约有 22% 的时间在等待 vsync。我已经通过移动 glFlush/glFinish 并测试我调用 presentRenderBuffer 的频率来确认这一点。这是我喜欢处理 AI 等的关键时间,而不是简单地停止阻塞 gl 调用。我能想到的解决这个问题的唯一方法是将渲染移到它自己的线程中,但我不确定是否有必要在单处理器设备上开始重新构建多线程架构。

那么有没有人找到解决这些问题的 Elixir ?有没有人拥有在这个平台上表现出色的 killer 级运行循环架构?目前看来我必须取其轻者。

最佳答案

对于我自己的 iOS 项目,我使用经典的方法(创建一个窗口 .nib,创建一个继承 EAGLView 的类,将 EAGLView 添加到 View Controller 中的 View 它被放置在它自己的 .nib 中)。

在工作中,我采用了受 SDL 启发而略有不同的方法,您可以在我们的开源库 APRIL 中查看它. APRIL 的主要目标是支持尽可能多的平台,同时保持简单性(仅窗口和输入管理)并清楚许可问题并免费使用。我们的开发人员希望在一个平台(Windows、Mac 或 Linux,根据喜好和需求)上编写应用程序,然后将代码交给我以适应其他平台。

在我们在 APRIL 中使用的方法中,您不创建任何 .nib,并且在调用 UIApplicationMain 时,您将委托(delegate)类指定为它的第四个参数。游戏的主要代码对于每个平台都保持完全相同,只有特定于平台的内容被 #ifdef 放入代码中,或者在辅助库中抽象出来。

在应用委托(delegate)中创建 View Controller 和窗口:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
// create a window.
// early creation so Default.png can be displayed while we're waiting for
// game initialization
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// viewcontroller will automatically add imageview
viewController = [[AprilViewController alloc] initWithWindow:window];
[viewController loadView];

// set window color
[window setBackgroundColor:[UIColor blackColor]];

// display the window
[window makeKeyAndVisible];

// thanks to Kyle Poole for this trick
// also used in latest SDL
// quote:
// KP: using a selector gets around the "failed to launch application in time" if the startup code takes too long
// This is easy to see if running with Valgrind

[self performSelector:@selector(runMain:) withObject:nil afterDelay:0.2f];
}

请注意我们如何将启动延迟 0.2?这就是为什么我在上面提到 ImageView 。在那 0.2 秒内,我们会在 Default.png 之后立即显示空白屏幕,并且在控制权转移到 runMain: 之前引入了额外的延迟,这会将控制权释放给主应用程序:

- (void)runMain:(id)sender
{
// thanks to Kyle Poole for this trick
char *argv[] = {"april_ios"};
int status = april_RealMain (1, argv); //gArgc, gArgv);
#pragma unused(status)
}

因此,现在控制永远不会转移回 UIApplication 的实际主循环。然后创建自己的主循环。

    void iOSWindow::enterMainLoop()
{
while (mRunning)
{
// parse UIKit events
doEvents();
handleDisplayAndUpdate();
}
}

void iOSWindow::doEvents()
{
SInt32 result;
do {
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
} while(result == kCFRunLoopRunHandledSource);
}

(附带说明,当然,使用 View Controller 来简化 UI 的旋转以匹配设备方向。)

如果操作系统支持,这两种方法都使用 CADisplayLink。我没有注意到这两种方法有任何问题,尽管我的私有(private)项目主要是基于加速度计的。我怀疑 APRIL 方法也可能会解决一些问题。

关于iphone - iOS 游戏和运行循环管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4817992/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com