Post on 08-Nov-2018
Animação e Visualização Tridimensional - Alameda 18 de Dezembro 2008
Heru
Bruno Vidal 56920 LEIC
bruno.vidal@ist.utl.pt
Raquel Costa 57745 LEIC
rgcc@ist.utl.pt
Vando Pereira 56847 LEIC
vandopereira@ist.utl.pt
Sumário
“Heru é um jogo de acção e plataformas com momentos de primeira pessoa”. Esta foi a frase que definiu o primeiro esboço do conceito, a partir desse momento todo o desenvolvimento foi feito de modo a concretizar esta
afirmação da melhor forma. Para tal, foi necessário criar muita tecnologia, além de toda a lógica de jogo. Entre as mais importantes encontram-se o movimento no mapa de alturas, a
detecção de colisões e o carregamento/animação de modelos. Em paralelo com o desenvolvimento da tecnologia, foi necessário criar os elementos que definiriam a jogabilidade, completando os elementos para concretizar o conceito de modo a tornar o jogo minimamente desafiante.
1. Conceito
O Heru apresenta-se, na sua essência, como um jogo de acção em plataformas,
enriquecido com mini-jogos de first person shooting e puzzles. Esta mistura de
géneros permite uma maior liberdade criativa, podendo proporcionar uma
jogabilidade diversa e envolvente.
A ideia inicial passou por ser um jogo de plataformas, mais ao estilo tradicional,
baseado nos grandes clássicos 2D como o Super Mario ou o Sonic, títulos que com o
passar do tempo conseguiram uma transição muito bem sucedida para o 3D. Ainda
assim, para alargar horizontes, recorreu-se a inspiração noutros outros géneros,
nomeadamente aos slash-em-up como Ninja Gaiden (com influência óbvia na escolha
do personagem principal) e aos first person shooters (de que Halo serve de exemplo).
Este jogo acompanha uma aventura de Heru, um ninja cujo objectivo é aniquilar
os inimigos e apanhar objectos valiosos que estão dispersos pelo cenário.
A principal mecânica de jogo utiliza uma câmara na terceira pessoa e consiste em
controlar o protagonista ao longo dos níveis de plataformas, combatendo os inimigos
(que tomam a iniciativa de o atacar, desde que estejam dentro do seu raio de acção).
Para além do que já foi referido, também existem no cenário situações de mini-
jogo onde o jogador terá de se empenhar, a fim de abrir caminho, ultrapassando
obstáculos que lhe são colocados. Os dois tipos de mini-jogo desenvolvidos são:
Pontos de arma fixa na primeira pessoa: as turrets de muitos dos FPSs de
hoje em dia que o jogador terá de usar a fim de abrir caminho
ultrapassando obstáculos que lhe são colocados.
Puzzles de sequência: alguns artefactos têm de ser activados numa
determinada ordem para despoletar um evento que permita seguir
caminho.
2. Guia de referência rápida para Utilizador Experiente
Controlos de Game-play
Acção Botão
Andar W,A,S,D
Correr W,A,S,D + Botão
direito do rato
Saltar Barra de Espaços
Atacar Botão esquerdo do
rato
Apanhar items E
Utilizar turrets F
Pausa/Menu Esc
Ataque Mortal Saltar para cima de
um inimigo (Retira
25% da vida do
jogador)
Objectivo do jogo
Chegar ao fim do nível, aniquilando todos os
inimigos, ultrapassando os obstáculos e obtendo o
maior número de Heuros.
Game Over
Existem três formas de morrer:
- Cair de grandes alturas
- Em combate
- Cair dentro de água
Menus Para navegar nos menus devem utilizar-se as teclas
direccionais e a tecla ENTER para confirmar. No
caso de opções de valor múltiplo, a definição
desejada pode ser escolhida com as teclas
esquerda/direita.
Dificuldade Existem três níveis de dificuldade (Easy, Medium e
Hard) que influenciam a prestação dos inimigos:
quanto mais alto o nível, mais rápidos e poderosos
estes ficam.
PC Specification Existem três tipos de profiles, que influenciam o
modo como o jogo é carregado. Esta é a opção a
modificar caso o jogo sofra de problemas de
performance.
Slow – Para computadores com grandes limitações
ao nível de processador e placa gráfica
Medium – Para computadores já com uma superior
disponibilidade, principalmente ao nível do
processador
Fast – Para computadores com um processador e
placa gráfica, relativamente recentes.
In-Game Interface Barra da vida
Mostra o estado actual da vida do Heru.
Os ataques dos inimigos diminuem a vida do Heru.
Se a barra ficar vazia, o Heru morre e é Game Over.
Para aumentar a barra da vida, o Heru pode apanhar
objectos que aumentam a vida.
Heuros Indicam o valor que o jogador juntou ao
apanhar os tesouros e matar inimigos.
Objectos para interagir O Heru interage com vários objectos:
Armas Fixas: Disparam contra
obstáculos, de modo a abrir
caminho para o jogador.
Puzzles: Sequências de botões a carregar na ordem
certa para abrir passagens.
Para carregar num botão
basta andar ou saltar para
cima dele. Quando um botão
é carregado na ordem certa
fica verde, caso contrário
mantém-se vermelho.
Itens Especiais
Power ups Aumentam a energia do Heru em metade do
valor máximo, encontram-se espalhados e
escondidos pelo cenário.
Heuros: Estão espalhados pelo cenário e contam para a
pontuação que posiciona o jogador no ranking.
Aniquilar inimigos também da Heuros!
3. Arquitectura e Bibliotecas Externas
A arquitectura que suporta o Heru está representada no diagrama abaixo, onde se
detalham os seus principais componentes. Pode-se dividir em três grandes blocos:
Gestão de Recursos;
Lógica de Jogo;
Detecção de Colisões.
O primeiro encapsula grande parte das tarefas de carregamento de imagens
(texturas), materiais, objectos (estáticos e dinâmicos). Ao nível das imagens, o
funcionamento deste bloco de componentes é suportado pela Devil, uma bibiloteca de
carregamento de imagens multi-formato que foi utilizada, entre outras coisas, para
carregar texturas directamente para uma das representações internas openGL. É
também com recurso a esta biblioteca que, por exemplo, é lido o mapa de normais do
terreno.
A responsabilidade da gestão de recursos nesta arquitectura está dividida em dois
sub-módulos criados para o efeito: um para os objectos, Object Manager, que mantém
referências para display lists de modelos OBJ importados, através da GLM, de
displaylists próprias previamente criadas, ou ainda de modelos animados Md2, através
de uma outra biblioteca externa adaptada (Md2Lib[3]) e outro para recursos mais
genéricos, o Resource Manager. Este resource manager guarda então referências para
materiais, texturas e luzes, possibilitando a reutilização destas.
Passando à detecção de colisões, este é o bloco que permite que haja interacção
entre o jogador e os objectos. No entanto uma explicação detalhada sobre o seu
funcionamento encontra-se no ponto “Algoritmos Relevantes ”, onde se explica todos
os intervenientes deste sistema e qual o seu papel.
Quanto à lógica de jogo, este é o maior bloco da arquitectura onde se concentram
vários tipos de entidades. As principais entidades deste bloco são os níveis e os seus
objectos. Foi feito um esforço, ao desenhar esta arquitectura, para que toda a
interacção que existisse num nível fosse detectada independentemente do tipo. Assim
surgiu a classe objecto, de onde herdam todos os tipos de objectos que interagem de
alguma maneira com o jogador, jogador esse que também herda de objecto.
De notar que o principal atributo desta classe objecto, é o seu volume envolvente,
utilizado no sistema de detecção de colisões.
Além dos habituais tipos de objectos, existem dois outros tipos considerados
especiais, são eles os AnimatedObjecs e os TriggerActionObjects. Os primeiros são
objectos que têm algum tipo de animação básica, que pode ser invocada por outros
objectos ou entidades. Os segundos são os objectos que podem invocar a animação
dos AnimatedObjects, neste caso com base em projécteis, que ao atingirem um
determinado ponto, desencadeiam a animação.
Já as entidades que também podem invocar a animação dos AnimatedObjects são
os MiniGames, esta classe é responsável por gerir uma colecção de “switches” que
tem uma ordem específica. Ao activar os switches pela ordem correcta, mais uma vez
activa-se a animação do AnimatedObject ligado a este.
Saindo um pouco do nível, existe, além das classes responsáveis pelos menus,
Head Up Display e Ranking, uma classe responsável por gerir os estados do jogo. O
LogicManager mantém internamente os diferentes estados do jogo, incluindo dentro
dos menus. Sendo assim todo o fluxo de execução do jogo, segue um ramo
determinado por uma sequência de estados, estados esses que estão especificados
nesta classe.
Por fim, as bibliotecas utilizadas foram essencialmente, e como já referido,
bibliotecas de carregamento de recursos. De seguida enumeram-se as bibliotecas e
qual o motivo porque foram adoptadas:
- Ft2Lib[4]
– Biblioteca de carregamento de TrueType Fonts. Embora complicada
de usar, foi utilizada uma camada de abstracção denominada GLFT_Font[8], para que
a utilização desta lib se tornasse trivial em OpenGL. A Ft2Lib é uma das mais
completas bibliotecas de suporte a fontes.
- GLM[5]
– Biblioteca que permite o carregamento de ficheiros WaveFront OBJ.
Existiam muitas alternativas aos modelos estáticos que poderiam ter sido utilizados.
No entanto optou-se pela utilização deste tipo, devido a esta ser uma biblioteca
simples de usar e já com provas dadas.
- DeviL[6]
– Biblioteca de carregamento de imagens. Esta biblioteca já é requerida
pela versão da GLM utilizada. Assim sendo, utilizou-se a DeviL para carregamento de
todas as texturas. Entre as maiores vantagens desta biblioteca, destacam-se a
possibilidade de abrir um vasto tipo de imagens, sempre da mesma forma e
devolvendo logo o identificador tal como as funções do OpenGL necessitam. Além
disso esta biblioteca, não só abre ficheiros dos tipos tradicionais (jpg, tga, etc) como
tipos vectoriais, como por exemplo os do Photoshop.
- XmParserlLib[7]
– Quanto a esta biblioteca, trata-se de um parser XML utilizado
para o carregamento dos níveis. Optou-se por esta solução uma vez que era bastante
simples e compacta, além de utilizar smart pointers, tornando assim desnecessária a
gestão de memória alocada por esta biblioteca.
- Md2Lib[3]
– Esta biblioteca foi utilizada para o carregamento dos modelos
animados MD2, mas foi bastante modificada de modo a incluir transição entre
animações diferentes. Além desta modificação, fez-se ainda uma indexação das
animações, de modo a evitar a pesquisa sequencial, bastante lenta, que inicialmente
vinha implementada. Esta biblioteca usada encontra-se no MD2Loader, para carregar
toda a informação necessária para o desenho dos GameChars.
4. Configurabilidade e Extensibilidade
Os pontos de extensibilidade e configurabilidade deste jogo assentam
essencialmente no modo como são carregados os níveis e respectivos recursos.
Fundamentalmente, criar novos níveis é tão simples como criar um ficheiro
XML, ficheiro este pensado e criado para que no futuro pudesse ser criado um editor
de níveis, assim qualquer utilizador pudesse criar um nível à sua vontade. Tudo no
nível está descrito num ficheiro XML, desde os recursos (modelos, texturas, luzes,
etc.), às posições ou à forma do terreno.
Uma vez que criar um editor de níveis, não eram um dos objectivos, existe a
necessidade criar o terreno num programa denominado L3DT, que permite desenhar o
terreno e no final exporta-o para um ficheiro RAW e gera a respectiva textura, com o
tipo de clima/ambiente pretendido. A partir desse programa, também é possível criar a
SkyBox à medida, exportando o mundo para um programa de geração de imagens
Ultra-Realistas denominado TerraGen. De salientar que o processo de criação do
terreno, neste programa pode ser tanto automático, como manual. Recomenda-se o
uso do modo manual para que o terreno se adapte ao tipo de jogo.
Outro ponto importante no jogo são os chamados mini-jogos, que permitem
adicionar algum nível de dificuldade e de desafio ao jogador. Na realidade um mini-
jogo é um conjunto de acções que desencadeia uma animação num objecto. Esta
animação pode ser usada para abrir caminho ou para aceder a locais que
aparentemente não são acessíveis ao jogador. Aqui mais uma vez reina a
simplicidade, basta especificar o número de “botões” pretendido, qual a sua posição, a
ordem (esta ordem determina a sequência necessária de activação para resolver o
puzzle) e por fim qual o objecto que este vai activar. Estes objectos não são mais do
que caixas que ao rodarem (de várias maneiras possíveis) desbloqueiam caminhos.
Quanto aos restantes elementos do jogo, o método é semelhante para todos,
especificar o tipo de objecto (powerUps, dinheiro, armas fixas, inimigos), a posição e
algumas propriedades típicas de cada um.
Para os inimigos e objectos, existem uma colecção de modelos/texturas, mas
podem ser adicionados qualquer outro, bastando para isso especificar a localização
deste no XML.
Quanto à extensão do jogo, à configuração de níveis, ou mesmo à sua ordem,
tudo isto é determinado pela quantidade e pelos nomes dos ficheiros XML existentes
no directório “xml”, ou seja, o jogo tem tantos níveis, quantas as descrições em XML
existentes. É apenas necessário respeitar a nomenclatura dos ficheiros, a qual está
especificada no ficheiro README.txt, no mesmo directório.
Ao nível da configurabilidade “in-game”, o utilizador pode optar por diferentes níveis
de detalhe, por resoluções da janela diferentes e pode ainda escolher a dificuldade.
5. Algoritmos Relevantes
Movimento no mapa de alturas
Para recriar um terreno montanhoso que proporcione múltiplos pontos de plataformas,
foi utilizado um mapa de alturas. Foi desenhado o cenário em 3D, recorrendo a uma
ferramenta de geração de terrenos (L3DT), a qual produz uma imagem em escala de
cinzentos (formato RAW), em que cada pixel da imagem corresponde a uma altura na
zona do mapa e vai servir como vértice para o desenho da triangle strip que constrói o
mapa.
Como era pretendido que o terreno fosse iluminado pelo OpenGL, tornou-se
necessário calcular as normais ao chão. Para levar esta tarefa a cabo foi utilizado mais
uma vez a ferramenta L3DT que gera um mapa de normais (vertex normals) em
formato de imagem para cada um dos vértices do mapa de alturas original.
Quando o personagem anda sobre o mapa, a sua altura é ajustada para corresponder à
do triângulo onde se encontra. A generalização deste comportamento durante um salto
ou durante uma queda levaria a uma mudança repentina e irrealista de posição. Para
contornar esta situação, foi definido um algoritmo de interpolação, integrado na nossa
classe de física que vai ajustando a posição até convergir para um valor alvo (o qual
pode ir mudando, por exemplo, no caso de um salto de uma plataforma para outra, em
que exista um fosso entre elas).
Optámos por implementar de raiz uma aproximação à física do mundo real, que nos
permite executar todos os movimentos do personagem. Utilizámos quaterniões para
suportar as rotações e a já referida interpolação de posições para os saltos e quedas,
cuja actualização se baseia nas equações de movimento ligeiramente adaptadas para
as nossas necessidades mas que nos permitem imprimir velocidades e acelerações de
forma adequada.
Detecção de colisões – “A Homemade approach”
Sendo este um jogo de plataformas com combate corpo-a-corpo, torna-se
inevitável um sistema de colisões minimamente competente e preciso. Embora
existisse esta restrição, optou-se por criar um sistema de detecção de colisões de
raiz, ao invés de usar um motor de física ou de colisões já existentes.
Os tipos de colisões que se podem encontrar neste jogo são as colisões com o
cenário e colisões com os objectos.
As colisões com o cenário são explicadas no ponto acima “Movimento no
mapa de alturas”, portanto esta explicação irá centrar-se nas colisões com
objectos. Esta detecção assenta principalmente em dois conceitos, volumes
envolventes e registo de colisões. Esta detecção é denominada AABB (“Aligned
Axis Bounding Boxes”) e tem por base a detecção de colisões aquando a
intersecção de duas caixas.
Neste jogo, o sistema criado para o efeito atribui obrigatoriamente, a cada
objecto do cenário, um volume envolvente. Estes volumes envolventes são todos
registados no registo de colisões e em cada momento são testadas as colisões entre
o jogador e os objectos do cenário. Repare-se que, por motivos optimização, foi
decidido que só seriam testadas as colisões entre o jogador e os objectos, uma vez
que o “preço a pagar” por testes entre todos os objectos, seria demasiado alto para
o retorno que isso traria ao nível da lógica de jogo.
Além dos volumes envolventes para cada objecto, existem outro tipo de
volumes. Estes são utilizados para criar uma detecção de colisões hierárquica, que
pode ter vários tipos de utilidades, entre elas, a possibilidade da diminuição de
cálculos de colisões ou a detecção de colisões com partes específicas de um
objecto, por exemplo com a cabeça de um modelo ou com um braço.
Este tipo de volumes, ao contrário dos volumes dos objectos, permite que o
jogador permaneça dentro do volume. Na realidade, só a partir do momento em
que um jogador está dentro de um destes volumes é que são testadas as colisões
com objectos. Deste modo diminui-se em muito o número de testes porque ao
invés de testar colisões com os objectos do nível todo, apenas são testadas colisões
com objectos do mesmo volume e portanto próximos do jogador.
Por fim resta salientar, que este sistema não tem um profundidade máxima, ou
seja, a colisão é testada recursivamente até se chegar ao volume que não contenha
outros volumes.
Na Figura 1, pode ver-se um exemplo. Existem no total seis volumes
envolventes e apenas três deles são de objectos. Neste exemplo, dada a localização
do jogador, só estão a ser testadas colisões entre o jogador e o Objecto1. Todos os
objectos fora da BB3 são ignorados.
Figura 1 – Exemplo de teste de colisões
Checkpoints - A solução para os problemas de framerate
A inclusão de modelos MD2 no jogo traz algumas facilidades na animação de
modelos, uma vez que além de existirem muitos recursos online já animados, o seu
carregamento e animação é também relativamente simples. No entanto, ao contrário
dos modelos mais complexos e actuais, a animação deste tipo de modelos faz-se por
interpolação dos vários keyframes, o que é computacionalmente muito exigente e não
pode ser trivialmente optimizado via display-lists, uma vez que o cálculo da posição
dos vértices depende da framerate do jogo.
Após a inclusão de todos os inimigos no cenário, a framerate do jogo desceu
consideravelmente, nos PCs com mais de 3/4 anos. Dada esta situação, foi necessário
criar métodos para minimizar os cálculos e optimizar ao máximo o jogo neste tipo de
máquinas. Começou-se então um processo progressivo de desenvolvimento de
metodologias, para diminuir o elevado número de operações por frame. Seguem-se os
dois métodos encontrados e implementados:
- Diminuição do cálculo de colisões: Com base na posição do jogador no nível, é
possível cortar vários elementos do registo de colisões, uma vez que não deverão ter
influência por se encontrarem, em planos que não são o do jogador. Estes planos
podem ser vistos como Volumes Envolventes e só os objectos que se encontrem no
mesmo volume que o jogador farão parte do teste de colisões. O funcionamento
concreto dos volumes encontra-se explicado na secção “Detecção de colisões” deste
mesmo capítulo.
- Diminuição do número de objectos desenhados: Baseado no mesmo princípio
que o ponto anterior, só deverá ser desenhado o que o jogador puder ver. Este método
oferece grandes melhorias a nível de performance, mesmo em computadores mais
antigos. Esta escolha do que se vai desenhar, é baseada em checkpoints, ou seja, um
jogador sempre que passa por um checkpoint, deverá conseguir, pelo menos, ver todos
os objectos abrangidos por essa área.
Quando esta abordagem é aplicada “à risca”, surge um problema, o jogador vai
reparar no desenho do que está à sua frente, quando passar por um checkpoint. A
solução utilizada, para resolver esta situação, foi a criar variações deste modelo,
conforme o tipo de máquina que está a correr o jogo. Assim existem três “profiles”
que determinam a quantidade de objectos desenhados:
- GAMER_PC_LOW_PROFILE : Apenas são desenhados os objectos do
checkpoint actual
- GAMER_PC_MEDIUM_PROFILE: São desenhados os objectos do checkpoint
actual e os do próximo checkpoint. Deste modo, quando o jogado passar o
checkpoint seguinte, não verá objectos a aparecerem do nada.
- GAMER_PC_HIGH_PROFILE: São desenhados os objectos do checkpoint
actual, do anterior e do próximo. Deste modo, o jogador nunca reparará que
existem objectos que não estão a ser desenhados, mesmo que percorra o nível no
sentido inverso.
Como seria de esperar, cada um destes modos tem implicações claramente visíveis ao
nível da performance. Estes profiles são escolhidos, com base na opção “PC
Specification” do menu de opções.
Por fim, resta explicar como se encaixam estes dois métodos. Estes métodos
conjugam-se de forma muito simples, na realidade, um checkpoint tem um volume
envolvente que representa toda a sua área de acção. Quando o jogador passa por um
checkpoint, esse volume envolvente é activado e adicionado à lista de objectos a ser
desenhados todos os objectos que estão dentro desse volume. Quando se está num
profile que não o “LOW”, desenham-se os objectos do(s) checkpoint(s) adjacentes,
mas não se calculam colisões com eles.
6. Post-Mortem
6.1. O que correu bem
Planeamento – O planeamento apresentado no inicio da execução foi um dos
aspectos que foi levado em conta até ao último dia, havendo alguns pontos que
foram deixados para trás, devido ao facto de se ter chegado à conclusão que já
não se aplicavam. Graças a esse rigor, foi possível, passo a passo, ganhar
algum tempo, face ao que estava no planeamento e no fim implementar
algumas das “features” que não estavam inicialmente previstas. Por exemplo,
a criação de um sistema que detecta o número de níveis criados e que
“estende” o jogo até não existirem mais níveis.
Gestão de risco – Mais uma vez o plano de contingência apresentado no início,
o que previa uma série de cortes, foi aplicado. Devido ao plano já estar
estabelecido previamente, foi mais fácil identificar os pontos em que
poderíamos cortar, uma vez que esse raciocínio foi feito previamente. Assim
na altura em que o tempo já parecia pouco, o facto de não ser necessário
pensar no que seria bom ou mau deixar para trás, poupou algum tempo.
Extensibilidade – Inicialmente não estava planeado a facilidade em inserir
novos níveis, na realidade estava apenas previsto a facilidade de configuração,
que apareceu via XML mas felizmente, devido a algum tempo extra, foi
possível criar o sistema que permite que exista um número arbitrário de níveis.
Claro que isso não dispensa a sua criação e configuração.
Escolha de modelos animados – Este ponto teve aspectos positivos e
negativos, tanto que aparece nos dois lados. O tipo de modelos escolhido,
como já foi referido, foi o do Quake2 (MD2). Este tipo de modelos permitiu a
existência de modelos animados de forma simples e uma vez que o jogo foi
tão popular em tempos, existem muitos recursos deste tipo. É de notar, que
provavelmente sem este tipo de modelos, nunca existiram modelos animados,
uma vez que os processos de animação alternativos são bastantes mais
complexos. Em vez disso, provavelmente existiriam animações bem mais
simples e não tão agradáveis visualmente.
Não inclusão de bibliotecas de física/colisões – Considera-se um aspecto
positivo a não inclusão deste tipo de bibliotecas porque assim a solução
implementada, além de se aproximar mais do que realmente é necessário,
permitiu perceber o funcionamento dos mecanismos de colisões existentes.
Além da flexibilidade fornecida por uma solução feita à medida, mesmo que
não tão precisa como as soluções profissionais existentes.
6.2. O que correu menos bem
Ideia inicial, para o combate por turnos – Inicialmente estava prevista a
criação de um sistema de combates, aplicável nos bosses, bem mais
aliciante do que o combate tradicional. Infelizmente e como já era de
esperar, não foi possível implementá-lo devido à sua complexidade.
Textura do mapa de alturas – A texturização do mapa de alturas foi um
assunto complexo, uma vez que existia a noção que, para uma correcta
texturização, deveriam ser aplicadas texturas pequenas, mas
repetidamente. No entanto, não se pretendia um padrão todo igual, e como
não foi possível criar um método que aplicasse diferentes texturas,
consoante a posição ou a altura, acabou por ser usada uma textura com
uma grande resolução, que ocupa imenso espaço na memória da placa
gráfica e que mesmo assim não é grande o suficiente para se tornar
minimamente agradável.
Escolha de modelos animados – Mais uma vez a escolha do tipo de
modelos animados, é uma “faca de dois gumes” e, portanto, a sua
simplicidade aparente ao nível da animação, traz grandes problemas de
performance. A forma de ultrapassar já foi explicada neste documento,
mas passou por desenhar apenas os modelos realmente necessários.
Testes com bibliotecas de detecção de colisões – Quando surgiu a
necessidade de existirem colisões, começou-se por pesquisar e tentar
utilizar algumas bibliotecas para o efeito. No entanto, uma vez que houve
alguma dificuldade em colocá-las a funcionar junto do projecto, desistiu-se
e implementou-se “à mão”.
Turrets – A concretização do conceito das armas fixas integradas num
jogo de plataformas acabou por não satisfazer as expectativas existentes
para esta funcionalidade, devido à sua simplicidade e à dificuldade de
especificação num ambiente totalmente descrito por XML. Embora
existissem outras possibilidades para o fazer dessa forma, as limitações de
tempo não permitiram reflectir muito sobre esse assunto.
Bugs, Bugs e mais Bugs – Como em todo o software, este jogo não está
isento de bugs. Alguns dos mais comuns prendem-se com:
- FrameRate e as falhas na detecção de colisões – Uma das
consequências imediatas da quebra de fluidez do jogo é o atraso da
detecção de colisões. FrameRates abaixo das 20/25 farão com que não
se detectem algumas colisões, podendo arruinar a experiência de jogo.
- Checkpoints – Este é um bug muito incómudo, mas que acabou por
não ser resolvido, porque só ocorre se o jogador parar em cima de um
checkpoint( não visível) e voltar para trás. Isto faz com que não sejam
carregados os volumes envolventes do checkpoint anterior. Isto porque
ao pisar o checkpoint são carregados os volumes envolventes da área
seguinte, no entanto se parar em cima do checkpoint e voltar para trás,
ele não consegue detectar essa inversão de sentido o que faz com que
não sejam carregados. Para isto não acontecer, é preciso que o volume
que envolve jogador, ultrapasse na totalidade o checkpoint e só assim
pode voltar para trás.
- Animações Presas – Por vezes a animação bloqueia ou então fica
sempre na mesma.
- Menu sem letras – Existe o risco do menu aparecer sem texto.
Todos estes bugs e outros que não estejam descritos são, na maioria das vezes,
resolvidos com o reiniciar do jogo ou do nível, consoante a situação.
Gestão de memória – Uma vez que não houve tempo, existem algumas
situações em que a memória é alocada e não é libertada. O principal factor
é a libertação dos recursos alocados pelo resource manager. Isto faz com
que, quando se reinicia um jogo ou se passa para um nível diferente, sejam
alocados recursos sem libertar os que foram anteriormente alocados,
fazendo com que a memória consumida pelo jogo aumente
consideravelmente. Embora identificado o problema, o deleteImages da
DeviL aparentemente não está a sortir efeito, não foi possível resolvê-lo
até à entrega final.
7. Impressões Finais e Conclusões
Começando pelo início, devido à nossa inexperiência, começamos logo por
nos preocupar com o carregamento de modelos. Na realidade nem existia a noção de
como isso era feito no OpenGL e portanto quando nos apercebemos que essa tarefa
não era trivial, principalmente em modelos animados, ficamos um pouco assustados.
Após esse primeiro choque e em conversa com o professor das práticas,
rapidamente chegamos à conclusão de que o mais importante seria desenvolver a
lógica de jogo e o necessário para que esta se concretizasse.
A partir desse momento, começamos por criar os dois grandes pilares onde
assentam a jogabilidade, a detecção de colisões e movimento do jogador no terreno.
Agora que tudo terminou, podemos afirmar que estes dois pilares, embora sejam
desenvolvidos na íntegra por nós, e apesar da nossa inexperiência, os resultados finais
são bastante satisfatórios, pelo menos para nós são surpreendentes, principalmente
quando por muitas vezes demos alguns aspectos menos conseguidos como certos.
Embora não fosse tão valorizado e seja um aspecto meramente estético, a
animação dos inimigos e do jogador, tornam o jogo bastante engraçado. A animação
dos inimigos foi a última a ser introduzida e para nós que convivemos muito tempo
com os modelos estáticos, assim que os animamos, o jogo ganhou outra vida,
chegando a dar a impressão de que os inimigos têm alguma inteligência, embora todo
o movimento de ataque seja um script bastante rudimentar.
Quanto ao nosso julgamento final sobre o nosso jogo, julgamos ter realizado
um trabalho muito acima das nossas expectativas iniciais, tendo em conta que não
tínhamos qualquer experiência em jogos, e em openGL muito pouca, podendo
considerar-se inexistente. A investigação realizada para desenvolver as tecnologias e a
criatividade exigida para criar a jogabilidade e ultrapassar alguns dos problema que
tivemos, permitiram-nos obter um nível de experiência aceitável e com certeza que no
inicio do próximo projecto deste género, teremos uma abordagem completamente
diferente, não voltando a cometer os mesmo erros e tendo noção do que é necessário
para fazer um jogo.
Sem dúvida que existem alguns bugs, defeitos ou más implementações mas
embora o jogo não seja muito interessante, conseguiu-se mesmo assim criar algo que
até pode ser divertido esquecendo os bugs que podem afectar esta experiência.
Referências
[1] http://www.bundysoft.com/L3DT/
[2] http://www.planetside.co.uk/terragen/
[3] http://www.videotutorialsrock.com/opengl_tutorial/animation/text.php
[4] http://www.freetype.org/
[5] http://devernay.free.fr/hacks/glm/
[6] http://openil.sourceforge.net/
[7] http://www.applied-mathematics.net/tools/xmlParser.html
[8] http://polimath.com/blog/code/glft_font/