quarta-feira, 11 de maio de 2011

Mais uma pausa

Pausa para reformulação do projeto.
Mudança das classes, mudanças dos componentes, organização em pastas e até mudança do nome. Na verdade, até mudança de biblioteca para framework (ou engine). Mudança de site também. O código está em http://code.google.com/p/elsagames-framework/ com nome provisório ELSA Framework.

terça-feira, 12 de abril de 2011

Andamento do projeto


Estou postando aqui um exemplo da utilização do projeto.
Ainda está no começo, mas dá para ver algumas funcionalidades já implementadas como movimento e ataque. Tem alguns pequenos bugs mas a maioria é por causa das constantes que estou utilizando para largura do Personagem e tiles colidíveis.
Nenhum dos gráficos usados são realmente meus, só estão sendo utilizados para exemplificar.
Use as setas para mover, X corre e A ataca e "conversa". E ESC sai.
E por favor, ande por cima da grama.

Download



Críticas e sugestões são muito bem vindos.

terça-feira, 22 de março de 2011

Máquina de Estados e AI Básica

Máquina de Estados

No projeto, todo GameObject tem uma máquina de estados baseada nesse artigo aqui: http://www.ai-junkie.com/architecture/state_driven/tut_state1.html

Um objeto como o player ou um monstro tem estados como Walk, Run, Idle, Attack e por aí vai, dependendo das funcionalidades que forem implementadas.

O uso da Máquina de estados facilitou e organizou meu projeto. Uma das coisas que mais me agradou foram os 3 métodos de cada estado:
//this will execute when the state is entered
virtual void Enter(Miner*)=0;

//this is called by the miner’s update function each update-step
virtual void Execute(Miner*)=0;

//this will execute when the state is exited
virtual void Exit(Miner*)=0;

Inicializar variáveis, carregar informações e coisas do tipo vão no Enter.
Um dos problemas que enfrentei no começo do projeto foi a mudança de sprite para cada tipo de ação do Character, principalmente em relação aos sprites de ataque. Então eu uso o Enter para carregar as informações de Área de Dano, Ataque e Colisão do Character para seu estado.

Inteligência Artificial Básica

Para o desenvolvimento da AI eu estou usando o conceito de MVC.
A classe Controller é assim:
class Controller {
public:
Controller() {}
virtual ~Controller() {}
virtual void update(Model *targetModel, GameObject *myObj) = 0;
virtual void init() = 0;
virtual bool getACTION() const =0;
virtual bool getDOWN() const =0;
virtual bool getLEFT() const =0;
virtual bool getRIGHT() const =0;
virtual bool getRUN() const =0;
virtual bool getSPECIAL_ATACK() const =0;
virtual bool getUP() const =0;
virtual void setACTION(bool ACTION) = 0;
virtual void setDOWN(bool DOWN) = 0;
virtual void setLEFT(bool LEFT) = 0;
virtual void setRIGHT(bool RIGHT) = 0;
virtual void setRUN(bool RUN) = 0;
virtual void setSPECIAL_ATACK(bool SPECIAL_ATACK) = 0;
virtual void setUP(bool UP) = 0;
};

Onde os Getters and Setters correspondem ao comandos dados pelo usuário no caso da classe filha ControllerInput. O método update foi colocado no Controller já pensando na AI.
A classe FightAI é filha da Controller e o método update é chamado para setar os atributos da classe:
bool LEFT;
bool RIGHT;
bool UP;
bool DOWN;
bool ACTION;
bool SPECIAL_ATACK;
bool RUN;

Assim, não foi preciso mudar o código do resto do jogo, uma vez que a classe Controller é usada pelo software a partir dos seus getters.

A AI de luta que eu programei é a mais simples possível. Ela apenas move o objeto (setando os direcionais) na direção do Player. Ao chegar na distância que é possível acertar um golpe ele ataca. Uma coisa que devo fazer posteriormente é acrescentar um fator randômico às escolhas da AI, deixando ele mais real e suscetível a erros. Além disso falta fazer o inimigo desviar dos objetos.

Eu não fiz uma máquina de estados própria para a AI, como eu queria fazer no princípio. O que eu faço é usar a máquina de estados, que já existe para todos os objetos, e retirar a informação sobre qual é o estado atual para as decisões da AI.

sábado, 19 de fevereiro de 2011

Andamento da Action RPG Lib

Apesar de demorar postar o andamento da Action RPG Lib o projeto continua andando.
Muitas funcionalidades já foram implementadas.

-> Movimento e colisão
-> Ataque
-> Dialog Box
-> Triggers para mudança de mapa
-> Data Driven
-> Mudança visual de terreno (igual a graminha de pokemon e Zelda a link to the past)

O que possibilitou uma boa organização do projeto foi a implementação da Máquina de Estado mostrada no post anterior.
No método Enter são carregadas as informações que dependem do estado, como a sprite sheet e as informações de área de colisão, por exemplo.

