2007-11-21 - Odisséia do Desenvolvimento de Jogos

21 de novembro

Odisséia do Desenvolvimento de Jogos

Odisséia do Desenvolvimento de Jogos
====================================
Olá, meu nome é Glaudiston, atualmente sou um desenvolvedor IBM, mas sempre que sobra algum tempo
tento desenvolver alguma coisa voltada à jogos e realidade virtual.

Vou tentar manter este documento atualizado como um manual para os que estiverem interessados
em desenvolvimento de jogos, e também para minha própria referência, afinal compartilhar
é a melhor forma de não errar denovo. =)

Por onde começar
================
Primeiro decidi que queria fazer jogos, e pagaria o preço por isto, então comecei a pesquisar...
De início pensei que daria conta facilmente, afinal me achava muito inteligente,
mas descobri que não é bem assim... é necessário muita dedicação, perseverança e ajuda.
Este é quase um passo a passo, mas se você não está disposto a passar horas intermináveis
quebrando a cabeça com detalhes, pode parar de ler, você ainda não está pronto.

O que é necessário saber/ter para desenvolver jogos
===================================================
Tudo pode ser conseguido sem custo na internet, mas o aprendizado é penoso.
Para criar um jogo você precisa de:
* Escrever a Lógica do seu jogo,
* Escolher uma Linguagem,
* Escolher a API(rotinas prontas),
* interface(janelas, resolução, tela cheia, cores)
* Entrada(Joysticks, Mouse, teclado)
* conexão(TCP/IP, multiplayer)
* audio(musicas, sons, mp3)
* Detecção de colisão
* Gerenciamento de gráficos 3D
* Configurar o ambiente(talvez a parte mais difícil),
* Fazer download certos de cada opção escolhida
* Instalar e configurar corretamente
* Aprender a compilar cada opção necessária no jogo

Escrever a Lógica do seu jogo
=============================
Você tem uma idéia do que quer que seu jogo faça, talvez até saiba de cór tudo,
mas acredite, precisa colocar isto por escrito.
Isto te dá um ponto de partida... e evita que você se perca em seus objetivos.
Existem diagramas UML e uma estrutura muito grande que pode te confundir se
vc se aprofundar nesta parte... Jogos grandes são escritos por times e tem profissionais
por conta de ficar criando documentações para serem implementados por outros...
isto é muito bom, mas não é o caso, pelo menos não o meu.

Não tente criar "O JOGO" de primeira
====================================
Primeiro porque para ser introduzido ao desenvolvimento de jogos é necessário ser humilde.
Isto mesmo, comece de baixo... crie jogos 2D simples para aprender lógica e conseguir
continuar motivado, sabendo que já conseguiu fazer alguma coisa.
Sem falar que criando estes joginhos 2D vc acaba tendo muitas idéias de como usá-los
dentro do seu jogo, então de certa forma, você já está trabalhando "NO JOGO".

Se tentar criar um jogo fantástico de primeira, vai esbarrar em muitas barreiras que já
deveria ter superado quando criava joguinhos pequenos e relativamente simples, e como
não conseguiu fazer nenhum jogo antes, pode chegar à falsa conclusão que não é capaz disto.

Lembre-se: "Motivação é Essencial."

Eu já tentei criar uma engine completa para um mundo virtual melhor que o secondlife...
na verdade pegando as melhores opções de jogabilidade dele mesclando um idéias do GTA e
the sims... nfsu2... etc... com certeza a engine para o Jogo de meus sonhos...
O resultado é que chegou em um ponto que não consegui mais passar... então desisti por
um bom tempo... ainda tenho o código, algum dia conseguirei retomá-lo.
Fique tão triste por não conseguir que voltei apenas a jogar e admirar os programadores
que conseguem criar tais jogos... quase venerando os desenvolvedores da EA Games dentre
outras empresas que fazem coisas fantástica escovando bits.
Mas depois de continuar na programação comercial por muito tempo e com mais maturidade,
voltei a sonhar... Afinal se cheguei na IBM, porque não posso chegar na EA ?
Mas desta vez pretendo começar realmente do zero, como tem que ser para um novato em jogos.
Vou relatar tudo para entender onde estou errando, ajudar os outros será conseguência.

Hoje tenho uma lógica mais aprofundada e entendo melhor a necessidade de documentar o que
deve ser feito antes de começar o código em sí.

Aí você diz: "Mas eu não quero fazer joguinhos... quero fazer jogos 3D!!!"
Eu sei... nem eu... a pesar de que existem muitos joguinhos 2D bem melhores q 3D, estou
fazendo isto pra aprender e conseguir chegar ao final do desenvolvimento de um jogo 3D.
E Nem sempre fazemos oque queremos.

Certo, já entendi que devo criar jogos básicos, e conseguir concluí-los antes de passar
ao jogo que realmente quero concluir.

Jogos que podemos criar para treinar lógica
===========================================
Campo Minado,
Paciência,
Pong,
Tetris,
Tiro ao alvo,
Invaders,
pac-man,
Damas,

