while ( true )
{
Atualizar();
if ( usuario.mandou.sair )
break;
Desenhar();
}
pronto, isso pode dar conta em um jogo muito simples, onde o usuário já entra no jogo, talvez passando por uma tela qe aceita qualquer entrada para ir para o jogo em si, mas quando a coisa começa a crescer, ou seja, você quer adicionar uma tela de opções, salvar e carregar jogos, pontuação persistente, telas de game over e game win e por ai vai, seu loop vai pareçer com isso:
while ( true )
{
if ( telaDeOpcoes )
{
AtualizarOpcoes();
DesenharOpcoes();
}
else if ( SalvarJogo )
{
SalvaJogoAtual();
}
else if ( GameOver )
{
MostraTelaGameOver();
}
else
{
Atualizar();
if ( usuario.mandou.sair )
break;
Desenhar();
}
}
Nossa, eu nem compliquei muito e já ficou complicado de manter esse código. Poderiamos usar inteiros, booleanos, enumerações e até classes mais simples parar representar os estados que ainda assim, seria complicado manter o código.
É ai que entra a Finite State Machine, ou Máquina de Estados Finitos. O que é isso?
É uma máquina com uma quantidade finita de estados! =D
Falando sério agora, vamos começar pela definição de estado. Imagine você, de mal humor e seu professor lhe apresenta uma prova surpresa cujo assunto você não sabe, sua reação: "QUE DROGA!". Agora se você estivesse de bom humor e soubesse do assunto: "Ainda bem que sei esse assunto...". Mal ou bom humor, raiva, tristeza, felicidade, etc são estados, são eles que vão determinar como agir em cada situação.
Voltando para os jogos, se o jogador, no meio da jogatina, clica na opção "Salvar Jogo", seu jogo deve mudar o estado atual de "jogando" para "salvar" e talvez apresentar um menu onde o usuário pode escolher em qual slot quer que seja salvo seu progresso. Uma Finite State Machine, ou FSM como será mencionada a partir de agora, gerencia essas mudanças de estado que seu jogo sofre, então o seu loop principal ficaria mais ou menos assim:
while ( true )
{
FiniteStateMachinhe.Atualizar();
Desenhar();
}
Muito mais simples, não é? Mas para onde foram todas aquelas linhas de código de antes? Elas foram para dentro dos seus respectivos estados. A FSM determina qual estado o jogo esta atualmente, chamando os métodos "atualizar" e "desenhar" do estado (ou de mais de um, dependedo da sua implemantação) e fazendo mudanças caso lhe seja solicitado! Isso que dizer que cada estado é independente do outro e pode pedir para ser retirado, colocar outro por cima dele ou mudar completamente de estado.
O jeito mais simples de fazer isso foi utilizando um stack, ou pilha, e nada melhor que um exemplo:
Eu começei a jogar XYT e apareçeu a introdução. Rapidamente eu aperto uma tecla para ir ao menu principal (mudança de estado). Noto que o som está muito alto e resolvo abaixar, clico em opções (colocação de estado), abaixo o volume e volto ao menu principal (retirada de estado) e só então entro no jogo (colocação de estado), mas depois de um tempo, perco completamente... Game over (mudança de estado) e logo após, retorno ao menu (mudança de estado).
Todas essas mudanças, colocações e retiradas são o motivo de usar uma stack, onde os pushes e pops fazem exatamente esse trabalho. Quando quero mudar, removo todos os estado e empurro o que eu quero mudar, como no caso da introdução para o menu, o usuário não vai voltar para a intordução. Empurro um estado quando eu sei que o usuário vai sair dele e voltar para o anterior, como no caso do menu de opções e finalmente retiro um estado quando ele não faz mais sentido, como quando o usuário perde (jogar sem vidas não faz sentido).
Cada estado terá seu próprio método Atualizar() assim como Desenhar(), se for o caso, e poderá solicitar ao FSM qualquer mudança que julgar necessária. Isso simplifica tremendamente o trabalho do programador, pois ele pode criar, remover ou modificar completamente estados sem muitas mudanças no código base.
Novamente não apresentarei código fonte ou tutoriais, mas se a demanda for suficiente (comentem!) então eu posso fazer!
Até a próxima, falarei dos Managers!
Abraços!
Nenhum comentário:
Postar um comentário