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.

terça-feira, 17 de agosto de 2010

Volta das férias

Após a pausa para as férias a actionrpglib volta.
Estou pulando algumas etapas para começar fazer alguns testes. Se for interessante eu posto alguma coisa aqui, senão eu volto com a programação normal.

segunda-feira, 7 de junho de 2010

Componentes Talk e Fight

Agora vamos falar dos componentes responsáveis pelos diálogos do jogo e pela Action do Action RPG.
Para diálogos eu pensei em 2 componentes: o Talk e o Listen. Um responsável por falar e outro por ouvir. Quem ouve são os jogadores, então apenas eles terão esse componente. Já o Talk estaria presente em qualquer entidade que tiver algo a falar. Vai ser nesse componente que vai ficar o texto a ser mostrado. O exemplo mais óbvio é um NPC da cidade falando sobre o mal que assombra a cidade mas tem muitos outro também. Uma placa indicando a direção do castelo precisa "falar" pois para o jogador o texto da placa aparece na forma de diálogo. Uma árvore também pode falar ou um baú trancado avisa que ele está trancado.
O componente Listen acessa o componente Talk da outra entidade, ativando o dialógo que é mostrado na tela.
Para a luta vai existir um componente Fight. Ele vai ser responsável pelo ataque e pelos testes de acerto. Aqui também ficarão propriedades relacionadas como precisão e esquiva e essas propriedades podem ser alteradas pelos componentes relacionados a os atributos como um componente de habilidades do personagem. Porém o Fight não enxergará esses componentes e agirá independente dos mesmos.

domingo, 30 de maio de 2010

Detalhes de implementação

Após escolher a estrutura do jogo faltava definir como seria a implementação dos componentes e da classe GameObject. O decidido foi fazer uma classe Component e todas os componentes herdam essa classe. Além disso a Component tem um ponteiro de map de GameObjects.
Eu prefiri definir a classe GameObject apenas com os componentes e com um identificador.

class GameObject {
public:
typedef int ObjID;
GameObject();
virtual ~GameObject();
Collection components;
};

class Component {
//ID do objeto que contem o componente
GameObject::ObjID owner;
public:
//Contem todos os objetos do jogo
map *objs;
// Todo componente tem um tipo
virtual int getType(){
return -1;
}
GameObject::ObjID getOwner() const
{
return owner;
}
}

Qualquer atributo como nome do objeto ou outra funcionalidade será adicionada a classe na forma de um componente. Os componentes podem ser criados pelo objeto ou fora do objeto.
Dentro do objeto tem o problema de deixar o objeto mais difícil de reconfigurar e uma vez que uma das vantagens de usar componentes é deixar o objeto mais flexível, isso é um problema a ser considerado.
Fora do objeto o código externo passará o componente criado para o objeto e isso manterá a flexibilidade, já que o objeto poderá ser alterado completamente apenas alterando seus componentes. Outra vantagem é a de que, como o GameObject recebe os componentes criados como classes derivadas de Component e por isso ele só conhece essa classe, o código está mantendo um fraco encapsulamento.

O problema agora é como seria a comunicação entre os componentes, uma vez que o componente Movement precisa do componente Position, por exemplo. Há três formas:
Acesso direto aos outros componentes
Na minha opinião é maís fácil de se pensar uma vez que não é preciso realizar a comunicação implicitamente utilizando métodos da classe componente. Porém tem a desvantagem de aumentar o acoplamento. A grande vantagem é que é simples e rápida.
Modificando atributos do GameObject
Diminui o acoplamento porque os componentes não sabem da existência um do outro. E requer informações compatilhadas e isso pode causar uma sobrecarga da classe GameObject com informações que nem todo objeto do jogo vai precisar. Além disso a comunicação seria implícita, o que aumenta a dificuldade de projetar o jogo.
Por mensagens
É o mais complexo mas tem fraco acoplamento e a classe GameObject é mais simples. O acoplamento seria deixado para o valor das mensagens e da interpretação da mesma e não requer informação compartilhada porque a troca de informação é feita apenas entre componentes.

Não há resposta certa e é aconselhado usar um pouco de cada. Em alguns componentes muito relacionados como Movement e Position não seria tanto problema o acoplamento devido ao acesso direto porque eles já são acoplados por um depender tanto do outro. Caso todos os objetos tem alguma informação comum ela pode ser compartilhada entre os componentes.
As mensagens normalmente são usadas para comunicação menos importante, como uma comunicação entre o componente de áudio e o componente físico.

Na Action RPG Lib eu optei por começar usando o acesso direto dos componentes porque eu ainda não vou descrever todo o sistema antes de começar programar e é mais fácil de pensar. Se no meio do projeto eu perceber que seria melhor outras abordagens eu tento implementa-las ou anoto para implementar na versão 2(espero).

