Categorias → Metal Gear Nanna
Metal Gear Nanna no Google Code
Aos interessados,coloquei o código fonte de Metal Gear Nanna no Google Code.
O endereço é http://code.google.com/p/metalgearnanna/
Metal Gear Nanna – Criando jogos usando C++ e OpenGL: o modelo – Parte II
O mais importante no projeto deste jogo, sem sombra de dúvidas é o modelo, pois os gráficos, assim como toda a interação do usuário com o jogo é resultado do estado definido neste.
Vamos começar pela classe Elemento. Esta representa, como o próprio nome já diz, um objeto que será representado na janela principal do nosso jogo. Trata-se de uma classe abstrata, que irá prover os atributos e métodos básicos que serão utilizados pelos elementos concretos do nosso jogo: Nanna, Inimigo, Parede e Destino (os explicarei novamente a seguir).
Na classe Elemento os seguintes atributos encontram-se definidos:
x e y: a posição do elemento na tela. No caso, por padrão estes elementos irão corresponder ao canto superior esquerdo de cada elemento de tela.
altura e largura: adivinha! :)
visivel: indica se o elemento em questão será renderizado ou não pela aplicação. Este atributo só será de fato útil quando formos trabalhar com a inteligência do jogo.
direcao: a direção do elemento naquele momento. É importante para que saibamos qual imagem renderizar. Por exemplo: se Nanna estiver na direção NORTE, iremos renderizá-la de costas, se for SUL, de frente
A classe abstrata Elemento possui dois métodos abstratos que são fundamentais para nosso jogo:
Elemento::draw(): Desenha o elemento na tela. Cada elemento irá se desenhar de maneira distinta. Por esta razão, este método foi definido como abstrato nesta classe, obrigando as demais a implementá-los.
Elemento::mover(direcao: tipoDirecao, incremento: float): Este método recebe dois parâmetros: direcao e incremento. O parâmetro direcao indica para onde estou movendo o elemento (veja o enum tipoDirecao no diagrama de classes para ver seus valores óbvios), e incremento a distância percorrida pelo elemento a cada chamada deste método. No caso, serão alterados os atributos x e y da classe, que correspondem à sua posição na tela.
Descrita a classe Elemento, vamos passar agora para a descrição das suas classes derivadas:
Nanna: Trata-se de nossa heroina. No estágio inicial do código fonte, trata-se do único elemento que podemos movimentar (e que possui qualquer tipo de movimento, diga-se de passagem). Só para lembrar, o objetivo de Nanna consiste em evitar ao máximo os “Traficantes de Delícias” (classe Inimigo), que uma vez a avistando, irão obrigá-la a comer alguma coisa, reduzindo assim o número de pontos que obteve nos vigilantes do peso.
Estou prevendo para Nanna duas capacidades: a de se movimentar e também a de distrair os seus inimigos. Para tal, Nanna irá gritar, fazendo com que os mesmos mudem de direção, possibilitando assim que ela os despiste.
Inimigo: Ah, estas cozinheiras da Bahia… Vivem nos engordando! Seu comportamento será definido pelo próprio mecanismo do jogo ao invés de Nanna, que será comandada pelo jogador.
No caso do Inimigo, há alguns atributos a mais: ele possui um raio de visão (definido pelo atributo direcao) e também se movimentará sozinho pelas 4 direções em busca de Nanna. Uma vez que esta esteja no seu campo de visão (que também será rendericado), automáticamente Nanna perderá pontos.
Parede: Uma paredde é uma parede, que é uma parede e, bem: uma parede. A única função de uma parede consiste em limitar os movimentos de Nanna. Uma parede não se move (ao menos não inicialmente), sendo assim, o método mover em nada modificará os atributos de uma parede neste momento.
O único método sobrescrito no caso será draw, que deverá expor o esboço exposto ao lado.
Destino: Para chegar ao final de uma fase, Nanna precisa saber aonde chegar. Por esta razão, existe a classe destino. No momento em que Nanna interceptar o destino, o mapa atual será descarregado da memória e o seguinte carregado, até que todos os mapas sejam finalizados e o usuário chegue ao final do jogo.
O Mapa!
O mapa pode ser visto como o container de todos os elementos do nosso jogo. Nele estarão armazenados os apontadores para cada classe derivada de Elemento de nossa aplicação.
Neste estágio atual do jogo, o código mais interessante sem sombra de dúvidas é o mapa, que inclusive já é renderizado (toscamente, é verdade, mas renderizado!), como pode ser visto na imagem abaixo:
Todos os elementos são inicialmente renderizados como quadrados, variando apenas suas cores: Nanna é vermelha, o Inimigo laranja, as paredes azuis e o destino verde (soa quase como um poema, não é mesmo?).
No caso, as posições dos elementos são definidas em arquivos externos, carregados pelo programa quando o mesmo é iniciado. Estes arquivos externos encontram-se no formato texto para que sejam de fácil edição, e são similares ao exposto na imagem abaixo:
Cada linha do arquivo possui um significado:
Primeira linha: nome do mapa
Segunda linha: código interno do mapa (será muito útil em um futuro próximo)
Terceira e quarta linnhas: número de linhas e colunas do mapa (mais sobre isto abaixo)
Linhas subsequentes:
As linhas subsequentes dizem respeito ao posicionamento dos elementos na tela. No caso, es trata de uma matriz de n linhas por m colunas, tal como definido nas linhas de número 3 e 4 do arquivo de configuração do mapa.
Cada caractere dentro desta matriz representa um dos elementos descritos acima: V = vazio, N = Nanna, I = Inimigo e E = Saída. Na realidade, para elementos vazios poderia ser definido qualquer caractere diferente de N, I ou E. No entanto, para que a visualização fique mais fácil, optei pelo caractere V mesmo (se quiser, modifique o arquivo de mapa trocando os caracteres V por qualquer coisa. Você verá que o programa funciona da mesma forma).
Conforme este arquivo é carregado, novas instâncias da classe Elemento vão sendo criadas e seu posicionamento configurado de acordo com a linha e coluna na qual se encontram (fica nítido no código fonte como isto é feito).
Renderização do mapa
A renderização do mapa é simples: neste há um atributo chamado conteudo, do tipo ItemLista. Este na realidade é o elemento inicial de uma linha encadeada. Sendo assim, o que o software realmente faz consiste em interar em cima destes elementos executando o método draw de cada instância. Em seguida, é chamado o método draw do atributo Nanna, que não se encontra dentro desta listagem.
Nanna não se encontra dentro desta listagem por duas razões:
1) É um elemento que é acessado constantemente
2) É um elemento único. Em um mapa, ao menos por enquanto, só pode haver uma Nanna.
O código fonte
Ei! Após ter falado tanto do programa, com certeza vocês devem estar querendo dar uma olhada no mesmo, certo? O disponibilizei para download neste link. Eu sei que é uma maneira bem tosca de disponibilizar código fonte, mas é que ainda estou procurando algum lugar para hospedar o meu repositório Mercurial. Assim que o encontrar liberarei para vocês maiores detalhes sobre como obter versões atualizadas deste bichinho.
(eu pensei no github, mas o estado do git para Windows (sim, estou usando Windows ao invés de Mac OS no desenvolvimento deste projetinho…) atualmente ainda é muito precário, além disto, devo confessar que tenho uma certa preferência pelo Mercurial)
Fontes adicionais de informação
Neste estudo, alguns livros estão sendo de EXTREMA valia para mim:
C++ Como Programar
O melhor livro de C++ que conheço, é o dos Deitel (assim como o livro de Java, Perl e C# também são os melhores).
Se você quer saber o básico de programação em C++, o livro é este.
OpenGL: Uma Abordagem Prática e Objetiva
De Marcelo Cohen
Um excelente texto introdutório ao OpenGL. Basicamente, do pouco que sei de OpenGL até agora, 90% vêm desta fonte.
A abordagem é muito simples, tornando o contato inicial com OpenGL pouquíssimo traumático. Na realidade, é até surpreendente: eu realmente achava que OpenGL fosse algo que só engenheiros da NASA pudessem dominar. Com este livro, vi que a história não é bem assim.
Computer Graphics: Theory Into Practice
De Jeffrey J. McConnell
Enquanto o OpenGL: Uma Abordagem Prática e Objetiva é mais mão na massa, o foco deste livro é mais a teoria por trás da computação gráfica. Aliás, primeiro tomei contato com este livro, e só depois com o primeiro.
Os exemplos do livro são todos em OpenGL, sendo assim, o que o primeiro não tratar, com certeza você encontrará com maiores detalhes neste.
Daqui para frente…
Se você executar o código fonte atual, irá perceber que Nanna pode fazer algo incrível: ela passa pelas paredes. Sendo assim, antes de renderizar Nanna com gráficos melhores, a primeira coisa a ser feita consiste em implementar os algoritmos de detecção de colisão.
Sendo assim, nos próximos posts começarei a trabalhar com maiores detalhes questões referentes à implementação de Metal Gear Nanna. Neste processo, iremos ver como funciona o OpenGL e também quais os erros que venho cometendo neste desenvolvimento (o que normalmente é o mais interessante em todo aprendizado).
Logo… até o final de semana que vêm (ou antes)!
Metal Gear Nanna – Criando jogos usando C++ e Open GL – Parte I
Iniciei um novo hobby neste final de semana: criação de jogos. De todas as atividades, a que mais me diverte sem sombra de dúvidas consiste em programar (há momentos nos quais tenho de me beliscar para acreditar que me pagam para isto!).
Após ter desenvolvido zilhões de aplicações empresariais/corporativas, acabo por ter a impressão/certeza de que sempre estou executando as mesmas tarefas: CRUD, validação de dados, formulários, bancos de dados, etc. Que tédio!
A solução para acabar com o problema consiste em buscar algo completamente diferente do feijão com arroz. O que poderia ser mais distinto que o desenvolvimento de um jogo?
- A interface com o usuário não é a partir de formulários
- Não preciso lidar com banco de dados algum (ainda irei escrever um dia sobre a minha teoria de que bancos de dados emburrecem programadores)!
- É significativamente mais complexo, pois preciso gerenciar detalhes de gerenciamento de recursos com muito maior detalhamento.
- Não estou preso a nenhuma restrição comercial!
Objetivos pessoais
Meus objetivos pessoais neste projeto consistem em me aprofundar no aprendizado do C++ e OpenGL a partir de uma aplicação real. Já faz no mínimo uns 6 anos que sei C++, porém nunca tive uma oportunidade de usá-la em um projeto real. Visto que a oportunidade não veio, porque não criá-la?
Além disto, ano passado fiz a matéria “Computação Gráfica” na faculdade, aonde aprendi OpenGL, que abriu meus olhos para o fato de que desenvolver aplicações gráficas não é algo tão complexo como até então imaginava. Na realidade, como exporei nesta série de posts, é quase fácil.
Enredo e Objetivo
O personagem principal da história é Nanna (minha esposa (aliás, uma bela maneira de homenagear quem amamos, não é mesmo?)), que após entrar para o grupo dos Vigilantes do Peso precisa vencer as tentações da vida dietética. A jogabilidade será basicamente a mesma presente no jogo Metal Gear original para MSX.
(a propósito, enquanto escrevia este post, descobri que existe uma versão do jogo para PC que pode ser baixada aqui)
Nanna deverá chegar à sede dos vigilantes do peso saindo de sua casa. Mas o caminho não é tão tranquilo quanto aparenta, pois Nanna precisa evitar os malditos “Traficantes de Delícias” que, caso a vejam, acabarão por convencê-la a comer alguma coisa.
Cada um destes traficantes possui um raio de visão que Nanna deverá evitar. Caso a vejam, automáticamente nossa heroina perderá pontos. O jogo termina se uma das condições abaixo for satisfeita:
- Nanna está com pontos menores ou iguais a zero.
- Nanna chegou à sede dos vigilantes do peso em todas as fases.
Ainda não pensei se será possível restaurar pontos perdidos, porém nada impede que, além dos malditos traficantes, também existam “academias” espalhadas pelos diversos níveis do jogo aonde Nanna poderá voltar à boa forma.
Plataforma adotada
Como mencionei acima, um dos objetivos deste projeto consiste em me aprofundar em C++ e OpenGL. Dentre as diversas IDEs existentes atualmente, acabei por adotar o Dev-C++ pelas razões abaixo:
- Possui pouquíssimos recursos, o que faz com que eu me sinta o mais próximo possível do compilador.
- Possui integração com as bibliotecas do OpenGL que precisarei.
- Caso no futuro eu desista desta IDE, ela não impõe nenhuma estrutura de diretórios ou restrição que me impeça de no futuro utilizar o editor/IDE que eu queira.
Será utilizada a biblioteca GLUT do OpenGL para o desenvolvimento deste jogo. GLUT significa Open GL Utility Toolkit, que consiste em uma biblioteca de funcionalidades da Open GL cujo principal objetivo consiste em abstrair o sistema operacional da aplicação, tornando-a assim multiplataforma. Dentre estes detalhes, encontra-se a criação de janelas e componentes de interface. A biblioteca GLUT foi implementada para basicamente todos os principais sistemas operacionais em uso atualmente. Sendo assim, você poderá pegar o código fonte qeu disponibilizarei e compilá-lo no sistema operacional de sua preferência.
Configurando o ambiente de desenvolvimento
Instalado o Dev-C++ em seu site oficial (http://www.bloodshed.net/devcpp.html), tudo o que você precisará fazer consiste em instalar a biblioteca GLUT no mesmo.
Abrindo o Dev-C++, clique no item de menu “Check for Updates/Packages…”. Surgirá uma janela tal como na imagem abaixo:
Localize o pacote GLUT na listagem presente e em seguida clique no botão “Download selected”. Pronto: o GLUT será baixado e em seguida instalado para uso pelo Dev-C++.
O que está por vir
Não tenho experiência ALGUMA no desenvolvimento de jogos, sendo assim, estou adotando um raciocínio out of the box neste processo, ou seja, o motor responsável pelo funcionamento de Metal Gear Nanna será inteiramente baseado na minha experiência como jogador de Metal Gear 1 e 2 para MSX.
Como consequência, irei reinventar inúmeras vezes a roda neste processo, o que é exatamente a intenção aqui. Pretendo com isto saber a fundo como funcionam todos os aspectos no desenvolvimento de jogos no nível mais baixo possível.
No próximo post irei disponibilizar o código fonte já criado e expor o modelo por trás do funcionamento de Metal Gear Nanna (e, espero, irei também expor gráficos bem melhores do que os obtidos por mim até a escrita deste post).
Até lá!










