Fiquei me perguntando se existe algum dano possível quando o loop do jogo é executado o mais rápido que o sistema permite?
Atualmente, tenho um loop que, medindo o tempo passado em nanossegundos, executa a lógica do jogo e processa a lógica em velocidades predefinidas sem problemas. De fato, qualquer lógica que eu faça no loop é cronometrada para uma certa quantidade de chamadas a cada segundo.
O loop em si, no entanto, roda tão rápido quanto ele gosta, chegando a cerca de 11,7 milhões de loops por segundo na minha máquina.
Loop (pseudocódigo simples):
while(!isGameOver){
if(canPollInputs){
pollInputs()
}
while(canStepLogic){
stepLogic()
}
if(canRender){
render()
}
}
Minha pergunta é basicamente se esse loop simples, se não estiver funcionando a uma velocidade controlada, pode causar algum dano a um sistema?
Edit: Isso significa que minha lógica está rodando 30 vezes por segundo (30 tps), meu renderizador está rodando a 60 fps, estou pesquisando entradas 100 vezes por segundo e também há alguma lógica para lidar com a lógica ou renderização levando mais tempo do que o esperado . Mas o loop em si não é regulado.
Editar: Usar Thread.sleep()
para, por exemplo, acelerar o loop principal até 250 loops por segundo leva a uma redução, mas os loops são executados em torno de 570 loops por segundo em vez dos 250 desejados (adicionará código quando estou na minha máquina de trabalho ..)
Edit: Aqui vamos nós, um gameloop java de trabalho, a fim de esclarecer as coisas. Também fique à vontade para usá-lo, mas não o reivindique;)
private void gameLoop() {
// Time that must elapse before a new run
double timePerPoll = 1000000000l / targetPPS;
double timePerTick = 1000000000l / targetTPS;
double timePerFrame = 1000000000l / targetFPS;
int maxFrameSkip = (int) ( (1000000000l / MINIMUM_FPS) / timePerTick);
int achievedPPS = 0;
int achievedFPS = 0;
int achievedTPS = 0;
long timer = TimeUtils.getMillis();
int loops = 0;
int achievedLoops = 0;
long currTime = 0l;
long loopTime = 0l;
long accumulatorPPS = 0l;
long accumulatorTPS = 0l;
long accumulatorFPS = 0l;
long lastTime = TimeUtils.getNano();
while(!isRequestedToStop) {
currTime = TimeUtils.getNano();
loopTime = currTime - lastTime;
lastTime = currTime;
loops = 0;
accumulatorPPS += loopTime;
accumulatorTPS += loopTime;
accumulatorFPS += loopTime;
if(accumulatorPPS >= timePerPoll) {
pollInputs();
playerLogic();
achievedPPS++;
accumulatorPPS -= timePerPoll;
}
while(accumulatorTPS >= timePerTick && loops < maxFrameSkip) {
tick();
achievedTPS++;
accumulatorTPS -= timePerTick;
loops++;
}
// Max 1 render per loop so player movement stays fluent
if(accumulatorFPS >= timePerFrame) {
render();
achievedFPS++;
accumulatorFPS -= timePerFrame;
}
if(TimeUtils.getDeltaMillis(timer) > 1000) {
timer += 1000;
logger.debug(achievedTPS + " TPS, " + achievedFPS + " FPS, "
+ achievedPPS + " Polls, " + achievedLoops + " Loops");
achievedTPS = 0;
achievedFPS = 0;
achievedLoops = 0;
}
achievedLoops++;
}
}
Como você pode ver, quase não há código executado em cada loop, mas sempre uma certa seleção com base em quanto tempo real se passou. A questão está se referindo a esse 'loop de trabalho' e como ele influencia o sistema.
fonte
Respostas:
Isso fará com que um núcleo da CPU seja sempre executado em 100%. Isso geralmente não causa nenhum dano ao sistema. As CPUs são projetadas para funcionar 100% por horas. Porém, em um dispositivo móvel, ela descarrega a bateria rapidamente e aquece o dispositivo, o que provavelmente custará cerca de uma estrela nas classificações da sua loja. Em um computador desktop, isso é menos problemático, mas consome mais eletricidade dos usuários, faz com que o ventilador da CPU gire mais rápido, o que pode causar algum ruído e desperdiçar ciclos de CPU que, de outra forma, poderiam ser usados por outros processos. Embora esses defeitos não sejam críticos, eles ainda têm um estilo ruim; portanto, evite-os quando possível.
Você não disse nada sobre como o loop da lógica do jogo funciona internamente, mas quando você usa a abordagem de tempo delta (cada cálculo que você faz leva um tempo desde a última chamada em consideração), está lidando com delta muito pequeno. valores de tempo. Isso significa que você pode ter problemas com imprecisão de ponto flutuante, o que pode causar todo tipo de comportamento estranho. Além disso, a resolução do timer do sistema geralmente é limitada; portanto, quando seu loop lógico é muito rápido, é possível obter um valor delta-t de zero, o que pode causar uma divisão por zero, resultando em uma falha.
Para atenuar esse problema, você deve limitar sua taxa de quadros (gráfico e lógica) ao máximo do que o olho humano pode perceber. Quanto é contestado e depende do tipo de animação e do tipo de exibição que é mostrado, mas as estimativas variam de 40 FPS a 120 FPS. Isso significa que você precisa definir um tempo mínimo de execução de cada loop entre 20ms e 8ms. Se uma iteração do loop terminar mais rapidamente, deixe o segmento da CPU
sleep
pelo período de tempo restante.fonte
Você está desperdiçando ciclos da CPU. Isso significa menor tempo de bateria em notebooks, tablets e telefones, contas de eletricidade mais altas, mais calor gerado pela máquina, ventiladores mais barulhentos. Além disso, você pode estar comendo ciclos de outros processos importantes do sistema (por exemplo, o servidor de janelas pode ficar irregular), o que pode afetar a jogabilidade. Alguns agendadores de sistema nos sistemas de multitarefa preventiva de hoje também penalizam aplicativos que usam muitos ciclos; portanto, você pode ser rápido primeiro e depois repentinamente ver uma sacudidela estranha quando você é estrangulado pelo sistema.
Muitos jogadores hardcore também constroem PCs personalizados a partir do zero, que estão no limite das especificações de seus fãs; nesse caso, um dia quente e o calor que seu jogo gera podem fazer com que as seguranças sejam acionadas na máquina (na melhor das hipóteses) ou até mesmo superaquecer as peças e morrer (na pior das hipóteses). Portanto, se esse for o seu público-alvo, convém garantir que você esteja sempre deixando um pouco de espaço "no topo".
Finalmente, há problemas de jogabilidade em que você pode estar aproveitando jogadores com máquinas mais rápidas do que aqueles com máquinas mais lentas. Ter o loop do jogo limitado em uma determinada frequência e usar ciclos adicionais apenas para aspectos não relevantes para o jogo (como renderização de gráficos de alta fidelidade, efeitos de som surround ou qualquer outra coisa) tornarão seu jogo mais justo.
fonte
Você não deve ter movimentos / jogabilidade nervosos
Há duas maneiras de implementar a lógica do jogo - vinculada a tempo real ou vinculada ao número de "turnos" / etapas de processamento. Se alguma coisa no seu jogo estiver se movendo para a esquerda, o movimento será diferente se o seu stepLogic () for chamado 100 em vez de 50 vezes?
Se o seu código tratar o tempo decorrido explicitamente em todos os lugares e fazê-lo corretamente, poderá ser bom; mas se houver algo no seu código que dependa do número de 'etapas', você terá efeitos colaterais indesejados.
Primeiro, a velocidade das coisas que devem estar se movendo constantemente variará de forma imprevisível (dependendo do uso do processador), e isso cria controles muito irritantes - você não pode dar um soco ou um salto preciso se, de repente, o jogo acelerar ou desacelerar. Mesmo para jogos sem 'espasmos', parece irritante e instável se as coisas não estiverem indo bem.
Segundo, você pode ter problemas com as habilidades dos personagens, dependendo da velocidade do computador - um exemplo clássico é o antigo problema do Quake, em que o alcance máximo do salto era involuntariamente dependente do seu fps.
Esses problemas podem aparecer mesmo se você tentar que o código seja independente de fps, o acúmulo de erros de arredondamento geralmente pode causar esses erros.
fonte
O único dano potencial é o seu consumo de energia; portanto, não faça isso em dispositivos móveis. Por outro lado, muitos sistemas embarcados passam a vida inteira em um ciclo esperando que as coisas aconteçam.
Costumava ser perfeitamente normal renderizar os quadros de jogos o mais rápido possível, às vezes sem um temporizador para compensar a jogabilidade pelas diferentes velocidades da CPU. O jogo de corrida da Bullfrog Hi-Octane foi uma vítima particularmente ruim disso, e eu suspeito que é a isso que o cartaz mencionando Civ2 está se referindo.
Aconselho você a pesquisar pelo menos as entradas a cada passo, se estiver em um sistema Windows ou similar, para garantir uma resposta rápida das entradas.
fonte
swap
/present
paraflip
fazer a espera no sinal vsync, para regular o ciclo do jogo.