Porém, apesar do meu esforço eu não consegui o fraco acoplamento que eu queria. Queria que a cada funcionalidade que eu fosse implementar não precisasse alterar tanto o código já feito. Mas os componentes mantiveram sua independência, o que já é bom o bastante. O uso de Model View Controller contribuiu para essa independência também.

O próximo passo será implementar a inteligência artificial para NPCs e Inimigos.
Mas uma vez, utilizarei o conceito de Controller separado do Model para facilitar e fazer uma classe AIinput.
Porém ainda me falta teoria para começar implementar.

terça-feira, 21 de dezembro de 2010

Reforma na Action RPG Lib

Considerações para a próxima versão

Problemas

->Problema com os sprites e suas dimensões, já que um sprite pode diferir de tamanho para o mesmo personagem.
Além Disso, existe o problema maior que é onde estaria o referencial de uma imagem. Há sprites em que o pé do Character está na base da imagem e em outros o pé está no meio da imagem.
O que causa problemas no código de colisão e em outros lugares tambem.


Solução
Eu decidi que a posição de cada objeto será o posição da metade da largura objeto e a altura da base. No caso de um humano o Ponto de Referência seria o ponto entre os pés, aproximadamente.


->Animação Baseada em tempo: o problema é quando um personagem anda 0.31 pixels/frame. Na hora de desenhar, cada pixel é indivisível, assim quando arredondo o personagem andará 0 pixels.

Solução
A solução que usei é armazenar cada parcela de pixel que o personagem andou até que se some 1, e assim realizar o movimento.

Decisões

->Para facilitar tanto programação e entendimento será passado como argumento do método os componentes. Assim ficará claro que outros componentes cada componente depende.

->Componente State: A criação desse componente facilitará o controle dos estados do componente.

->Especialização de Componentes: Existirá tipos de State como CharState, ItemState e MonsterState. Assim, cada tipo de GameObject terá um State mais personalizado, simplificando cada Máquina de Estados. Será extendido para controle, Movimentação e muitas outras coisas. Isso irá diminui a genericidade de cada componente, mas simplifica e organiza o código.

->A primeira vista, parece ser interessante abusar do uso de interfaces. O que eu vou tentar fazer.

->Estudar mais a fundo State Pattern

Pra finalizar segue um link interessante sobre Component Pattern

sábado, 18 de dezembro de 2010

Máquina de estados nos Jogos / Game State Machine

Mais uma vez parei de programar devido a um problema que dá vontade de começar tudo de novo.
E só agora realmente tive a vontade de começar tudo de novo.
Para recomeçar eu tive que relembrar alguns conceitos bem importantes e relembrar cada problema que eu tive com a Action RPG Lib.

Estava tudo indo muito bem quando eu lembrei de uma coisa que me encucou bastante.

Máquina de estados. O jogo é uma máquina de estados e alguns objetos do jogo também são máquinas de estados, certo?
Mas o problema é que aquele aglomerado de IFs e ELSEs e CASEs dá a impressão que tem algo errado no código.

void Update()
{
switch( myState )
{
case DoingTheFirstThing:
...
case DoingTheSecondThing:
...
case DoingTheLastThing:
...
}
}


Não existiria uma maneira mais certa ou mais organizada de fazer isso?

Update: O Vinícius Godoy deixou um ótimo artigo que mostra uma ótima solução para Máquina de Estados.
http://www.ai-junkie.com/architecture/state_driven/tut_state1.html
http://sofiaia.wordpress.com/2008/07/11/maquina-de-estados/

domingo, 12 de setembro de 2010

Conclusões - Movimentação

Antes de começar a discursão sobre as conclusões algumas informações sobre a Action RPG Lib.
Os ensinamentos sobre o loop do jogo veio desse artigo http://www.koonsolo.com/news/dewitters-gameloop/
Nele mostra alguns tipos de loop e eu optei pelo loop com velocidade do jogo constante. Apesar dos problemas que poderiam aparecer eu escolhi esse porque é mais simples e, como os jogos serão jogos 2D e que demandarão pouco da CPU, mesmo um computador mais lerdo não deve travar o jogo.
Então o código do meu loop ficaria assim:


while( game_is_running ) {
updateGame(sleep_time);

next_game_tick += SKIP_TICKS;
sleep_time = next_game_tick - GetTickCount();
if( sleep_time >= 0 ) {
Sleep( sleep_time );
}
}


O sleep_time(que vou começar chamar de delta) contém o tempo que o jogo deve ficar parado.
O delta é passado para o método de movimento, então resolvi fazer o movimento assim: distância = velocidade x tempo.
Os objetos que se movem tem uma variável que a velocidade e o delta é o tempo.
Parece ser mais fácil assim controlar a movimentação.

Agora restou fazer a visualização da movimentação.
Tendo em mão uma sprite sheet qualquer dá pra ver o deve ser feito.



Se eu mudar a frame da sheet toda vez que o objeto se movimentar vamos ter um problema, que é:



Então eu coloquei uma taxa de atualização na visualização também, baseada no delta. Agora eu posso controlar a troca de frames e ficaria assim:



Por enquanto é isso.
Related Posts Plugin for WordPress, Blogger...