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...