Como vocês estão?
Esta aqui é a continuação da Parte 2, então se ainda não a leu, vai lá que eu espero!
Pra começar gostaria de esclarecer uns termos que acabei fazendo confusão no ultimo post.
GameSpeed:
Não falei sobre ele no ultimo post. Ele é o que define a velocidade de processamento da física e das interações no jogo. De modo geral, GameSpeed é a quantidade de vezes que o
update()
do jogo é chamado. No caso do TimeStep Fixo, o GameSpeed é designado pelo programador, o que eu chamei anteriormente de FPS fixo é na verdade GameSpeed fixo.
O termo é confuso por que nos jogos ele fica transparente para o jogador, sendo que, para os jogos que usam TimeStep Variável e a implementação intuitiva, o GameSpeed e o FramesPerSecond são a mesma coisa.
FramesPerSecond (FPS):
O amplamente conhecido FPS é basicamente a quantidade de chamadas ao
render()
do jogo.Este conceito é mais ouvido porque é muitas vezes usado como parâmetros para medir o desempenho de um jogo.
Exceto na implementação intuitiva, maior FPS significa maior desempenho.
Então, na ultima visita eu prometi uma conclusão sobre o assunto do TimeStep e os comentários sobre a utilização no WL.
O controle do TimeStep é o que faz o jogo rodar numa mesma velocidade em máquinas diferentes.
Nas primeiras versões do War Legacy, nas quais o laço principal do jogo era basicamente o mostrado aqui, o update e o render não tinham nenhuma diferenciação, tudo fazia parte do mesmo laço. E a forma de controlar a velocidade do jogo (ou o FPS) era através de um calculo do FPS atual e um ajuste no parâmetro da função
rest()
. A função rest(t)
pausa o processamento por t milissegundos, um ajuste no valor de t fazia o jogo parar por mais tempo quando a velocidade precisasse diminuir ou por menos tempo quando a velocidade precisasse aumentar.
Um trecho do código que não foi citado quando mostrei aqui o pseudocódigo das primeiras versões do WL era mais ou menos assim:
|
rest(t)
faz o processo "descansar" por aproximadamente t milissegundos. Digo aproximadamente porque há pouca garantia de que será exatamente t milissegundos, e a principal razão disso é a forma que o Sistema Operacional faz o escalonamento dos processos em andamento.Abstraindo essa parte, apenas ter em mente que
rest(t)
não garante uma pausa no processo numa quantidade de tempo exata à que queremos já dá pra perceber que esta não é uma boa prática de TimeStep.Devo adicionar que: usar funções como rest, sleep e afins não é uma prática abominável. Elas têm seu próprio benefício, que é poupar o uso continuo do CPU para economizar bateria em plataformas mobile. Porém, por causa da sua característica de possível não-determinabilidade, as mesmas devem ser usadas de forma responsável e consciente.
Outro detalhe sobre o desempenho dessa minha implementação é que o código de controle do jogo, vulgo update()
, estava tão bagunçado e ineficiente que o fps ficava 90% do tempo abaixo do desejado, fazendo o valor de t diminuir abaixo de zero e, consequentemente, fazendo a função rest(t)
quase nunca ser chamada.
Então a lição que fica é a seguinte: Controle do TimeStep do jogo é importantissimo para manter a consistência e fluidez do gameplay, mas a organização e planejamento do código do jogo é essencial para que esse controle faça alguma diferença.
Por causa disso, no(s) próximo(s) post(s) vou dar algumas dicas de como programar pensando nesse aspecto, e para começar vou falar da Memória Cache e como programadores de jogos podem usá-la a seu favor, então até lá!
Então é isso, espera que tenham gostado e aprendido alguma coisa, deixa um comentário aí. E como sempre vocês podem me encontrar no tuiter @LinceAssassino ou no email emailDoLince(arroba)gmail(ponto)com para qualquer dúvida, sugestão, crítica ou simplesmente se quiser trocar uma ideia.
Abraços do Lince.
Tweetar
Nenhum comentário:
Postar um comentário