Lógica do nosso primeiro jogo: Campo minado
===========================================
Descrição:
Campo minado é um jogo muito simples de cálculos matemáticos, e muito divertido também.
Funcionamento:
O jogador inicia o jogo e aparece para ele uma espécie de tabuleiro de botões,
e uma quantidade de bombas escondidas em alguns botões,
se o jogador clica em um botão que tem uma bomba, ele perde o jogo,
se clica em um botão que não tem bomba, mas está próximo(faz fronteira) com uma
ou mais bombas, aparece o nr de bombas que existem nas proximidades, esta é a única
pista que o jogador tem para descobrir quais quadrados têm bomba e quais não têm,
e se não tem bombas nas proximidades, o jogo automaticamente abre as fonteiras até
não encontrar mais fonteiras sem números.

Opções e comportamento do jogo:
Ao Abrir o jogo o usuário tem as opções:
Novo jogo
Ao clicar em novo jogo, as opções são:
Novo jogo
* Monta novamente um novo jogo pro usuário
Esta montagem é feita criando os botões visíveis ao jogador, e espalhando
as bombas aleatoriamente nestes de maneira oculta ao jogador.
* Zera o cronômetro
* Aguarda o primeiro clique do jogador
Sair do Jogo
Fecha o programa
----------------
Clicar em um botão(fazer uma nova jogada)
* No primeiro clique o cronômetro é disparado e o jogo começa.
* Se o jogador clicou em quadrado com uma bomba o jogo termina, ele perdeu +(
* Se o jogador clicou em quadrado sem bomba, e não existe bomba de fronteira com este
quadrado, o quadrado é aberto, e outros quadrados de fronteira são abertos
recursivamente até esgotarem-se os quadrados que não tem bombas nas fronteiras
* Se o jogador clicou em um quadrado sem bomba, mas que tem bomba em um dos quadrados
de fronteira, imprime no quadrado clicado, o nr de bombas que existe nas fonteiras
* Se não restam mais quadrados sem bombas, o jogo termina, ele venceu. =D
Ao vencer são guardados os dados nas estatísticas.
Estatísticas
Ao Clicar em Estatísticas o jogo mostra uma lista em ordem de maior dificuldade e menor tempo
com os dados:
Nome jogador, Data, Tempo gasto, dificuldade

Podemos definir a dificuldade como a possibilidade de erro em um chute,
por exemplo, se ele tiver 30 bombas em um tabuleiro de 200 quadrados,
dizemos q a dificuldade era (30/200)*100 = 15
então nossa fórmula será (bombas/quadrados)*100
Opções
Permite ao usuário definir a quantidade de bombas e o tamanho do tabuleiro
Sair do jogo
Fecha o programa

Analisando possíveis problemas
==============================
Lendo atentamente este comportamento do jogo notei as seguintes dificuldades:
Como gerenciar todos os itens e bombas em memória?
Penso que a melhor opção seria trabalhar com arrays... pra quem não conhece,
são como matrizes da matemática, todos já vimos isto na escola se não me engano no fim do ensino fundamental.
ficaria algo como isto:
int linsize=10; // Numero de colunas
int colsize=10; // Numero de linhas
int campo[linsize][colsize]; //
int bombas=10; // As bombas não são arrays então posso colocar o valor certo
após a rotina distribuir as 10 bombas randomizadas... ficaria algo como:
campo[0] = {0,0,0,0,0,0,1,0,0,0};
campo[1] = {0,0,1,0,0,0,0,0,0,0};
campo[2] = {0,0,0,0,0,0,0,0,0,0};
campo[3] = {0,0,0,1,0,1,0,0,0,0};
campo[4] = {0,0,1,0,0,0,0,0,0,0};
campo[5] = {0,1,0,0,0,0,1,0,1,0};
campo[6] = {0,0,0,0,0,0,0,0,0,0};
campo[7] = {0,0,0,1,0,0,0,0,0,0};
campo[8] = {0,0,0,0,0,0,0,0,0,0};
campo[9] = {0,0,0,0,0,0,1,0,0,0};
Os zeros são onde não existem bombas e os 1 são onde existem...
Observe que existem apenas dez "1" espalhados no array que é nosso tabuleiro
Porém em C não é possível definir um array por variáveis... é possível em java e outras linguagens mais
alto-nivel q C... Isto complica um pouco... sem isto não poderíamos permitir ao jogador definir o tamanho.
No máximo conseguiríamos predefinir niveis pra ele.
Uma boa saída é o malloc e trabalhar com ponteiros... vamos ver:

campo = malloc(linhas*colunas * sizeof(int));


Mas como espalhar as bombas?
Isto é bem simples dependendo da linguagem, na maioria tem algo como rnd ou randomize
que nos permite fazer isto com muita facilidade.
Mas não é o caso de C, onde a handomização é feita sempre na mesma sequência, o q deixaria nosso
jogo no mínimo previsível.
Neste caso da C, pensei em gerar a randomização baseada na data, hora completa incluindo os
milisegundos... e me veio outro problema, por padrão não é possível pegar os milisegundos no C,
não no ANSI C... e como gosto de seguir padrões de portabilidade, encontrei uma boa saída...
o SDL possui uma forma de calcular o framerate que disponibiliza uma variável atualizada em
milisegundos.... o SDL_GetTicks()... vamos trabalhar com ela para gerar a randomização.

Primeiro faça simples, depois complique gradativamente
Vamos primeiro fazer um código que permita o usuário acessar os menus em modo texto mesmo...
Assim você vai aprender a base do C


Iniciar um novo Jogo
Sair
Campo minado lógica:
define tamano de campo como 10 linhas e 10 colunas num total de 100 quadrantes.
int linsize=9;
int colsize=9;
campo[linsize][colsize] //O array começa do zero, sendo assim, se usar 10 vai gerar um array de 11 posições, por isto usamos o array de 9
usuário iniciou um novo jogo.
rotina distribui 10 bombas randomizadas... algo como:
campo[0][0,0,0,0,0,0,1,0,0,0]
campo[1][0,0,1,0,0,0,0,0,0,0]
campo[2][0,0,0,0,0,0,0,0,0,0]
campo[3][0,0,0,1,0,1,0,0,0,0]
campo[4][0,0,1,0,0,0,0,0,0,0]
campo[5][0,1,0,0,0,0,1,0,1,0]
campo[6][0,0,0,0,0,0,0,0,0,0]
campo[7][0,0,0,1,0,0,0,0,0,0]
campo[8][0,0,0,0,0,0,0,0,0,0]
campo[9][0,0,0,0,0,0,1,0,0,0]

Totaliza os quadrantes livres:
int quadranteslivres = 0;
for (int i=0; i<=linsize; i++)
{
for(int j=0; j<=colsize; j++)
{
if (campo[i,j]==0)
quadranteslivres += campo
}
}

usuáro seleciona um item:
linhasel=3;
colsel=2;
caso campo[linhasel,colsel]==1
tem bomba, explode, game over.
revelabombas();
caso campo[linhasel,colsel]==0
// Rotina calcula quantidade de bombas próximas:
int bombasproximas = 0;
for (int i=-1; i<2; i++)
{
if (linhasel+i>=0 && linhasel+i<linsize)
{
for(int j=-1; j<2; j++)
{
if (colsel+j>=0 && colsel<colsize)
bombasproximas += campo[linhasel+i, colsel+j];
}
}
}
caso itensproximos==0
não tem bombas na fronteira, rotina abre todos os ítens próximos recursivamente até esgotar itens de fronteira sem bombas próximas.
caso itensproximos > 0
Apenas relata ao usuário a quantidade de bombas nas proximidades.

// incrementa quadrantesabertos
quadrantesabertos++;
Verifica se existe mais algum quadrante livre,
if (quadranteslivres-quadrantesabertos>0)
caso exista o relata ao usuário.
e aguarda a próxima jogada.
else
caso não exista o usuário ganhou o jogo. Parabéns pra ele =)
usuário desiste do jogo:
gameover;
revelabombas();


