Resolvi começar essa série porque tem certas informações que eu realmente gostaria de ter recebido quando estava aprendendo a programar games. Digo isso pois a maioria dos tutoriais te ensinam a fazer um jogo de pong, fazer um boneco se mexer, desenhar coisas na tela, mas quando chega na parte boa, que é estruturar algo levemente mais complexo, todos eles acabam.
Parte I
A primeira coisa que me intrigava era como fazer as coisas acontecerem na tela, simultaneamente (e.g. como dar uma tacada em um jogo de sinuca e fazer todas as bolas se mexerem, colidirem e possivelmente serem mortas). Bom, a grande verdade é que as coisas não acontecem ao mesmo tempo.
O que acontece geralmente é que existe uma classe chamada Engine que reune todas as entidades do jogo e tem um método Run() que faz a mágica em questão. No exemplo do jogo de sinuca, as classes dentro da engine seriam: jogador, bolas, mesa, física, interface. Na tal função “faz tudo”, cada classe teria a oportunidade de executar seus métodos pertinentes.
Como exemplo dessa interação de classes, uma função que executa uma tacada:
// Executa uma tacada
Engine::ExecuteShot ()
// Seta a velocidada da bola branca
cueBall.SetSpeed(Player.Shot())
// Enquanto as bolas tiverem velocidade
while (!Physics.Done(BallArray))
// Para cada bola do jogo
foreach (ball in BallArray)
// Move a bola
ball.Move()
// Considera o atrito
Physics.Attrict(ball)
// Trata colisao com o buraco
Physics.HoleCollision(Table, ball)
// Toca o som da colisao
Interface.PlayHoleSound(Physics.LastCollision())
// Atualiza a pontuacao
Player.RefreshScore(Physics.LastCollision())
// Trata colisao com outras bolas
Physics.BallCollision(BallArray, ball)
// Toca o som da colisao
Interface.PlayBallSound(Physics.CollisionArray())
// Trata colisao com a mesa
Physics.TableCollision(Table, ball)
// Toca o som da colisao
Interface.PlayTableSound(Physics.LastCollision())
// Desenha mesa, bolas, pontuacao, etc
Interface.Draw(BallArray, Player)
return
Na prática, isso desloca as bolas em pequenas distâncias, verificando colisões com outras bolas, cantos da mesa e buracos. Em cada verificação, as velocidades das bolas são tratadas pelo módulo da física. Além disso, a classe interface é responsavél por tocar os sons e desenhar coisas na tela. Portanto, apesar do resultado final ser algo aparentemente simultâneo, a engine do jogo executa pequenos passos.
Vale lembrar que cada ciclo da engine, como o while do exemplo acima, é executado várias vezes por segundo. Pense, no caso da sinuca, que seriam feitos cerca de 40 frames por segundo (daí o motivo de se mover em curtas distâncias).
O objetivo dessa primeira parte é apenas mostrar como interagir as classes em alto nível. A maneira como cada uma das classes é composta e implementa os métodos não entra nessa discussão inicial.
Até a próxima…