Fonte: Game Programming Patterns - Component

quarta-feira, 26 de maio de 2010

Herança x Componentes

Quando eu comecei a Action RPG Lib mais programando do que projetando ela era baseada em herança.
Mas eu comecei ter umas dúvidas de como eram organizados os jogos e acabei achando muitos artigos falando sobre o porque de não usar herança nos jogos e fui apresentado a programação de jogos baseada em componentes.
Esses artigos falam das várias desvantagens de se utilizar herança e as vantagens de se utilizar componentes.
Evolve Your Heirachy
Component-Based Architechture: Getting Away from Inheritance
A grande vantagem dos componentes que me convenceu a utilizar essa abordagem é o fato de ser muito mais reutilizável. E o que tem sido minha dificuldade fazendo do modo antigo era manter um código de fraco acoplamento.
No jogos Component-based os objetos do jogo são todos da mesma classe, GameObject no meu caso. O que muda de uma item para o personagem são os componentes que eles terão. Então o personagem teria um componente para posição, para movimento e para a fala, por exemplo. Uma árvore teria posição apenas. Mas se eu quisesse uma árvore que fala eu colocaria um componente de fala nessa árvore. Para o caso do meu jogo a grande vantagem é que eu poderia implementar várias funcionalidades depois, na forma de componentes.

sexta-feira, 14 de maio de 2010

Apresentanto a Action RPG Lib

A idéia de fazer a Action RPG Lib surgiu depois da minha insatisfação com a falta de jogos de Action RPG 2-player para Super Nintendo. Há algum tempo atrás eu e minha namorada jogamos Seiken Densetsu 3 e ficamos maravilhados com o jogo. Ele tem uma ótima história, vários personagens e grande jogabilidade além de gráficos muito legais. Mas o que eu vim a descobrir depois que o que realmente faz desse jogo único em sua categoria é o 3-player que Seiken Densetsu 3 tem. Após várias buscas e vários fóruns descobri que não existe outro RPG de Super Nintendo 2-player e mesmo em outros consoles como PSX e PS2 é muito raro. E pelas buscas e fóruns da net acabei por descobrir que tem muita gente que quer um “RPG co-op for SNES” assim como eu.

ACTION RPG LIB

Preview
Fazer uma coleção de bibliotecas que possam ser usadas para o desenvolvimento de jogos de Action RPG 2D.

Objetivos
A biblioteca deve tratar dos Gráficos, sons, entrada e a lógica dos jogos;
Prover funcionalidades para diferentes tipos de Action RPGs 2D;
Manter alta coesão e acoplamento fraco;
Partir de um projeto simples, mas com facilidade de alterar e adicionar funcionalidades.

Primeiras escolhas
O projeto será desenvolvido em C++;
O conceito de POO deve ser bem utilizado;
A SDL será utilizada para tratar dos gráficos, sons e entrada;
A linguagem de script Lua deve ser usada para IA e outras funcionalidades(ainda não definidas);
A lógica deve ser cuidadosamente desenvolvida independente da SDL e da Lua.
A biblioteca será Component-Based

Descrição dos sistemas
  1. Arquivos
    Haverá um arquivo principal que vai conter valores das constantes que deve ser aberto na inicialização da biblioteca. O uso do arquivo é importante porque assim não será necessário recompilar tudo ao se alterarem valores. Muito útil para testes.
    Cada personagem e cada cenário terão arquivos com valores relativos.
  2. Gráficos
    A ideia inicial é fazer um sistema de jogos 2D ortogonal.
    Os cenários devem ser construídos por tilesets e os personagens serão charsets. Não deve haver restrição para tamanho dos tiles nem tamanho nem tipo de charset.
  3. Sons
  4. Entrada
    A classe de entrada deve ser feita de modo flexível. O jogador deve poder alterar as teclas para maior conforto do mesmo. Também deverá ser implementado o Joypad.
  5. Multiplayer
    A primeira ideia é fazer single player mas com possível ampliação para 2-players. No futuro deve ser implementado também a possibilidade de jogo multiplayer por TCP/IP.
  6. Logs
    Deverá existir um sistema de logs que vai conter todos os erros e algumas saídas da biblioteca para poder ser sempre melhorada.

Classes Principais
  1. A classe de manipulação de arquivos será responsável por abrir, interpretar e fechar todos os arquivos do jogo, de txt até imagens.
  2. A classe gráficos terá uma coleção de imagens e será responsável pela saída de vídeo do jogo.

quinta-feira, 13 de maio de 2010

Bem Vindo!

Este blog trará a Action RPG Lib e várias discursões sobre o desenvolvimento de jogos.
Related Posts Plugin for WordPress, Blogger...