2009-08-29 57 views
5

爲了將遊戲清晰地移植到iPhone上,我試圖製作一個不使用NSTimer的遊戲循環。如何在不使用NSTimer的情況下在iPhone上製作遊戲循環

我認爲,如果使用的NSTimer,你會用什麼設置它在一開始像一些示例代碼注意到

self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; 

其中drawView函數看起來是這樣的:


- (void)drawView 
{ 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); 
    mFooModel->render(); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
} 

當使用這種技術mFooModel呈現很好,但我反而想讓自己的遊戲循環調用drawView,而不是讓NSTimer每秒調用drawView 60次。我想這樣的事:


while(gGameState != kShutDown) 
{ 
    [self drawView] 
} 

不幸的是,當我這樣做,我得到的只是一個黑屏。爲什麼會發生?無論如何,我可以實現我在這裏描述的內容嗎?

我想避免NSTimer的原因是因爲我想在遊戲循環中做物理和AI更新。我使用自己的時鐘/定時器來跟蹤已經過去的時間量,以便我可以準確地做到這一點。渲染髮生儘可能快。我嘗試使用一些技巧,如this article

這是有些衝動的問題的描述(你做你一直在編碼一整天后,被卡住,並希望回答的人在那裏,到了早晨)

乾杯的傢伙。

回答

2

如果你不希望使用NSTimer你可以嘗試NSRunLoop手動運行:

static BOOL shouldContinueGameLoop; 
static void RunGameLoop() { 
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; 
    NSDate *destDate = [[NSDate alloc] init]; 
    do { 
     // Create an autorelease pool 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     // Run the runloop to process OS events 
     [currentRunLoop runUntilDate:destDate]; 
     // Your logic/draw code goes here 
     // Drain the pool 
     [pool drain]; 
     // Calculate the new date 
     NSDate *newDate = [[NSDate alloc] initWithTimeInterval:1.0f/45 sinceDate:destDate]; 
     [destDate release]; 
     destDate = newDate; 
    } while(shouldContinueGameLoop); 
    [destDate release]; 
} 
+0

謝謝。這是非常有用的代碼。 – user156848 2009-08-30 04:34:19

+0

我忘了提醒你,如果你有更多的工作比1/45秒(或runloop停滯不止),你會有口吃,延遲觸摸事件和其他奇怪的問題。一定要徹底測試。更新代碼來解決這個問題是可能的,但是特定於應用程序 – rpetrich 2009-08-30 08:07:16

+0

運行循環中的所有alloc/dealloc都不會影響性能嗎?有沒有辦法在循環之外移動? – Andrew 2010-08-12 21:38:50

21

另一種選擇用的iPhoneOS 3.1是使用新的API CADisplayLink。這將調用您在屏幕內容需要更新時指定的選擇器。

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(renderAndUpdate)]; 
[displayLink setFrameInterval:2]; 
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

如果您需要更多示例代碼,XCode中新的OpenGL項目模板也使用CADisplayLink。

+0

是否需要爲displaylink添加NSAutoreleasePool – 2011-02-14 14:07:01

+0

NSAutoreleasePool不是必需的。在XCode中創建一個新的基於OpenGL的項目,您將會學習如何使用它。 – 2011-02-18 14:22:55

2

雖然使用CADisplayLink對於基於3.1的遊戲來說是一個非常好的選擇,但是使用「Timer」的任何東西都是一個非常糟糕的主意。

最好的方法是將舊的「tripple buffering」去耦合GPU工作。

法比安斯基在他的末日iPhone回顧了很好的解釋:末日的iPhone文章法比安斯基
http://fabiensanglard.net/doomIphone/

0

關於CADisplayLink和,我通過電子郵件法比安斯基,我認爲最好的辦法是主觀的。性能方面的DisplayLink和三重緩衝應該是相同的,但DisplayLink僅適用於> OS 3.1。所以這應該是你的決定性因素。

2

請注意使用self作爲displayLinkWithTarget的目標,手冊中提到「新構建的顯示鏈接保留了目標」。 Martin

相關問題