iphone store遊戲 - iOS遊戲和運行循環管理




1 Answers

對於我自己的iOS項目,我使用經典方法(創建一個窗口.nib,創建一個繼承EAGLView的類,將EAGLView添加到視圖控制器中的視圖中,該視圖控制器放在它自己的.nib中)。

在工作中,我採用了一種略微不同的方法,靈感來自SDL,您可以在我們的開源庫APRIL進行檢查。 APRIL的主要目標是支持盡可能多的平台,同時保持簡單性(僅限窗口和輸入管理)並明確許可問題並免費使用。 我們的開發人員希望在一個平台(Windows,Mac或Linux,根據品味和願望)編寫應用程序,然後將代碼交給我以適應其他平台。

在我們在APRIL中使用的方法中,您不創建任何.nib,並且在調用UIApplicationMain ,您將委託類指定為其第四個參數。 遊戲的主要代碼對於每個平台保持絕對相同,並且只有特定於平台的東西是#ifdef進入代碼,或者在幫助程序庫中抽象。

在app委託中,​​您可以創建視圖控制器和窗口:

- (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? 這就是為什麼我提到上面的圖像視圖。 在這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);
    }

(在旁注中,當然,使用視圖控制器來簡化UI的旋轉以匹配設備方向。)

如果操作系統支持,這兩種方法都使用CADisplayLink 。 我沒有註意到任何一種方法的任何問題,雖然我的私人項目主要是基於加速計。 我懷疑APRIL方法可能會使一些問題消失。

免費遊戲app推薦 store電腦版

首先,我的問題是:你如何管理你的iOS Run-Loop?

接下來我的理由是:我一直在研究各種原型(v。早期開發),並發現了許多令人困惑的問題。

  • 首先,輸入問題和運行循環使我嘗試以下方法:
    • 當使用最推薦的系統(CADisplayLink)時,我注意到一旦CPU負載導致緩衝區翻轉(presentRenderBuffer)必須等待一幀,某些觸摸輸入就會被丟棄。 這只發生在設備而不是模擬器中(令人討厭 - 這似乎與等待主線程上的vsync阻塞以及應用程序運行循環過程觸摸輸入和吃消息的方式有關)
    • 當使用下一個最推薦的系統(NSTimer)時,我注意到一旦CPU負載達到模擬器中的某個點而不是設備中的某個點(也令人討厭),某些觸摸輸入就會被丟棄。 NSTimer在我的更新發佈時也會導致精度降低
    • 當使用推薦最少的系統(在內部使用由mach_absolute_time構建的高精度定時器管理自己的線程中運行運行循環時,我的所有觸摸輸入問題都會消失,但是我的ASSERT代碼現在陷入了錯誤的線程,只有當我睡著了跟隨軟件中斷。(我的斷言代碼類似於http://iphone.m20.nl/wp/?p=1 )我真的很喜歡我的斷言代碼陷阱導致問題,所以這個解決方案是對我來說不太適合:更難調試。
  • 第二,失去的時間:
    • 在調查系統時,我發現無論幀速率如何(奇怪的是,但我認為統計上它仍然有意義w / vsync)我在vsync上等待大約22%的時間。 我已經通過移動glFlush / glFinish並通過玩我多久經常進行presentRenderBuffer調用來證實這一點。 這是我喜歡處理AI等關鍵時刻,而不是簡單地停止阻塞gl調用。 我能想到的唯一方法就是將渲染轉移到它自己的線程中,但我不確定是否有理由開始在單處理器設備上重新構建多線程。

那麼有沒有人圍繞這些問題找到靈感? 有沒有人在這個平台上有一個殺手運行循環架構? 目前看起來我必須選擇較少的邪惡。




Related