2009-08-29 6 views
5

私のゲームをiPhoneにきれいに移植するために、NSTimerを使用しないゲームループを作ろうとしています。NSTimerを使わずにiPhoneでゲームループを作る方法

私はNSTimerを使用している場合、あなたは

drawViewのようなものになります
self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; 

ようなもので最初にそれを設定したい、いくつかのサンプルコードに気づい:


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

このテクニックを使用してmFooModelはうまく描画されますが、NSTimerがdrawViewを1秒間に60回呼び出すのではなく、drawViewを呼び出す独自のゲームループを作りたいと思っています。


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

残念なことに私がこれを行うと、黒い画面が表示されます。なぜこれが起こるのですか?とにかく私がここで説明していることを実装することができますか?

私がNSTimerを避けたい理由は、ゲームループでフィジックスとAIアップデートを行いたいからです。私はこれを正確に行うために、自分の時計/タイマーを使って経過時間を記録しています。レンダリングはできるだけ速く行われます。 this article

これは多少の疑問です(一日中コーディングした後で、つまって、答えが朝までにあることを願っています)

乾杯。

答えて

2

あなたがNSTimerを使用したくない場合は、NSRunLoop手動で実行してみることができます。iPhoneOS 3.1と

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

+0

私は1/45thよりも多くの仕事があると警告していませんでした(またはそれ以上のラン・ループ・ストール)、あなたは吃音、遅れたタッチイベント、および他の奇妙な問題を抱えます。徹底的にテストしてください。それを考慮に入れるコードを更新することは可能ですが、アプリケーション固有です – rpetrich

+0

実行ループ内のすべてのalloc/deallocがパフォーマンスに影響しませんか?それをループ外に移動する方法はありますか? – Andrew

21

別のオプションは、新しいCADisplayLink APIを使用することです。これにより、画面の内容を更新する必要があるときに指定したセレクタが呼び出されます。

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

Xcodeの新しいOpenGLプロジェクトテンプレートでは、さらにコード例が必要な場合にCADisplayLinkも使用されます。

+0

displaylinkにNSAutoreleasePoolを追加する必要があります –

+0

NSAutoreleasePoolは必要ありません。 XCodeで新しいOpenGLベースのプロジェクトを作成すると、その使用方法がわかります。 –

2

CADisplayLinkを使用するのは、3.1ベースのゲームの本当に良い選択肢ですが、
「Timer」を使用するものは本当に悪い考えです。

GPUの作業を切り離すには、最良の方法は古い「トリプルバッファリング」です。

ファビアンが彼の運命のiPhoneのレビューでは非常に良い説明があります。
http://fabiensanglard.net/doomIphone/

0

についてCADisplayLinkとファビアンによってドゥームiPhoneのための記事を、私はファビアンを電子メールで送信し、私は最良の選択肢は主観的だと思います。パフォーマンス上のDisplayLinkとトリプルバッファリングは同じにする必要がありますが、DisplayLinkはOS> 3.1でのみ使用できます。それはあなたの決定要因になるはずです。

2

selfをターゲットとして注意してください。マニュアルには「新しく作成された表示リンクがターゲットを保持しています」と記載されています。 Martin

関連する問題