2009-08-29 23 views
5

'u kullanmadan iPhone'da bir oyun döngüsünü nasıl yaparım Oyunumu iPhone'a temiz bir şekilde bağlamak için, NSTimer kullanmayan bir oyun döngüsü oluşturmaya çalışıyorum. NSTimer

Ben NSTimer kullanarak, sen gibi bir şeyle başında kurmak istiyorum bazı örnek kodda fark

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

drawView benzer görünümde olacaktır burada:


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

zaman Bu tekniği kullanarak mFooModel iyi, ama ben NSTimer çağrı drawView yerine 60 kez bir kez drawView çağırır kendi oyun döngü yapmak istiyorum. Şunlar gibi bir şey istiyorum:


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

Ne yazık ki bunu yaptığımda, tek istediğim siyah bir ekran. Bu neden oluyor? Zaten burada tarif ettiğim şeyi uygulayabilir miyim?

NSTimer'den kaçınmak istemem nedeniyle oyun döngüsünde fizik ve AI güncellemeleri yapmak istiyorum. Bunu doğru bir şekilde yapabilmem için geçen süreyi takip etmek için kendi saatimi/zamanlayıcıyı kullanıyorum. Render mümkün olduğunca hızlı gerçekleşir. this article

Bu biraz tepkisel soru olduğu açıklandığı gibi ben

(eğer bütün gün kodlama oldum sonra, sıkışabilir ve cevap umuyoruz biri sabaha yoktur) bazı teknikleri kullanmayı deneyin

Şerefe çocuklar.

cevap

2

Eğer NSTimer kullanmak istemiyorsanız size NSRunLoop elle çalıştırmayı deneyebilirsiniz: iPhoneOS 3.1 ile

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

Teşekkürler. Bu çok kullanışlı bir kod. – user156848

+0

Bir saniyenin 1/45'inden daha fazla çalışmanız varsa (ya da daha fazla koşmak için runloop tezgahları), kekemelik, gecikmeli dokunma olayları ve diğer garip sorunlar yaşayacağınız konusunda uyardım. İyice test ettiğinizden emin olun. Bunun hesaba katılması için kod güncellenmesi mümkündür, ancak uygulamaya özel – rpetrich

+0

Çalışma döngüsündeki tüm tahsis/dealloc performansı etkilemiyor mu? Döngünün dışına taşınmanın bir yolu var mı? – Andrew

21

Diğer bir seçenek yeni CADisplayLink api kullanmaktır. Bu, ekran içeriğinin güncellenmesi gerektiğinde belirttiğiniz seçiciyi çağırır.

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

Daha fazla örnek kod gerekirse, XCode'daki yeni OpenGL proje şablonu da CADisplayLink kullanır.

+0

Displaylink için NSAutoreleasePool eklemem gerekir –

+0

NSAutoreleasePool gerekli değildir. XCode'da yeni bir OpenGL tabanlı proje oluşturun ve bunu nasıl kullanacağınızı göreceksiniz. –

2

CAD tabanlı olarak kullanıldığında, 3.1 tabanlı oyunlar için gerçekten iyi bir alternatif,
"Timer" kullanarak bir şey gerçekten kötü bir fikirdir.

En iyi yaklaşım, GPU çalışmasının ayrıştırılması için iyi eski "üçlü tamponlama" dır.

Fabien bir onun Doom Iphone incelemede çok iyi bir açıklama vardır:
http://fabiensanglard.net/doomIphone/

0

İlişkin CADisplayLink ve Fabien'in tarafından Doom iPhone makaleye, ben Fabien gönderilecektir ve en iyi seçenek sübjektif olduğunu düşünüyorum. Performansa dayalı DisplayLink ve üçlü tamponlama aynı olmalıdır, ancak DisplayLink yalnızca> OS 3.1'de kullanılabilir. Yani bu sizin belirleyici faktörünüz olmalı.

2

displayLinkWithTarget için hedef olarak self'u kullanırken dikkatli olun, elkitabında "Yeni oluşturulan görüntü bağlantısı hedefi korur". Martin

İlgili konular