[Projeto Niflheim] 7DRL e motivação

Desenvolvimento de jogos.

São três palavras que soam mais convidativas a cada momento. Por isso, a idéia de um projeto pequeno e rápido é perfeita para complementar nossa experiência: passaremos 7 dias em um único projeto de jogo, e o objetivo é iniciá-lo, construí-lo, e terminá-lo neste tempo.  Este é exatamente o objetivo do 7DRL (sigla em inglês para 7 Day Roguelike), um desafio online para elaboração de um jogo do gênero roguelike em 7 dias.

A idéia de participar começou com um convite feito de um amigo para outro, que aceitou no ato. Logo depois, já estávamos discutindo temas e história, funcionalidade e organização de tarefas. Já havíamos discutido a possibilidade de um projeto conjunto, porém nada concreto.

O projeto que realizaremos não será como os roguelikes “clássicos”, isto é: teremos imagens para arte no lugar de caracteres ASCII, e controles e atributos de personagem simplificados para garantir o fácil entendimento do jogo. Utilizaremos também o cenário da mitologia nórdica – mais especificamente o plano de Niflheim. Isto nos permite nos preocupar com a parte técnica do jogo, pois a história, cenário, e “lore” já está criada.

Angband: um clássico roguelike

Minha própria experiência em game dev é pouca,  não passando de alguns projetos iniciados e não terminados em diversas tecnologias, desde RPG Maker até Android.

Por isto, decididimos documentar todo nosso desenvolvimento neste blog, para que possamos olhar para trás e ver como um pequeno jogo de 7 dias impactou em nosso desenvolvimento – mas se será realmente terminado, só veremos daqui a 7 dias.

Advertisements
Posted in Projeto Nifheim

Iniciando um projeto 2d base no XNA

Algumas pessoas podem ter medo de criar um novo projeto do 0 sem ter estruturado o básico possível de uma arquitetura orientada a objeto que funcione corretamente.
Acho muito válido a pessoa desenhar no papel uma estrutura de classes simples antes de programar, mas acredito que exista a necessidade de um equilíbrio entre intuição e organização para se fazer um bom código.
Neste começo, eu fiz um pouco dos dois para criar o projeto da melhor forma possível. Graças ao pouco investimento do governo de São Paulo nos transportes públicos, tenho um grande de sobra entre minhas idas e voltas do trabalho, e foi neste tempo que aproveitei meu bloquinho de idéias para estruturar uma arquitetura simples para o jogo.

Fazia muito tempo que não mexia com XNA, mas é quase como andar de bicicleta. Desta forma, resolvi ter como objetivo desenhar um boneco na tela, apenas para relembrar os callbacks da ferramenta. Porém, aproveitei para já ir implementando algumas soluções que um código orientado a objeto pode fornecer.

Iniciei o projeto com o nome RoguelikeProject, e as estruturas básicas do XNA foram criadas.

É fácil perceber que qualquer personagem em um jogo possua propriedades semelhantes. Desta forma, resolvi criar uma estrutura chamada Char, pensando na possibilidade de qualquer personagem no jogo ter as mesmas características.
De início, nossa classe Char possui as seguintes propriedades:
Position, para determinar a posição relativa do personagem;
Texture, para armazenar a textura do personagem;
Rectangle, para determinar o frame do personagem;

classChar

Isto permite que consigamos atribuir estas características para cada personagem. Porém, ainda precisamos atribuir os valores a cada propriedade.
O XNA possui callbacks padrões para cada parte da execução do jogo. Resumidamente, podemos destacar os 3 callbacks principais da seguinte forma:

LoadContent, onde os recursos como texturas e outros arquivos são armazenados na memória;
Update, responsável por atualizar a lógica do jogo a cada iteração;
Draw, responsável por atualizar os gráficos do jogo a cada iteração;

É necessário imaginar que cada personagem precisará realizar estas 3 ações, sendo gerenciados pela classe principal Game1.cs.
Poderíamos instanciar nosso personagem na classe principal, e realizar as ações nos métodos da classe. Porém, se realmente queremos já implementarmos os conceitos de POO da maneira correta, devemos delegar estas ações para a própria classe Char.
Mas ainda precisamos pensar mais a frente. Sabemos que todo personagem ou outro elemento do jogo terá estas 3 ações necessáriamente. Por isto, criamos a classe abstrata XNAObject, da qual possui os 3 métodos abstratos, obrigando a classe que a herdar de implementa-los.

classeAbstrata

Desta forma, podemos fazer a classe Char herdar de XNAObject, e implementar seus métodos.

classeHerdada

Finalmente, basta instanciar o Character no Game1, chamar os métodos nos locais certos e testar para ver se funciona.

roguelike

É necessário pensarmos também que o jogador não andará livremente pelo cenário, e sim em cima de áreas específicas, como em um próprio jogo de dungeon crawler.

É fácil pensarmos nesta estrutura. O conceito básico de um mapa de dungeon crawler é que ele é dividido como uma matriz, onde cada  quadrado representa um possível local que o jogador poderá andar, ou que esteja guardando alguma coisa, conforme ilustrado na imagem abaixo.

map

Desta forma, é fácil imaginar como esta estrutura deverá ficar. Chamamos cada quadrado deste de Tile, o qual possui uma posição e um tamanho. Porém, ambas estas propriedades serão privadas, e terão seus valores setados apenas no construtor.

classeTile

Precisamos agora criar um modelo para a própria Dungeon. É muito fácil imaginar a Dungeon como uma matriz de Tiles (nem sempre será assim, pois a Dungeon não terá tamanhos uniformes), então, de começo, temos uma matriz de Tiles que organiza a Dungeon em espaços. A partir deste momento, criamos um construtor em que definimos apenas o tamanho da Dungeon, e a posição de cada tile é definida dinâmicamente. A idéia é posteriormente receber isto de um arquivo de texto ou XML, mas por enquanto, é o suficiente para o que precisamos.

Também  definimos uma propriedade chamada InitialPosition, a qual o jogador estará quando entrar na Dungeon pela primeira vez.

classeDungeon

É importante agora redefinirmos um conceito de cada Char. A posição de um Char esta relacionada a um Tile, e não mais a um ponto 2D. Logo, fazemos esta alteração na classe Char.

position

Por fim, definimos um controlador que ficará responsável pelo controle da Dungeon. O Controle passará a receber o Char, e a controlar as atualizações de cada objeto dentro da dungeon.

DungeonController

É claro que poderíamos ter feito de uma forma muito mais abstrata, e deixar o código muito mais elegante. Porém, isto já é o suficiente para conseguirmos trabalhar no código decentemente, e irmos evoluindo com o tempo. A idéia é irmos melhorando cada estrutura de acordo com a nossa necessidade, e irmos adaptando conforme acharmos necessário
Com este núcleo básico criado, podemos nos focar nas estruturas básicas para a gerência de regras de nosso jogo.

Tagged with:
Posted in Projeto Nifheim
In Archive