Trabalho de Formatura
Supervisionado
Supervisor:
Prof.
Marcos Dimas Gubitoso
Aluno:
Fernando
Kasten Peinado
No.
USP 3104092
BCC
1999
1. Introdução
e elaboração da idéia
2. Modelagem
e definições adotadas
a. Modelagem
do tabuleiro hexagonal
e. Persistencia
e Seriação de objetos
3. Descrição
dos principais algoritmos
a. Distância
entre dois hexagonos
5. Ferramentas
construidas / a construir
a. Desenvolvimento
do tabuleiro hexagonal
b. Pouco
conhecimento de OO no início do projeto
c. Pouco
conhecimento de C++ no início do projeto
d. Falta de
um melhor planejamento e objetivos
7. Experiências
e Integração com o curso
a. Importância
de Engenharia de Software
b. Aprendizado
em OO, C++ e JAVA
d. Redes de
comunicação TCP/IP
1. Introdução e
elaboração da idéia
Um dos grandes sonhos de todo programador, que sempre se divertiu com jogos eletrônicos, é um dia fazer o seu próprio jogo. Mas por que um jogo? Porque esse processo propicia uma satisfação dupla ao desenvolvedor, já que o fato de ser um software complexo e desafiador estimula o lado programador, e se o resultado é um jogo interessante, estimula o lado jogador. Este por sua vez pede melhorias em seu jogo, e o programador volta a cena. É um processo contínuo e divertido, e uma grande fonte de aprendizado.
Arena é um jogo de estratégia multiplayer baseado em regras de RPG. Não posso dizer que esta seja uma idéia original, pois este jogo não começou a ser desenvolvido com este objetivo, mas posso dizer que suas características são especiais. Meu objetivo é construir um campo de batalhas em que as peças são personagens de RPG, capazes de evoluir e se equipar ao longo de sua história.
Qualquer jogador, hoje em dia, sabe que os jogos multiplayer estão cada vez mais dominando este mercado da diversão eletrônica. Jogar sozinho não tem mais graça, pois o computador é uma máquina que passa a ser previsível quando nos acostumamos a ela. Jogos multiplayer acabam com essa previsibilidade na medida em que colocam dois ou mais jogadores humanos frente a frente, como nos jogos convencionais, porém com a possibilidade de reproduzir no computador qualquer mundo ou ambiente que a imaginação possa criar.
Estratégia e RPG são dois diferentes estilos de jogos, mas que se combinados produzem resultados muito interessantes. Muitos podem dizer que não gostam desses tipos de jogos, mas qual jogador nunca jogou um desses jogos: “Monkey Island”, “Maniac Mansion”, “The Hitch Hiker’s Guide to the Galaxy”, “GURPS”, “D&D”, que são jogos que pertencem ao estilo RPG, e outros famosos como “CIVILIZATION”, “WAR”, e até mesmo o bom e velho xadrês, que pertencem ao estilo estratégia.
a.
Modelagem do
tabuleiro hexagonal
O uso de um tabuleiro hexagonal é algo comum em jogos de RPG. Ele permite uma grande flexibilidade, trazendo o jogo mais próximo da realidade, que é um dos objetivos desse tipo de jogo. Este também é fundamental para um jogo de estratégia, já que define uma das ações mais importantes nesse tipo de jogo que é o deslocamento das peças.
A grande dificuldade de se usar este tipo de estrutura é representá-la de maneira eficiente, de modo que seja possível manejá-la facilmente. Para isso foi necessário então estudar melhor esta estrutura, e as seguintes idéias foram adotadas:
|
COORDENADAS
HEXAGONAIS
Os hexágonos no tabuleiro são
identificados seguindo o padrão mostrado na figura. Este padrão permite uma
identificação eficiente da posição de cada hexágono no plano, e é facilmente
mapeada para uma estrutura de armazenamento e para a tela. Esta numeração é baseada nos eixos (x
, y), com o eixo x crescente para direita e o eixo y
crescente para baixo. Importante observação: os hexágonos
possuem os valores x e y com a mesma paridade. |
|
A
orientação do tabuleiro segue a figura: 0
para cima, 3 para baixo, 1, 2, 4 e 5 para as diagonais. Os deslocamentos correspondentes são: 0:
(+0 , -2) 1:
(+1 , -1) 2:
(+1 , +1) 3:
(+0 , +2) 4:
(-1 , +1) 5:
(-1 , -1) |
Para armazenarmos de forma eficiente o tabuleiro
usamos uma matriz simples, seguindo a transformação de coordenadas hexagonais
para coordenadas de matriz:
Matriz <= Hexágono |
Hexágono <= Matriz |
X_matriz =
x_hexágono |
x_hexágono =
x_matriz |
y_matriz = ëy_hexágono / 2û |
y_hexágono =
(y_matriz * 2) + x_matriz mod 2 |
Uma vez definida a estrutura capaz de representar do tabuleiro como um conjunto de hexágonos, foi então necessário definir a estrutura de um hexágono, dos tipos possíveis de hexágonos e da estrutura real de armazenamento desse conjunto de unidades que formam o tabuleiro. Essas outras estruturas são importantes, por exemplo, quando queremos desehar os hexágonos na tela, ou seja como desenha-lo. A aparência do tabuleiro é dada por um conjundo de imagens que são colocadas lado-a-lado, o que é chamado de “Tiled-map”.
[ ver classes em src/table ]
As unidades, ou personagens, são o ponto central de qualquer jogo de RPG. Normalmente são entidades complexas, subdivididas em classes de personagens, que possuem diversas habilidades diferentes. Essa estrutura deve ser flexível para permitir as diversas possibilidades de personagens, e que este evolua ao longo do jogo através de pontos de experiência obtidos ao longo de suas batalhas. Esta evolução deve permitir ao jogador escolher que caminho seguir. (Não implementada completamente)
Para se flexibilizar os personagem foi criada uma estrutura capaz de representar suas ações, de modo que diferentes tipos (classes) de personagens pudessem ter um grupo de ações específicas.
[ ver classes em src/units ]
Ações de personagens resumem a funcionalidade e a capacidade de um personagem atuar dentro do jogo. Estas ações podem ser básicas, ou seja, comuns a qualquer personagem, tais como andar, virar, atacar, pegar e largar objetos, ou complexas como lançar feitiços e magias (não implementadas ainda), que são ações especificas da classe dos magos.
Além disso, essas ações são a base distribuição do jogo através da rede, já que sua estrutura fornece, para cada ação realizada, um descritor capaz de reproduzir a ação a partir da situação existente anteriormente. Com isso uma ação realizada em um dos pontos da rede é reproduzida nos demais pontos, e com isso mantemos a consistência de estado dos personagens no jogo.
[ ver classes em src/actions ]
O Protocolo de rede é simples, baseado em TCP/IP para garantir o envio e o recebimento das mensagens, trabalha com um simples broadcast de mensagens na maior parte do tempo. Através de um servidor central, necessariamente criado por um dos jogadores, o jogo é gerenciado. Durante uma partida, grande parte das mensagens que trafegam pela rede são descritores de ações, como explicados anteriormente, capazes de reproduzí-las. Caso contrário são mensagens denominadas de ações de servidor. Essas são iniciadas pelo caractere ‘#’ e possuem um código que define a ação. O servidor interpreta e devolve uma resposta, se necessário, somente ao jogador que a invocou. Esta é muito utilizada na inicialização do jogo, e em algumas decisões que são tomadas pelo servidor.
Um fator de grande importancia neste protocolo são os objetos seriáveis. Estes permitem que sejam transportados de um ponto a outro na rede em forma de texto simples, e que sejam reconstruidos posteriormente. Esta seriação é melhor explicada abaixo.
[ ver classes em src/network ]
e.
Persistencia e
Seriação de objetos
Muitos dos objetos existentes no Arena necessitavam de alguma forma de persistência. Unidades precisavam ser persistidas quando uma partida acabava, pois gostariamos de poder usar o mesmo personagem em uma próxima jogada. Um tabuleiro também deveria ser persistido em um arquivo, para que pudessemos carregá-lo. Para isso um foi necessário a criação de um esquema de seriação simples dos objetos em C++, já que este método não é nativo como em JAVA. Para evitar grandes complicações, cada objeto em particular é responsável por si próprio, ou seja, se escreve e se carrega de um arquivo texto simples. A estrutura desse arquivo é, atualmente, definida por cada objeto, permitindo que cada um se utlize dos recursos necessários da melhor forma possível.
Futuramente esta persistência sofrerá transformações de modo que seja possível realizar algum tipo de criptografia sobre os dados, para que não existam trapaças. Deverá também assumir algum padrão a ser adotado, para torná-la genérica o suficiente de modo que todas os objetos utilizem o mesmo formato de arquivo.
Esta seriação de objetos também tornou-se conveniente no processo de transmissão dos dados através da rede, já que unidades, tabuleiro, equipamentos, entre outros precisavam ser replicados em todas as máquinas participantes de uma partida.
a.
Distância entre
dois hexagonos
Aparentemente simples, o cálculo da distância entre dois hexágonos é
fortemente dependente da estrutura adotada, e extremamente importante no
desenvolvimento dos próximos algoritmos. Também é importante quando é
necessário saber simplesmente a distância real entre duas unidades, por exemplo
na realização de um ataque, para decidir se é ou não possível atacar com uma
determidada arma, e decidir a dificuldade que ele terá para acertar o inimigo.
Este algoritmo e a distância são a base para quase todos os cálculos feitos sobre o tabuleiro hexagonal. Consiste basicamente em descobrir todos os hexágonos que contém um pedaço do segmento de reta que une dois hexágonos dados.
Muitas tentativas para resolver este problema foram fracassadas e serão relatadas posteriormente, mas com a ajuda de um colega: Danilo Eiji Seki, chegamos a um algoritmo simples e bastante eficiente para este problema.
O algoritmo é usado basicamente para calcular obstáculos entre um atacante e um defensor, quando nos referimos a ataques de longa distância entre outros como o algoritmo de visão.
Trata-se de um algoritmo para resolver o campo de visão de cada unidade em particular. Essa visão se baseia em um raio, e é modificada pelos obstáculos presentes no mapa. Cada obstáculo possui um valor de bloqueio que define o quanto ele interfere no campo de visão.
Este é um dos responsáveis por tornar o jogo mais interessante, já que
com um campo de visão limitado é possível planejar emboscadas.
Allegro foi a biblioteca gráfica escolhida para o desenvolvimento do Arena. Atualmente na versão 4.0.x, a Allegro é uma biblioteca que surgiu inicialmente com grandioso videogame Atari. Além de oferecer estruturas de manipulação gráfica, som, teclado, mouse, joystick e tudo mais que um jogo pode precisar, ainda oferece uma grande comunidade de desenvolvedores e usuários, o que faz com que aplicativos de suporte e todo tipo de informação e ajuda estejam amplamente divulgados pela rede.
Oferece também suporte aos pricipais sistemas operacionais como: MSDOS,
Windows 3.1 or earlier, Windows 95, Windows 98, Windows ME, Windows NT, Windows
2000, Windows XP, OS/2, OS/2 Warp 3, Linux DOSEMU, Caldera OpenDOS, Linux, FreeBSD,
Unix, BeOS, QNX e MacOS.
Libnet é uma biblioteca de rede simples, desenvolvida com o objetivo de
fornecer este recurso aos programadores de jogos. Permite basicamente o uso de
dois protocolos: UDP e TCP/IP. Não oferece recursos avançados para controlar as
conexões, porém também possui suporte a vários sistemas operaconais.
Principal linguagem da programação de jogos, oferece a robustez e a
eficiência da linguagem C, e a organização e demais vantagens de uma linguagem
orientada a objetos.
DevCpp é uma interface IDE para desenvolvimento da linguagem C++ para o ambiente windows, agregado ao compilador GCC. Foi de fundamental importância nesse processo de desenvolvimento.
Personagens são o centro do jogo, e suas diferenças fazem com que o jogo seja mais divertido e mais pessoal em relação ao jogador que a utiliza. Por isso era necessaria alguma ferramenta capaz de trazer esta individualidade, ou seja capaz de construir novos personagens para serem utilizados no jogo.
Esta ferramenta deve limitar as possibilidades da criação, pois um jogador com uma super personagem venceria facilmente outro com personagens normais. Para isso novamente nos utilizamos de regras de RPG para criar um personagem equilibrado, a partir de pontos que podem ser gastos com melhorias nas habilidades de um personagem básico.
O tabuleiro em um jogo de estratégia tem a função de representar o ambiente onde o jogo se desenvolve. Em alguns jogos estes tabuleiros representam mais que uma simples estrutura, que limita as ações dos jogadores, mas sim tentam reproduzir regiões geográficas, e por isso são também chamados de mapas.
Um jogo que apresenta apenas um tabuleiro, ou alguns poucos mapas
apenas pode se tornar cansativo. Uma das maneiras consagradas de se evitar este
tipo de problema é a construção de uma ferramenta capaz de ser utilizada por
qualquer jogador, que permita a construção de novos mapas, e esses podem ser
distribuidos para outros jogadores.
Assim como as demais ferramentas acima, um editor de equipamentos
traria maior flexibilidade ao jogo, permitindo sua evolução indenpendente de
alterações em código. Os equipamentos são todas as armas, armaduras e
ferramentas que um personagem pode usar no jogo. Estas estão divididas em
grupos, que possuem características semelhantes de uso, porém algumas dessas
são potencialmente configuráveis de maneira independente ao código. Essas
configurações independentes consistem no construtor de equipamentos.
a.
Desenvolvimento
do tabuleiro hexagonal
No princípio do desenvolvimento do Arena, uma das primeiras decisões tomadas foi o uso do tabuleiro hexagonal. Porém com esse objetivo comecei, com a ajuda de alguns colegas, a tentar definir uma maneira de criar uma representação para este tabuleiro e definir seus principais algoritmos. Muitas tentativas sem sucesso foram feitas, e isso atrasou o inicio do projeto em quase seis meses. Após este periodo, decidi então deixar este problema um pouco de lado, e baseando me em um tabuleiro convencional (quadrado), comecei a desenvolver as outras partes do jogo. Graças a ajuda de um colega em especial, Danilo Eiji Seki, que interessado no problema, se dedicou e chegou a uma estrutura e aos dois algoritmos básicos que eram necessários: distância e traço. Após este fato o jogo passou a ser desenvolvido da maneira desjada.
Para chegar ao resultado desejado tinhamos que enfrentar 3 problemas básicos: chegar a uma estrutura compacta de representação do tabuleiro, pois o mapeamento simples para uma matriz disperdiçava grandes quantidades de espaço; usando a estrutura escolhida definir uma forma de representá-la graficamente; construir dois algoritmos básicos que forncessem a distância entre dois hexágonos e todos os hexágonos contivessem o segmento de reta que une dois hexágonos quaisquer (algoritmo de traço).
Uma idéia era usar uma estrutura verdadeiramente geométrica, ou seja os hexágonos teriam coordenadas geométricas e os algoritmos seria implementados através de geometria analítica. A idéia não vingou devido a problemas de precisão, tanto em relação aos algoritmos quanto em relação à representação gráfica.
Então decidimos que ela deveria ser baseada em coordenadas inteiras simples, e que os algoritmos deveriam trabalhar de maneira discreta e não contínua como no caso anterior. Dessa maneira conseguimos algoritmos estremamente eficientes e bastante precisos.
Com esses dois algoritmos, foi possível implementar os de visão (define a área de visão de uma unidade), linha de tiro, e área de hexágonos (um hexágono central e os adjacentes até uma distância r).
b.
Pouco
conhecimento de OO no início do projeto
Um dos objetivos pessoais ao iniciar o projeto deste jogo era buscar um conhecimento em Orientação a Objetos, que eu não tinha por completo. O fato de aprender com um projeto é bastante interessante do ponto de vista do aprendizado em si, porém, no projeto, os impactos dessa falta de experiência são grandes. Conforme evoluímos somos capazes de identificar problemas, e então quase sempre refatoramos ou até mesmo reconstruimos boa parte código já existente. Com isso, a produção torna-se lenta e desgastante.
c.
Pouco
conhecimento de C++ no início do projeto
Ao buscar o conhecimento em OO descrito acima, decidi aprender a linguagem C++, com a qual nunca tinha entrado em contato antes. Esta foi outra barreira a um desenvolvimento produtivo no início do projeto. O pouquissimo conhecimento vinha da linguagem C, e do contanto com pessoas que conheciam melhor as idéias de OO.
d.
Falta de um
melhor planejamento e objetivos
Outra importante barreira ao desenvolvimento produtivo foi a falta de
planejamento, e de objetivos no inicio do projeto. Pelo fato deste ter começado
devido a um projeto pessoal, e a uma busca de conhecimento, o objetivo inicial
era muito vago: aprender, e se possível,
ainda ter um jogo no final.
a.
Importância de
Engenharia de Software
Muitos de nós despresamos a importância de praticar a Engenharia de Software de maneira correta. Talvez porque a falta de experiências profissionais reais, que são desincentivadas ao longo do curso, nos priva do mundo real. Quando nos involvemos profissionalmente em um grande projeto, onde os limites e os conceitos foram pouco trabalhados durante a fase de engenharia, percebemos há uma grande dificuldade de se produzir um software de boa qualidade.
Apesar deste projeto não se encaixar propriamente neste cenário, posso dizer que sofri dos mesmos problemas. Porém, acabei descobrindo isso um pouco tarde, e hoje vejo que deveria ter dado muito mais atenção a um curso, que parecia falar de coisas óbvias em um desenvolvimento de software. Hoje vejo que as coisas óbvias nem sempre são seguidas.
b.
Aprendizado em
OO, C++ e JAVA
O aprendizado de tecnologias não é um dos pontos centrais ao longo do nosso curso, porém somos bastante estimulados a aprendermos sozinhos. Vejo este projeto como fruto desse incentivo, pois nele fui desafiado a aprender diversas tecnologias que não conhecia. Este foi um fator extremamente importante em um processo de auto afirmação, que me mostrou que o curso realmente me preparou, e que sou capaz de aprender novas coisas com grande facilidade.
Com esse projeto pude aprender muito mais sobre Orientação a Objetos, seus beneficios e suas limitações, e principalmente o aprendizado das tecnologias C++ e JAVA, que são de extrema importância hoje em dia.
Apesar de não ter feito o curso de computação gráfica oferecido pelo instituto sempre estive em contato com o assunto, e pude extrair um conhecimento valioso do seu material.
Sempre tive a curiosidade de saber como jogos antigos funcionavam, como eram possíveis aquelas interfaces gráficas que me faziam viajar em diferentes mundos. Esses conhecimentos quebraram boa parte do encanto desses jogos, porém introduziram o respeito à grande habilidade dos programadores.
d.
Redes de
comunicação TCP/IP
Até então as redes eram algo místico, capazes de comunicar computadores
de uma forma um pouco mágica. Mas assim que começamos a estudá-las e analisar
como são construidas percebemos exatamente as suas capacidades e limitações.
Durante o curso tive contato com diversas matérias que me levaram a analisar as
redes de um ponto de vista mais alto nível, tais como construir sistemas
distribuidos ou otimizar sistemas em paralelo, porém o conhecimento básico
sobre redes eu obtive de maneira individual, pois não fiz o curso de redes.
Apesar disso fui capaz de aprender facilmente os seus princípios, e de
desenvolver em cima deles.
Devo agradecer aos meus colegas pela força e pelo insentivo, não apenas no desenvolvimento deste projeto, mas sim no decorrer de todo curso.
Danilo
Eiji Seki |
que me ajudou no desenvolvimento da idéia e nos principais algoritmos relacionados ao tabuleiro hexagonal |
Professor
Marcos Dimas Gubitoso |
meu orientandor no desenvolvimento deste projeto |