Qual é a melhor maneira de criar um loop de jogo no iPhone além de usar o NSTimer?

Estou programando um jogo no iPhone. Atualmente, estou usando o NSTimer para acionar minha atualização/renderização de jogos. O problema com isso é que (após a criação de perfil) pareço perder muito tempo entre atualizações/renderizações e isso parece estar relacionado principalmente ao intervalo de tempo que eu conecto ao NSTimer.

Então, minha pergunta é qual é a melhor alternativa para usar o NSTimer?

Uma alternativa por resposta, por favor.

0
adicionado editado
Visualizações: 2
Eu olhei muitos exemplos e pesquisei alternativas na internet. Então eu já conheço algumas alternativas. O que eu realmente quero é o que as outras pessoas acham que é a melhor alternativa? Eu estou trabalhando em um projeto extremamente curto para que qualquer tempo economizado em investigação seja uma grande ajuda.
adicionado o autor Ashley Davis, fonte
Você já olhou para os exemplos do desenvolvedor do iPhone? Eu acho que existem alguns exemplos (Touch Fighter ou CrashLanding, por exemplo) que podem ser esclarecedores.
adicionado o autor Mark Bessey, fonte

3 Respostas

Você pode obter um melhor desempenho com threads, tente algo como isto:

- (void) gameLoop
{
    while (running)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [self renderFrame];
        [pool release];
    }
}

- (void) startLoop
{
    running = YES;
#ifdef THREADED_ANIMATION
    [NSThread detachNewThreadSelector:@selector(gameLoop)
    toTarget:self withObject:nil];
#else
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60
    target:self selector:@selector(renderFrame) userInfo:nil repeats:YES];
#endif
}

- (void) stopLoop
{
    [timer invalidate];
    running = NO;
}

No método renderFrame você prepara o framebuffer, desenha o frame e apresenta o framebuffer na tela. (P.S. Existe um ótimo artigo sobre vários tipos de loops de jogos e seus prós e contras.)

0
adicionado
@zoul: a alternativa THREADED_ANIMATION também funciona para versões anteriores? Eu pensei que eu li que não em algum lugar.
adicionado o autor Jonas Byström, fonte
@tc: Você está certo, mas o pôster não diz nada sobre a camada gráfica que ele usa. Já que estamos falando de jogos, eu assumi o OpenGL, onde esse loop funciona sem problemas.
adicionado o autor zoul, fonte
Você quer dizer versões anteriores do iOS? Sim, eu usei código semelhante em jogos em torno de 2.x ou 3.x.
adicionado o autor zoul, fonte
-1. O UIView não é thread-safe, então você precisa fazer um monte de outras coisas para fazê-lo funcionar. UIGraphics é apenas thread-safe desde 4.0.
adicionado o autor tc., fonte

Eu não sei sobre o iPhone em particular, mas ainda posso ajudar: Em vez de simplesmente conectar um atraso fixo no final do loop, use o seguinte:

  • Determine um intervalo de atualização com o qual você ficaria feliz e que seja maior do que uma única passagem no loop principal.
  • No início do loop, pegue um timestamp atual de qualquer resolução disponível e armazene-o.
  • No final do loop, pegue outro timestamp e determine o tempo decorrido desde o último registro de data e hora (inicialize isso antes do loop).
  • sleep/delay para a diferença entre o tempo de quadro ideal e o tempo já decorrido para o quadro.
  • No quadro seguinte, você pode até tentar compensar imprecisões no intervalo de suspensão, comparando com o registro de data e hora no início do ciclo anterior. Armazene a diferença e adicione/subtraia a diferença do intervalo de suspensão no final desse loop (sleep/delay pode ser muito longo OU muito curto).

Você pode querer ter um mecanismo de alerta que lhe permita saber se o tempo está muito apertado (ou seja, se o seu tempo de sono depois de toda a compensação ser menor que 0, o que significaria que você está demorando mais para processar do que sua taxa de quadros permite). O efeito será que o seu jogo fica mais lento. Para pontos extras, você pode querer simplificar a renderização por um tempo, se você detectar isso acontecendo, até que você tenha capacidade de reserva suficiente novamente.

0
adicionado

Use o CADisplayLink, você pode encontrar como no projeto de modelo OpenGL ES fornecido em XCODE (criar um projeto a partir deste modelo e dar uma olhada na classe EAGLView, este exemplo é baseado em aberto GL, mas você pode usar CADisplayLink apenas para outros tipo de jogos

0
adicionado