Pergunta

Eu estou tentando criar um loop passo fixo no meu programa, mas por algum motivo eu simplesmente não consigo fazê-lo funcionar corretamente. Basicamente o que eu preciso é um loop que faz:

while(!over) {
    Update(elapsedtime);
    Draw(elapsedtime);
}

ou algo semelhante, com um. Eu tentei usar Thread.Sleep mas eu não estou tão certo de que me deu uma verdadeira fixo circuito passo, e quando tentei implementar a solução em este site I teve problemas devido ao fato de que eu não podia ver uma maneira de salvar o estado dos objetos afetados pelo loop. Isso me forçou a excluir essa parte, o que levou a desaceleração quando havia muitos objetos no loop.

Como posso obter um loop passo fixo sem constantemente ter que salvar o estado de cada objeto no loop?

Foi útil?

Solução

Se você estiver trabalhando em um motor de jogo, um temporizador irá provavelmente não funcionar bem. Temporizadores não têm precisão suficiente para lidar com um loop passo fixo e mantê-lo regular.

Você precisará implementar isso usando uma alta temporizador precisão. Neste caso, você vai querer usar a classe Cronômetro. Isto irá permitir que você tenha precisão suficiente para acompanhar o seu elapsedTime com precisão.

Você só precisa manter o controle de freqüência com que você deseja atualizar (em carrapatos), em seguida, usar um cronômetro para medir o tempo que leva para cada uma de suas atualizações. Depois disso, você pode potencialmente usar uma chamada Sleep () para o bloco, mas perceber que o sono só terá uma precisão de 14-15 ms na maioria dos sistemas, mesmo se você só dormir por 0 ou 1 ms. Isso pode abrandar o seu ciclo muito, então você pode precisar implementar um bloqueio de rotação ou similar (ao mesmo tempo (em espera) {fazer algo}). Sleep () é bom porque ele economiza CPU, se puder, o bloqueio de rotação vai comer ciclos de CPU enquanto você está esperando, mas dá-lhe mais precisão.

Outras dicas

Você está perguntando para um loop que irá executar basicamente a cada n carrapatos? Isso soa como um Temporizador . Há um par de temporizador de na BCL. A temporizador para servidores ou um para formulários de janela

.

Você pode usá-los ao longo destas linhas. O seguinte é o código pseudo e destina-se a mostrar geralmente como isso é feito. Em outras palavras, ele provavelmente não irá compilar se você acabou de copiar e colar.

public class RepeatingTask
{
    public MyObjectState _objectState;

    public RepeatingTask(Timespan interval)
    {
       Timer timer=new Timer(Timer_Tick); //This assumes we pass a delegate. Each timer is different. Refer to MSDN for proper usage
       timer.Interval=interval;
       timer.Start();

    }
    private DateTime _lastFire;
    private void Timer_Tick()
    {
       DateTime curTime=DateTime.Now();
       DateTime timeSinceLastFire = curTime-lastFireTime;
       _lastFire=DateTime.Now(); //Store when we last fired...

       accumulatedtime+=timeSinceLastFire
       while(accumulatedtime>=physicsInterval)
       {
          Update(physicsInterval);
          accumulated-=physicInterval;
       }

               }

}

Você também pode usar um fecho para embrulhar o seu estado do método que o temporizador está definido na.

Editar

Eu li o artigo e eu entendo a questão; no entanto, você ainda pode usar um timer, mas você precisa que ele indica definir a sua função até chamar os motores para cada intervalo definido o seu motor de física para.

Você está usando WPF eles têm alguns eventos que eu acredito que se disparados contra as taxas estáveis ??para animações doign.

Editar

Eu atualizei meu código de exemplo para mostrar-lhe a minha interpretação, mas basicamente o que você faz é definir um intervalo para o seu motor de física, e então o que você precisa fazer em cada passagem no "Loop / temporizador que quer que" é determinar o quanto de verdade tempo decorrido desde a última iteração. Você, então, armazenar esse delta em uma Accumalator, o que você vai usar a contagem decrescente até que você tenha chamado o seu motor de física para todos os intervalos que você perdeu desde a última chamada.

O que luta com é se usando um timer aqui é melhor, em seguida, ter um sono fio dedidicated, ou alguma outra aplicação.

Thread.Sleep não vai dar-lhe um loop passo fixo, ele vai simplesmente esperar a quantidade dada de tempo antes que ele permite que o programa continue. A frequência real vai depender de quão preciso o sono é e como consistente o seu programa está em execução a mesma quantidade de tempo relógio de parede em cada etapa. Se você pode acomodar algumas deriva, no entanto, isso pode ser adequada e é certamente o mais fácil.

Para obter um verdadeiro fixo circuito etapa, o que você precisa é de uma intervalo do temporizador que executa seu código através de uma chamada de retorno quando o temporizador expira. Note que não é realmente um laço mais, mas você código é executado periodicamente, o que é, penso eu, o que você quer. Mais uma vez, pode haver algum desvio e assim você pode precisar de ajustar o intervalo em cada passo para que o próximo evento é acionado no momento certo, se você precisar de mais precisão. Não é realmente possível para torná-lo perfeitamente precisos - mesmo temporizadores de intervalo baseadas em hardware ter uma precisão, depois de tudo -. Mas espero que você pode torná-lo o suficiente precisas para seus propósitos

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top