A Escolha da Linguagem
======================
Teoricamente, você pode usar quase todas as linguagens para criar seu jogo, porém algumas se destacam
C, C++, Java, .Net(C#, VB.NET, etc)...
Eu programo em todas estas linguagens, principalmente em java, que se destaca muito pela portabilidade,
que traduzindo é: você escreve um programa no linux, mas roda em qualquer outro lugar onde tenha java...
mas optei por C, por querer algo mais comercial... nos jogos normalmente é usado C++,
mas eu gosto de procedural. =)

A Escolha das APIs
==================
Claro que você pode escolher uma engine pronta como a OGRE ou irlitch, mas eu quero conhecer mais do
que estou fazendo, estas APIs encapsulam muito as coisas e mesmo assim ficam complexas.
Decidi montar meu próprio motor...
Vou usar SDL como API principal para gerenciamento de ambiente, graficos, janelas, mouse, teclado, joys,
sons, etc), bullet physics para detecção de colisão, que é algo extremamente complexo, e OpenGL para 3D.

Compilando
==========
gcc fonte.c -o rodar -lmingw32 -lSDLmain -lSDL

Não mude a sequencia!!!


logo vou atualizar isto corrigindo alguns erros e adicionando o autotools para podermos usar os famosos: ./configure ; make ; make install;

...continua...

Mas só Deus sabe quando.

O primeiro grande problema é aprender a compilar o SDL
depois de instalar o gcc e baixar o SDL,
não teria tido problemas com isto no Linux, mas no windows precisei do mingw32 e o SDLmain
pra compilar um código de iniciação do SDL:
gcc helloSDL.c -o helloSDL -lmingw32 -SDLmain -lSDL

Isto compilou o básico, mas agora enfrento um novo desafio, a compilação do SDL para o SDL_GetTicks


Comentários

Postagens mais visitadas