Baixe o app para aproveitar ainda mais
Prévia do material em texto
Programação de Jogos com C++ e DirectX André Santee 21 Capítulo 1 Introdução à linguagem C++ Oprimeiro capítulo apresentará a linguagemC++ e indicará as diferenças entre C e C++. Apren- deremos como utilizar o compilador Microsoft Visual C++, além de constatar como é o funcio- namento dos operadores matemáticos e de alguns conceitos de entrada e saída de dados. Histórico A linguagem C foi criada em 1972, por Dennis M. Ritchie e Brian W. Kernighan, do Bell Labs Innovations, baseando-se na linguagem B, proveniente da antiga BCPL. B foi renomeado com a primeira letra de BCPL e a linguagem C, com a segunda. C tornou-se rapidamente popular, pois une leveza, poder e velocidade em códigos bem legíveis e de fácil interpretação, sem a necessidade de entender instruções complexas como os códigos escritos em linguagem Assembly. C/C++ é utilizada no desenvolvimento de mais de 90%dos jogos profissionais, de Tetris a jogos que utilizam avançadosmotores comoDoom III, da Idsoftware. A linguagemC++ foi introduzida por Bjarne Stroustrup, emmeados de 1983, com novos e poderosos elementos e novas propostas para a programação, que contribuem para o reuso, manutenção e adição ao código. C++ possui extensas bibliotecas-padrão que utilizam em grande quantidade as características exclusivas da linguagem em relação à C. Códigos escritos em C/C++ são de fácil leitura, pois a linguagem permite separar seu código em partes e arquivos para que seja mais bem estruturado. Com C++, o programador cria bons hábitos na programação, sabendo organizar seu código de maneira legível e tor- nando-o mais veloz. Compilador Umcompilador é um tipo de tradutor utilizado para que o desenvolvedor possa “comunicar- se” com a máquina sem a necessidade de utilizar a própria linguagem de máquina. No caso de um compilador de C/C++, essa ferramenta traduz um código escrito em linguagem C/C++ para linguagem de máquina e gera um arquivo EXE, que pode ser executado pelo sistema operacional. 22 Programação de Jogos com C++ e DirectX Um compilador inicia o processo lendo a primeira instrução do início do programa, es- crito em “linhas de comando”, e confere se existem erros. Se não existirem, o compilador avança para a próxima linha, sempre seguindo este processo, até a última linha (caso não haja mudanças de fluxo no código). Caso o compilador encontre algum erro no código, este será apontado demaneira que o programador saiba do que se trata. Um erro pode variar desde uma palavra desconhecida até uma falha em determinada expressão. Se nenhum erro for encontrado pelo compilador, este irá gerar um arquivo com extensão OBJ, com todas as linhas de código traduzidas, e logo em seguida será gerado um arquivo com extensão EXE, podendo ser executado pelo sistema operacional. Neste livro será utilizado o compilador Microsoft Visual C++, por ser o melhor e mais popular atualmente. Mas pode-se optar por outros compiladores gratuitos, como oDev-C++, da Bloodshed. Todos os códigos de lições desta primeira parte do livro funcionarão tanto com o Visual C++ como com o Dev-C++, com algumas mínimas alterações. No momento em que este texto foi escrito, a página oficial do compilador Dev-C++ era http://www.bloodshed.net/devcpp.html, onde este pôde ser obtido gratuitamente. Todos os compiladores de C/C++ são semelhantes, qualquer código pode ser escrito para o compilador Visual C++ 6.0 e funcionar perfeitamente com oDev-C++, fazendo apenas algumas modificações dependendo de quais bibliotecas foram utilizadas no código, pois nenhum compilador é idêntico a outro, principalmente no modo em que os programas são compilados. Tipos de compiladores Existem dois tipos de compiladores, os chamados compiladores simples e os compiladores com interface de desenvolvimento: ••••• Compiladores simples:Compiladores simples:Compiladores simples:Compiladores simples:Compiladores simples: compiladores cuja única função é compilar o código e indicar possíveis erros. Não possuem editor de código, ou seja, o código deve ser escrito em algum editor de texto simples, como o Bloco de Notas (Notepad) doWindows. Após escrever o código, o programador deve digitar uma linha de comando via console para compilar certo arquivo com determinado nome, que deve estar em formato C (linguagem C) ou CPP (linguagem C++). Um exemplo de compilador simples é o DJGPP, que não será utilizado para compilar os códigos neste livro, a não ser que se decida utilizá-lo. Os compiladores simples estão cada dia sendomenos utilizados, em virtude da falta de recursos fundamentais que os softwares da atualidade exigem.Nãohá nadamelhor que programar emumcompilador com ambiente de desenvolvimento especial para C/C++, com indicadores coloridos, em que basta um simples clique para compilar o programa, como ocorre com os compiladores com ambiente de desenvolvimento. 23 ••••• Compiladores com ambiente de desenvolvimento:Compiladores com ambiente de desenvolvimento:Compiladores com ambiente de desenvolvimento:Compiladores com ambiente de desenvolvimento:Compiladores com ambiente de desenvolvimento: como característica básica apre- sentam um editor de texto interno, e o programador só precisa escrever os códigos e compilá-los. A maioria desses compiladores possui várias opções e preferências para facilitar a compilação e vários outros métodos de depuração. Um exemplo de indicadores de cor no código: Exemplo:Exemplo:Exemplo:Exemplo:Exemplo: #include <ostream.h> #define oi “Oi mundo,\n” // início intintintintint main() { floatfloatfloatfloatfloat pi=3.1415f; cout << pi << “\n”; cout << “Oi mundo!\n”; returnreturnreturnreturnreturn 0; } Como se pode ver, o código possui identificadores com formatação diferenciada, indi- cando o que cada um deles representa, o que facilita muito esta tarefa. Não se preocupe em entender esse código por enquanto. Um fator extremamente importante da linguagem C/C++ é que, por padrão, uma letra minúscula é diferente de uma letra maiúscula, por exemplo: ‘Nome’ é diferente de ‘nome’, ‘QuEiJo’ é diferente de ‘Queijo’, ou seja, ‘X’ é diferente de ‘x’. Esta característica é conhecida como case sensitivity. C ou C++? Apesar de semelhantes, C e C++ não são e não podem ser tratadas como se fossem a mesma linguagem. C++ é uma nova linguagem que reaproveita a sintaxe e palavras-chave de C e adiciona diversos recursos extras, diferenças na estrutura do código e também de sintaxe em alguns casos. Por enquanto, vamos evitar abordar os mais profundos fundamentos de orientação a objetos da linguagem C++. Entenda C++ como umamelhoria e extensão da C. Todos os com- piladores de C++ compilam perfeitamente códigos escritos completamente em C, tendo al- guns cuidados e diretivas de pré-processamento inicialmente, mas os compiladores de C não podem compilar códigos com os recursos de C++. Visual C++ Visual C++ é um compilador extenso que pode parecer um pouco assustador a princípio. Antes de abordar os detalhes de seus recursos, mencionaremos um pouco as funcionalida- des básicas do compilador. Essa famosa ferramenta para programação C/C++ em ambiente Capítulo 1• Introdução à linguagem C++ 24 Programação de Jogos com C++ e DirectX 32-bit (Win32), com um ambiente de trabalho baseado na interface doWindows, modo tam- bém conhecido como IDE (Integrated Development Environment). Oi mundo! Vamos criar nosso primeiro projeto no Visual C++. Abra o programa, clique File, no canto superior esquerdo da tela, como mostra a figura 1.1, e, em seguida, clique New. Figura 1.1 – Tela do Visual C++. Quando você clicar New, surgirá uma janela semelhante à mostrada na figura 1.2. Figura 1.2 – Tipo de arquivo. 25 Em seguida, clique a aba Projects, como mostrado na figura 1.3. Figura1.3 – Seleção do tipo de projeto. Escolha a opção Win32 Console Application (Figura 1.4), no campo Project Name, que determi- nará o nome do projeto, escreva “Oi mundo” e, em seguida, clique OK. Figura 1.4 – Tipos de aplicação. Após clicar OK, será exibida outra janela (Figura 1.4), escolha An empty project e, finalmen- te, clique Finish. Uma nova janela surgirá e clique OK. Está tudo pronto para começarmos a escrever. Aparecerá no canto de seu editor algo parecido com o que é exibido na figura 1.5. Clique FileView no canto inferior e, em seguida, o símbolo + que está localizado ao lado do nome do projeto (Oi mundo files). A exibição ficará como ilustra a figura 1.6. Capítulo 1• Introdução à linguagem C++ 26 Programação de Jogos com C++ e DirectX Figura 1.5 – Componentes do ambiente de trabalho. Figura 1.6 – Arquivos do projeto. Volte ao File e New, como se estivesse fazendo tudo novamente.Mas, desta vez, clique a aba Filese, nocampo File Name,escreva “oimundo”, depois escolha aopção C++ Source Fileecliqueno campo Add to Project comomostra a figura 1.7. Figura 1.7 – Tipo de arquivo fonte. Clique OK. Você notará que foi incluso o arquivo oimundo.cpp na pasta Source Files e que uma janela de texto surgiu na tela. É nela que os tão esperados códigos serão escritos! Primeiro programa Escreva o seguinte programana caixa de texto intitulada oimundo.cpp: 27 oimundo.cpp: #include<ostream.h> intmain() { cout<<“Oimundo!\n”; return0; } Como já é tradição entre programadores, quando se está aprendendo determinada lingua- gem, sempre se começa com um programa que simplesmente escreve “Oi mundo!” na tela. Pressione Ctrl+F5 para executar o programa que acabou de escrever. Se não existir ne- nhum erro de compilação, a saída do programa (o resultado do código que escrevemos) será como mostra a figura 1.8. Figura 1.8 – Pequeno programa que exibe a frase “Oi mundo” na tela. Pressione uma tecla para fechar o programa. Analisando o código #include <ostream.h> A diretiva #include inclui o código de outros arquivos em seu programa. No caso deste código, a função usada do arquivo ostream.h é cout, que, na verdade, não se trata de uma função ou instrução, mas podemos tratá-la como se fosse por enquanto. int main() { main é a principal função do programa; nela é que se escreve o conteúdo do projeto que ficará entre as chaves ({ e }). O que estiver entre essas chaves é o que será executado antes de mais nada pelo compilador, linha por linha, de cima para baixo. Neste caso, o “conteúdo” de nosso programa é uma chamada ao comando cout, que você verá a seguir. Se ainda não entendeu muito bem esse processo não se preocupe. Em C/C++, todo o espaço em branco é ignorado pelo compilador. O programa mostrado (oimundo.cpp) é praticamente o mesmo que este: Capítulo 1• Introdução à linguagem C++ 28 Programação de Jogos com C++ e DirectX #include<ostream.h> intmain(){cout<<“Oimundo!\n”;return0;} Que seria idêntico a este também: #include<ostream.h> intmain() {cout<<“Oimundo!\n”; return0;} Amaneira inicial é a mais comum por facilitar a leitura do código. Sempre usaremos este padrão: int main() { cout << “Oi mundo!\n”; return 0; } Como já foi dito, a função main() é o início de um programa, e o que está entre as chaves é seu corpo, ou seja, os comandos que serão executados pelo compilador quando executa- da a função. A linha cout << “Oi Mundo!\n”; imprime na tela a frase “Oi mundo”, a constante \n no fim do texto é inserida para que o cursor vá uma linha abaixo, ou seja, o próximo caractere a ser exibido na tela será mostrado na linha debaixo. A estrutura do comando pode ser vista na figura 1.9. Figura 1.9 – Estrutura da chamada cout. O return 0; é uma palavra-chave da linguagem C/C++ que será apresentada mais adiante. Note que o return 0 também termina com ponto-e-vírgula, pois é uma instrução como qual- quer outra. Toda instrução que está no corpo de uma função, ou seja, entre chaves, deve terminar com ponto-e-vírgula. Entenda return 0 apenas como um comando que precisa ser utilizado, mas que aparentemente não causa nenhuma alteração no programa, e todas as instruções dadas devem ficar acima do return por enquanto. Pode-se usar várias chamadas cout em um programa para imprimir várias seqüências na tela, por exemplo: oimundo2.cpp: #include<ostream.h> intmain() { cout<<“Oimundo!“; cout<<“Cheguei!\n”; 29 cout<<“____FIM____\n\n”; return0; } Compile oprograma oimundo2.cpp. Para sair, basta pressionar uma tecla qualquer.Oprograma gerado a partir deste código émostrado na figura 1.10. Figura 1.10 – Compilando o projeto. A constante \n posiciona o cursor uma linha abaixo (retorno), e se utilizarmos dois \n (\n\n), então o cursor será posicionado duas linhas abaixo. Note que no fim de cada instru- ção foi inserido o caractere ; (ponto-e-vírgula) para indicar que a instrução terminou. Outras constantes Veja mais algumas constantes que são utilizadas da mesma forma que \n,mas possuem fun- ções diferentes: Constante Significado \b Retrocesso \f Alimentaçãodeformulário \n Novalinha \r Retornodecarro \t Tabulaçãohorizontal \” Aspas \’ Apóstrofo \0 Nulo \\ Barrainvertida \v Tabulaçãovertical \a Sinalsonoro \N Constanteoctal(ondeNéumaconstanteoctal) \xN Constantehexadecimal(ondeNéumaconstantehexadecimal) Capítulo 1• Introdução à linguagem C++ 30 Programação de Jogos com C++ e DirectX Variáveis Variáveis são utilizadas para armazenar algumdado namemória do computador. As variáveis são extremamente importantes emqualquer programa epodemassumir o valor de umnúme- ro inteiro (sem ponto decimal), real (com ponto decimal), caractere e outros tipos de dado quaisquer. Imagine um jogo onde a vida (saúde) do jogador é de 100. Este valor existe graças às variáveis, pois é nelas que está armazenado. Algo semelhante ocorreria com a munição, a posição, a quantidade de dinheiro e diversas outras propriedades. Tipos de variáveis Existem cinco tipos básicos de variáveis, cada um com suas características, seus valores e suas utilidades. Eles são: Nome Tamanho (em bytes) Valores que pode armazenar int 4 -2.147.483.648a2.147.483.647 char 1 256valoresdecaracteres float 4 1,2e-38a3,4e38 bool 1 trueoufalse double 8 2,2e-308a1,8e308 Existem tambémcombinações queutilizamaspalavras-chave unsignede signedou shorte long anteriormente à declaração do tipo de dado: Nome Tamanho (em bytes) Valores que pode armazenar unsignedchar 1 0 a 255 signedchar 1 -127a127 unsignedint 4 0a65.535 signedint 4 Omesmoqueint shortint 2 Omesmoqueint unsignedshortint 2 0a65.535 signedshortint 2 Omesmoqueshortint longint 4 -2.147.483.648a2.147.483.647 signedlongint 4 Omesmoquelongint unsignedlongint 4 0a4.294.967.295 longdouble 8 Dezdígitosdeprecisãodecimal Declarando variáveis Para declarar uma variável em C/C++, deve-se especificar seu tipo (int, float, char etc.) e, em seguida, um nome qualquer, que será utilizado para identificá-la, por exemplo: int var; 31 Essa instrução cria uma variável do tipo inteiro chamada var. Veja que o ; (ponto-e-vírgu- la) está presente. Umexemplo de declaração de variável: primeira_variavel.cpp: intintintintint main() { intintintintint idade; returnreturnreturnreturnreturn 0; } Comooprograma primeira_variavel.cppnãoutilizoua instrução cout, ocabeçalho ostream.hnãofoi incluso. Atribuindo valores Denada adianta ter uma variável e não poder atribuir-lhe valores que possam ser alterados no decorrer do programa. Para isso, é preciso atribuir umvalor à variável, comouso dooperador =, por exemplo: intidade=30; Neste caso, a variável idade passa avaler 30. Um programa que cria variáveis e lhes atribui valores pode ser: atribuindo.cpp: intintintintint main() { shortshortshortshortshort intintintintint vida=30; floatfloatfloatfloatfloat municao=20.34; charcharcharcharchar tipo=’c’; returnreturnreturnreturnreturn 0; } Nesseprograma foramdeclaradas variáveis do tipo short int, floate char. Comosepodever, a variável de tipo chardeve ter seuvalor entre apóstrofo. Emvariáveis do tipo float, seu valor pode conter ponto decimal; no caso da linguagemC/C++ (e amaioria das outras linguagens), usa-se ponto no lugar da vírgula que estamos acostumados a utilizar. Existemoutrasmaneirasmais flexíveis de se atribuir umvalor a uma variável, umadelas é: intvar; var=20; Esse método é empregado em casos em que seja necessária alteração no valor de uma variável após sua declaração. Capítulo 1• Introdução à linguagem C++ 32 Programação de Jogos com C++ e DirectX Utilizando variáveis Podemos tambémexibir variáveis utilizando a já conhecida instrução cout, comomostra o programacoutvar.cpp: coutvar.cpp: #include<ostream.h> intmain() { intvar1=30; doublevar2=20.34; charvar3=’c’; intvar4=var1; cout<<“var1=”<<var1; cout<<“\nvar2=”<<var2; cout<<“\nvar3=”<<var3; cout<<“\nvar4=”<<var4; var3=’v’; cout<<“\nAgoravar3éiguala:“<<var3<<“\n”; return0; } Imprimir uma variável é uma tarefa simples: em vez de um texto entre aspas, digita-se simplesmente o nome da variável. Se declararmos novamente o operador sobrecarregado <<, a função cout poderá imprimir outra entidade. Quando a variável var4 foi declarada, foi- lhe atribuído o valor de var1. Esse tipo de movimentação de valores é possível em qualquer linguagemde programação. Pode-se atribuir o valor de uma variável a outra como se estivés- semos atribuindo uma constante. Exemplos: valor=valor2 valor2=valor3 E daí em diante. Constantes Constantes são números ou valores quaisquer que não são variáveis. Considere a instrução int var=10;, neste caso o valor 10 é uma constante decimal, e algo semelhante ocorreria para variáveis do tipo char: char ch=’c’, assim o ‘c’ é uma constante de caractere. Lembre-se de que nunca se deve atribuir um valor a uma constante: erro.cpp: #include<ostream.h> intmain() { 20=10//ERRADO! return0; } 33 Regras É muito importante mencionar que ao escrevermos uma constante numérica, não devemos escrevê-la entre aspas, digite apenas seu valor, seja este decimal, hexadecimal ou octal. Sem- pre que formos escrever uma constante de caractere, a escrevemos entre apóstrofos, e sem- pre que formos escrever um conjunto de caracteres (conhecido como string), devemos es- crevê-lo entre aspas: regras.cpp: intmain() { cout<<20<<“\n”; cout<<“string\n”; cout<<‘c’<<“\n”; return0; } Declarações múltiplas de variáveis Umrecursomuito útil da linguagemC/C++ é apossibilidadededeclarar diversas variáveis com apenas umapalavra-chave. Por exemplo: int a, b, c, d; É o mesmo que: inta; intb; intc; intd; Veja que todas essas variáveis foramdeclaradas emuma linha só. Essemétodo é válidopara qualquer tipo de dado: float a, b, c, d; Mais sobre seu compilador Abrindo projetos Se você fechouoVisual C++ equer abrir novamente umprojeto, comoo “Oimundo”, nãobasta abrir o arquivo oimundo.cpp, o queéumerro freqüente cometidopor iniciantes, pois sedeve abrir o projeto. Para isso, clique File e, em seguida, Open Workspace, como indicadona figura 1.11. Capítulo 1• Introdução à linguagem C++ 34 Programação de Jogos com C++ e DirectX Figura 1.11 – Abrindo o ambiente de trabalho. Quandoclicar, surgirá na tela a janela deescolhade arquivos-padrãodoWindows; encontre oarquivoOi mundo.dsw,quenormalmenteestaráemC:\Arquivos de Programas\Microsoft Visual Studio\Myprojects\Oi mundo\ounodiretórioqueescolher. Pronto, oprojeto será aberto. Clique Close Workspacepara fechar oprojeto. Os arquivos comextensão .dsw são arquivos deprojeto doVisual C++. No compiladorDev- C++, da Bloodshed, o formato semelhante é o .DEV. Erros de compilação Quando o programador digita alguma linha com um erro de sintaxe ou digitação e tenta compilar o código, normalmente o compilador acusará o erro. No caso do Visual C++ (e também do Dev-C++), o erro será mostrado na barra inferior do software (Figura 1.12). Figura 1.12 – Erros de compilação. Se houver erro, o compilador tentará reconhecer o problema e indicar do que se trata se- gundo sua interpretação. Normalmente o aviso de erro não émuito preciso, e o programador é quem deverá analisar o trecho de código apontado à procura do(s) erro(s), ou seja, o compila- dor dá apenas as dicas. Se não houver erro, a mensagem do Microsoft Visual C++ 6.0 será Oi mundo.exe - 0 error(s), 0 warning(s), em outras palavras, nenhum erro e nenhum alerta. 35 Saiba diferenciar erros de alertas. Um erro é algo grave, que impossibilita o compilador de continuar, e um alerta (warning) é apenas um aviso do compilador de que algo pode estar errado, podendo indicar variáveis declaradas, mas nunca utilizadas, acessos a locais na me- mória não especificados que freqüentemente causam o travamento do programa e várias outras possíveis irregularidades. Criando executáveis A função fundamental de um compilador é gerar arquivos EXE de seu código. Para gerá-los, é preciso antes saber qual a diferença entre Build e Compile na maioria dos compiladores de C/ C++: o Compile cria somente os arquivos OBJ, conecta-os e gera um executável de modo DEBUG (para depuração), e o Build gera o arquivo EXE. Para obter um arquivo executável de extensão EXE, o compilador deve antes criar os ar- quivos OBJ a partir das fontes .cpp, o que ocorre automaticamente ao se clicar Build. Figura 1.13 – Modos de compilação. Como se pode ver na figura 1.13, o menu Build contém as opções Compile oimundo.cpp e Build Oi mundo.exe, com as teclas de atalho Ctrl+F7 para Compile e F7 para Build. Mais abaixo temos a opção Execute Oi mundo.exe, com a tecla de atalho Ctrl+F5. A função Execute Oi mund.exe realiza o Build e, então, executa o arquivo EXE. Versão release Ao compilarmos o programa no modo Build, o que estamos fazendo é criar o executável na versão para depuração (Debug). É um tipo de compilação que torna o programa mais pesa- do e lento, porém possibilita a indicação de erros e localizar onde estes ocorreram no códi- go. Após o desenvolvimento do jogo ou software, não é necessária nem recomendada sua distribuição em versão de depuração. Capítulo 1• Introdução à linguagem C++ 36 Programação de Jogos com C++ e DirectX A compilação otimizada e sem declarações para depuração do compilador pode ser feita em Batch Build. No mesmo menu mostrado na figura 1.13, clique Batch Build. Uma pequena janela será aberta. Selecione as duas caixas de opção e clique Rebuild All. A versão Release do software estará localizada no subdiretório Release da pasta do projeto. Operadores matemáticos A principal razão pela qual os computadores foram criados é processar dados, o que inclui a resolução de cálculos matemáticos, como adição, subtração, divisão e multiplicação. E é nisto que a linguagem C/C++ nos auxilia muito bem. Confira a seguir quais são os operadores matemáticos: Operador Função Símbolo + Adição + - Subtração - / ou : Divisão / X ou . Multiplicação * % Resto % Ooperador% retorna o resto de uma divisão. Vamos a alguns exemplos simples de uso desses operadores: math.cpp: #include<ostream.h> intmain() { intmult=10*5; intsoma=500+400; floatdivi=100.0/3.0; intsub=10-11; floatresto=11%3; cout<<mult<<“\n”; cout<<soma<<“\n”; cout<<divi<<“\n”; cout<<sub<<“\n”; cout<<resto<<“\n”; return0; } A figura1.14mostra o resultadodoprograma math.cpp. Figura 1.14 – Saída do programa math.cpp. 37 Neste programa, declaramos as variáveis e atribuímos valores que o computador deve calcular inicialmente e, em seguida, exibir na tela cada um deles. Também se pode imprimir o resultado dos cálculos diretamente como parâmetro para a função cout: math2.cpp: #include<ostream.h> intmain() { cout<<10*5<<“\n”; cout<<500+400<<“\n”; cout<<100.0/3.0<<“\n”; cout<<10-11<<“\n”; return0; } Asaídadoprograma math2.cppserá idêntica àdo math.cpp. Aprofundando Pode-se tambémutilizar operadores cujos elementos da operação sejamvariáveis. Trata-se de uma prática muito utilizada tanto em aplicativos comuns como em qualquer jogo. Um pequeno e simples exemplo de matemática em jogos poderia ser dado quando um personagem pega uma caixa contendo energia. Esse personagem está com 45 em sua barra vital e esse item adiciona 20 pontos à energia, então esse personagem ficará com 65. Vamos pegar esse exemplo e transformá-lo emprograma: life.cpp: #include<ostream.h> intmain() { intlife=100; cout << “Você tem “ << life << “ de vida\n”; cout<<“Vocêlevouumtiro!\n”; life=life-55; cout<<“Agoravocêtem“<<life<<“devida!\n”; cout<<“Vocêpegouumacaixadevida\n”; life=life+20; cout<<“Agoravocêtem“<<life<<“devida!\n”; return0; } Vamos entender o programa: intlife=100; cout << “Você tem “ << life << “ de vida\n”; cout<<“Vocêlevouumtiro!\n”; Capítulo 1• Introdução à linguagem C++ 38 Programação de Jogos com C++ e DirectX O int life declara a variável do tipo inteiro life e atribuímos a esta o valor 100. Usamoso cout e a variável lifepara indicar a quantidade de energia. Na terceira linha, há o aviso de que o jogador levou um tiro. life=life-55; cout<<“Agoravocêtem“<<life<<“devida!\n”; cout<<“Vocêpegouumacaixadevida\n”; Agora, atribuímos à variável lifeovalor desta comuma subtraçãode55. Podemosdizer que esse valor foi subtraído damesma variável. Em seguida,mostramos na tela o novo valor de life e avisamos que o jogador pegou uma caixa de vida. life=life+20 cout << “Agora você tem “ << life << “ de vida!\n”; Agora que o jogador pegou uma “caixa de energia”, podemos adicionar 20 à variável. Utilizamos a mesma lógica da subtração, mas agora atribuímos à life o valor dela mesma com a adição de 20. Podemos fazer várias combinações com variáveis e operadores. Uma lista com alguns exemplos de expressões seria: int a=20; int b=10; int c=5; a=b+c; c=a/2+b; b=a*-1; a=a*b*c; Utilizando parênteses Você já deve ter utilizado muito os parênteses nas aulas de matemática enquanto esteve na escola. O conceito é que toda a expressão ou valor dentro deles é resolvido primeiro. Quan- to mais interna for a expressão, maior é a prioridade e inicialmente esta será resolvida. Um exemplo válido em C/C++ que demonstra o uso dos parênteses é: x=(((10+15)*-1)+((101-(110+123)))*2); O que resultará em -289. Poderíamos também remover os parênteses: x=10+15*-1+101-110+123*2; Tendo agora 232 como valor de x. O resultado diferente nos leva a concluir que as ex- pressões entre parênteses possuem prioridade na execução da expressão. Um exemplomais simples e completo: 39 parenteses.cpp: #include<ostream.h> intmain() { intbonus=10; intEXP=5; intHP=((EXP*2)-1)+bonus; intMP=((EXP*3)+bonus)/2; return0; } C-Reduzido Umagrande vantagemna linguagemC/C++ está na possibilidade de utilizar operadores otimi- zados que permitem a redução na quantidade de instruções em linguagem de máquina no arquivo executável. Um exemplo disso são os operadores C-Reduzido, que podem ser uti- lizados para adicionar, subtrair, multiplicar e dividir, além de incrementar e decrementar em apenas uma unidade o valor das variáveis. Anteriormente, mostrou-se que para adicionar algum valor a uma variável pode-se atri- buir-lhe o valor dela mais determinado valor. Esses operadores servem para simplificar este processo e otimizar o programa. Veja a lista deles: C-Reduzido Equivalente X+=Y; X=X+Y; X-=Y; X=X-Y; X/=Y; X=X/Y; X*=Y; X=X*Y; X%=Y; X=X%Y; Trate X comoqualquer variável e Y comoqualquer constante, variável ou expressão. Vamos reescreveroprograma life.cppagora aplicandoessesoperadores e adicionandomais linhas de código: lifecompacto.cpp: #include<ostream.h> intmain() { intlife=100; cout << “Você tem “ << life << “ de vida\n”; cout<<“Vocêlevouumtiro!\n”; life-=55; cout<<“Agoravocêtem“<<life<<“devida!\n”; Capítulo 1• Introdução à linguagem C++ 40 Programação de Jogos com C++ e DirectX cout<<“Vocêpegouumacaixadevida\n”; life+=20; cout<<“Agoravocêtem“<<life<<“devida!\n”; life/=3; cout<<“life=”<<life; life*=3; cout<<“\nlife=”<<life<<“\n”; return0; } Analisando o código life-=55; Subtraímos55de life, queéomesmoque life=life-55. life+=20; Omesmoque life=life+20. life/=3; Omesmoque life=life/3. life*=20; Omesmoque life=life*20. Pratique estemétodo sempre que possível. Émais rápido e prático. Incremento e decremento Osoperadores de incremento e decremento têmbasicamente função semelhante à dos +=, -=, / =, %= e *=, com a diferença de que estes apenas somam ou subtraem uma unidade do valor da variável. Eles são ++e --. Ooperador ++, quandoutilizado, incrementa (como já deve ter notado) e -- decrementa o valor de uma variável qualquer. Assim, x++éomesmoque x=x+1, comumadiferença: sempreque este operador for utilizado, este irá incrementar a variávelmesmo sendoutilizada comoargumento. Isto tambémvale para x--, que decrementa umaunidade. ++ e --podemser utilizados de doismodos: pós-fixadooupré-fixado.Nomodopré-fixado, ooperadordeveestarposicionadoao ladoesquerdodonomedavariável e, nopós-fixado, ++ou -- devem ser posicionados ao lado direito do nomeda variável. Pós-fixado x++; ou x--; 41 Quando o pós-fixado é utilizado, o programa inicialmente utiliza o valor da variável e, em seguida, incrementa ou decrementa. Por exemplo: posfix.cpp: #include<ostream.h> intmain() { intx=0; cout<<x++<<“\n”; cout<<x<<“\n”; return0; } Oprograma anterior imprimena tela 0 e depois 1. Isto ocorre porquequandoédeclaradoo ++ pós-fixado, o valor de x é utilizado antes de ter seu valor incrementado, então o programa deve imprimir 0 e depois de incrementado o valor é impresso o número 1. Pré-fixado ++x; ou --x; No modo pré-fixado, o valor é incrementado e, em seguida, utilizado. Veja o exemplo posfix.cppalteradoparapré-fixado: prefix.cpp: #include<ostream.h> intmain() { intx=0; cout<<--x<<“\n”; cout<<x<<“\n”; return0; } Desta vez foi impresso na tela o valor -1 duas vezes. Pois aqui primeiro a variável foi de- crementada e, em seguida, seu valor foi utilizado. Operador de negação Esteoperador inverteovalor de algumavariável ouconstante. Vamosconsiderar x=10. Se aplicar- mos o operador ao x, atribuindo a ele próprio: x=-x;, xpassará a valer -10 (10 negativo). Basica- mente é como semultiplicássemos a variável por -1. Diferentemente dos operadores reduzidos ++ e --, quando utilizamos ‘-’ para passagemde uma variável como argumento ou elemento de expressão, seu valor não será alterado, mas o valor de retorno sim. Veja o exemplo: Capítulo 1• Introdução à linguagem C++ 42 Programação de Jogos com C++ e DirectX inverte.cpp: #include<ostream.h> intmain() { intx=123; cout<<x<<“\n”; cout<<-x<<“\n”; cout<<x<<“\n”; x=-x; cout<<x<<“\n”; return0; } O resultado deste programa é: 123 –123 123 –123 Ooperador de negação é igual ao de subtração, porém esses operadores não são osmes- mos para o compilador. Se formos utilizar o operadorde subtração ou qualquer outro junto a este, devemosescrevê-loentreparênteses: y=x-(-x);. Um exemplo: inverte2.cpp: #include<ostream.h> intmain() { intx=123; inty=321; y=x-(-y); x=y+(-x); cout<<x<<“\n”; cout<<y<<“\n”; return0; } Comentários Os comentários podemser utilizados para inserir textos emnosso código semalterar oprogra- ma. Sãomuito úteis ao explicar alguma linha, marcar algum trecho no código e para diversos outros propósitos. Sempre que o compilador encontrar a seqüência de caracteres //, tudo o que estiver deste local até o fim da linha será ignorado, e normalmente o código comentado ficará de uma cor diferente do restodo código se estivermos editandoocódigo emumcompilador com interface dedesenvolvimento. 43 Outramaneira de inserir comentários é entre /* e */, tudo que estiver entre esses pares de caracteres será ignorado.Vejaoprograma comentario.cpp: comentario.cpp: #include<ostream.h> //parausarocout /*Esteprograma fazsimplescálculos eimprimenatela*/ intmain() //funçãomain()doprograma { cout<<10*5<<“\n”; // cout<<500+400<<“\n”; // cout<<100.0/3.0<<“\n”; //oscálculos cout<<10-11<<“\n”; // //cout<<“Estetextonãoseráimpresso”; return0; } //fimdocódigo Testeocódigo comentário.cppeobservequeoscomentáriosnãoafetamemnadaacompilação e execução do programa. Diretivas Opapel da diretiva de compilação épassar informação ao compilador, e não ao computador. A diretivamais utilizada por nós até agora foi a #include, mostrada namaioria dos exemplos deste capítulo. Asdiretivasdevempossuir ooperador# comoprefixo, e apenasumadiretivapor linha deve ser chamada. A seguir, veremos duas das principais diretivas que vamos utilizar por enquanto. #include Adiretiva #include concatena o códigodedeterminado arquivono local onde foi chamada. Isto vale para tudo que for declarado, desde variáveis até funções e classes. Por exemplo: caso se declaremalgumas variáveis dentro de umarquivo separado, assimque for chamadoo #include deste arquivo, o compilador tratará todo o código incluso como parte do código onde esta fonte foi chamada. Normalmente, em vez de .c ou .cpp, a extensão do arquivo chamado no #include é .hou .hpp (primeira letra dapalavra “header”, o ‘pp’ indica plus-plus ou ++). #include“funcs.h” Onomedo arquivo deve ficar sempre entre <> (caso esteja localizado próximo aos outros arquivos de cabeçalho-padrão do compilador ou exclusivos doprojeto) ou aspas (caso seja de uso exclusivo do projeto atual, mas não pertença a uma biblioteca ou framework). O arquivo deve estar localizadonomesmodiretório de seuprojeto ounodiretório includedo compilador. Capítulo 1• Introdução à linguagem C++ 44 Programação de Jogos com C++ e DirectX #define Esta diretiva basicamente permite a permutação de uma palavra por outra palavra-chave ou expressão. Tanta simplicidade não indica que este recurso seja de pouca utilidade, muito pelo contrário, visto que evita muitas vezes a necessidade de reescrever uma constante ou palavra-chave complexa e de difícil memorização. O #define funciona da seguinte maneira: #define MOSTRA cout << “Oi mundo”; O novo identificador MOSTRA, à direita do #define, indica o nome do valor. E cout << “Oi mundo”; é o valor de MOSTRA. Após essa declaração, sempre que for encontrada no código-fonte a palavra MOSTRA, esta será substituída por cout << “Oi mundo”; sem alterar em nada o que foi escrito no restante do código. Um exemplo: def.cpp: #include<ostream.h> #defineMOSTRAcout<<“Oimundo”; #definePI3.1415 intmain() { MOSTRA cout << “\nPI = “ << PI << “\n”; return0; } Nesseexemplo,ocompilador interpreta MOSTRAcomo cout << (...)e PIcomo 3.1415. Lembre-se de quenunca devemos inserir espaçononomedeuma constante #define: def-erro.cpp: #include<ostream.h> #defineOIMUNDOcout<<“Oimundo\n”;//estáerrado! intmain() { OIMUNDO //estáerrado! return0; } Quandoo compilador encontrar o primeiro espaço, será definida a primeira palavra como sendo o parâmetro e, então, esse código será interpretado da seguinte maneira: int main() { MUNDO cout “Oi mundo\n”; MUNDO // está errado! return 0; } 45 O que é grosseiramente errôneo. Espaço em qualquer nome de identificador deve ser substituídopor sublinhado (_), comonoexemplo corrigidodoprograma def-erro.cpp: def.cpp: #include<ostream.h> #defineOI_MUNDOcout<<“Oimundo\n”;//Corrigido! intmain() { OI_MUNDO//Corrigido! return0; } Agora, sim, está tudo certo! Obtendo valores do teclado Emqualquer software é necessário, de algummodo, promover a entrada de dados pelo usuá- rio, o que épossível coma instrução cin, que solicita a entrada de algumvalor pelo teclado, seja este uma string, char, float, double, intou qualquer outro dado.O cin encontra-se no arquivo de cabeçalho istream.he sua sintaxeé: cin>>variável; O operador >> indica que esta será uma entrada de dado (lembre-se do operador << que significa saída de dado). Com isso, quando o usuário digitar um valor no teclado, este será automaticamente atribuído à variável passada como parâmetro. Vamos ao nosso primeiro programautilizandoo cin: cin.cpp: #include<ostream.h> #include<istream.h>//temosumnovoheaderaqui! intmain() { intidade; intdia; cout<<“Qualsuaidade?“; cin>>idade; cout<<“\nQuediaéhoje?“; cin>>dia; cout<<“\n\nSuaidade:“<<idade; cout << “\nHoje é dia “ << dia << “.\n”; return0; } Após executado, cin.cpp seguirá os seguintes passos comomostra a figura 1.15. Capítulo 1• Introdução à linguagem C++ 46 Programação de Jogos com C++ e DirectX Figura 1.15 – Saída do programa cin.cpp. Vamoscompreenderoprograma cin.cpp: intidade; intdia; Declaramos as variáveis que serão utilizadas durante o programa. cout<<“Qualsuaidade?“; cin>>idade; cout<<“\nQuediaéhoje?“; cin>>dia; Primeiro, imprimimos na tela a pergunta: “Qual sua idade?” e esperamos que o usuário digite sua idade ou qualquer número. Já na segunda linha da função main, o cin desempenha seu papel: espera que ENTER seja teclado após um valor ser digitado. Este valor será atribuído à idade. Realizamos o mesmo processo novamente, mas desta vez perguntando que dia é hoje e armazenando esse valor na variável dia. cout << “\n\nSua idade: “ << idade; cout << “\nHoje e’ dia “ << dia << “.\n”; Imprimimos na tela o conteúdo das variáveis para nos certificar de que os valores real- mente foram alocados. Agora vamos escrever programasmais interessantes! dias.cpp: #include<ostream.h> #include<iostream.h> intmain() { intidade; cout<<“Qualsuaidade?“; cin>>idade; cout<<“\nVocêtem“<<idade*365<<“diasdeidade!\n”; return0; } Este programapergunta a idade dousuário e revela quantos dias de vida ele possui aproxi- madamente. 47 porcento.cpp: #include<ostream.h> #include<iostream.h> intmain() { doubleval1; doubleval2; cout<<“Digitequanto%vocêdeseja:“; cin>>val1; cout<<“\nDigiteovalor:“; cin>>val2; cout << val1 << “% de “ << val2 << “ é “ <<(val2/100)*val1 << “!\n\n”; return0; } Esse programa pede dois valores e informa sua porcentagem. printf e scanf Anecessidadeda abordagemdeste par de funções da linguagemC sedeve ao fato deque você provavelmente verá e terá vontade de analisar códigos-fonte nãopertencentes aos destemate- rial. Amaioria desses códigos utiliza esses comandos, que são semelhantes à cin e cout. printf O printf é uma espécie de cout da antiga linguagemC. Funciona demaneira semelhante, com algumas diferenças. O scanf é como um cin, mas também com algumas diferenças de sintaxe. Por exemplo: cout << “Oi mundo”; Com o printf seria: printf( “Oi mundo” ); O resultado seria omesmo para ambas asfunções. As funções printf e scanf encontram-se no arquivo-cabeçalho stdio.h. Especificador de formato Um tipo de constante exclusivo das funções do arquivo stdio.h são as de string (texto), que possuem como prefixo o caractere %. Essas constantes são utilizadas para possibilitar a im- pressão, dentro de um texto, de valores contidos em variáveis, por exemplo: int x=10; char ch=’a’; printf( “O numero é: %d, e a letra é: %c\n”, x, ch); Capítulo 1• Introdução à linguagem C++ 48 Programação de Jogos com C++ e DirectX Na exibição do texto final, %d e %c serão substituídos pelos valores de x e ch, passados como parâmetro emordemde declaração após a declaração da string. Veja a tabela dessas constan- tes: Código Formato %c Caractere %d Inteirodecimalsinalizado %i Inteirodecimalsinalizado %e Notaçãocientífica(eminúsculo) %E Notaçãocientífica(Emaiúsculo) %f Pontoflutuantedecimal %g Usa %e ou %f, o que for mais curto %G Usa %E ou %f, o que for mais curto %o Octalnãosinalizado %s String %u Inteirodecimalnãosinalizado %x Hexadecimalnãosinalizado(letrasminúsculas) %X Hexadecimalnãosinalizado(letrasmaiúsculas) %p Exibeumponteiro %% Mostraosímbolo% Todos estes funcionam damesmamaneira. Quando é definido um tipo com %_ dentro da string, a função vai esperar uma variável desse tipo após a string ser passada. Lembre-se de que são opcionais em uma chamada printf. scanf Já a função scanf possui uma diferençamaior para o cin.Vamos comparar códigos equivalen- tes usando cada uma dessas funções: int x; scanf( “%d”, &x ); É o mesmo que: int x; cin >> x; Na função scanf, primeiramente devemos especificar o tipo com uma string (ex.: %f para float, %c para char, %u ou %i para int), diferentemente da instrução cin, que encontra o tipo automaticamente. Note que há um operador & prefixado à variável x. Por enquanto saiba apenas que este deve estar sempre presente. Sumário Agradecimentos Prefácio Parte I - Linguagem C++ Capítulo 1 - Introdução à linguagem C++ Histórico Compilador Tipos de compiladores C ou C++? Visual C++ Oi mundo! Primeiro programa Analisando o código Outras constantes Variáveis Tipos de variáveis Declarando variáveis Atribuindo valores Utilizando variáveis Constantes Regras Declarações múltiplas de variáveis Mais sobre seu compilador Abrindo projetos Erros de compilação Criando executáveis Versão release Operadores matemáticos Aprofundando Utilizando parênteses C-Reduzido Analisando o código Incremento e decremento Operador de negação Comentários Diretivas #include #define Obtendo valores do teclado printf e scanf printf Especificador de formato scanf Capítulo 2 - Conceitos básicos da linguagem Comando if Analisando o código Operadores relacionais Várias instruções no escopo if Operadores lógicos AND e OR A palavra-chave else Verdadeiro e falso Operador NOT Variáveis do tipo bool e if Operador ? SWITCH Regras básicas switch aninhado switch sem break Laço WHILE Comando BREAK Laço DO WHILE Laço FOR Laço regressivo Pulando valores no laço FOR Laço infinito Comando CONTINUE Capítulo 3 - Funções e sua relação com as variáveis Funções O que são funções? Qual a vantagem de utilizar funções? Programando funções Analisando o código Funções com argumento Funções com valor de retorno Funções do tipo void Funções inline Funções como parâmetro do if Funções como argumento para outras funções Sobrecarregando funções Valores default e omissão de argumentos Recursividade em funções Manipulando variáveis externas As relações entre funções e variáveis Variáveis externas Variáveis estáticas Constantes Capítulo 4 - Arrays, ponteiros e strings Arrays Analisando o código Atribuindo valores durante a declaração Ponteiros Como as variáveis são organizadas Declarando ponteiros Encontrando endereços de variáveis Manipulando variáveis via ponteiros Ponteiro para ponteiro Apontando arrays Manipulando arrays por ponteiro Uso de ponteiros em funções Array de ponteiros Recebendo arrays em funções Arrays multidimensionais Strings Declarando strings Estrutura de uma string Passando strings como argumento Copiando strings com strcpy Concatenando strings com strcat Casting Casts para conversão em variáveis Ponteiros do tipo void sizeof #define com argumentos Cuidados a serem tomados O comando typedef Alocação dinâmica Capítulo 5 - Tipos definidos pelo programador e introdução à orientação a objetos Estruturas Conceitos básicos de estruturas em C++ Declarando variáveis de estruturas Acessando membros de estruturas Estruturas aninhadas typedef e structs Funções membro Definindo funções externamente Ponteiros para estruturas Transferindo valores de estrutura para funções Funções que retornam estruturas Arrays de estrutura new e delete em structs Construtores Sobrecarregando construtores Destrutores Analisando o código Listando valores Classes: a base da linguagem C++ Declaração de classes Analisando o código Herança de classes Mais sobre herança de classes Classes amigas Sobrecarga de operadores Analisando o código Mais sobre sobrecarga de operadores Ponteiro this Enumerando constantes Mais sobre pré-processamento e compilação condicional #ifdef #else Compilação condicional com expressões #elif Diretiva #undef Uniões Parte II - Computação gráfica e conceitos da programação de jogos Capítulo 6 - Introdução teórica à computação gráfica Conceitos básicos de espaço 2D Conceitos básicos de espaço 3D Mão-esquerda e mão-direita Câmera Polígonos Vetores Normalizando vetores Vetores cruzados Produto escalar Rotação, translação e escala Translação Rotação Escala Matrizes Matriz identidade Transformando matrizes Escalando matrizes Transladando matrizes Rotacionando matrizes Multiplicando matrizes por matrizes Espaço de modelo para espaço de mundo Direct3D? OpenGL? API? Termos que você precisa saber RGBA ou ARGB Renderização Rasterização Clipping Depth-buffer Pipeline Alpha ou alpha blending Neblina Vertex shaders Pixel shaders Modos de classificação de vértices e triângulos Triangle strips Triangle fans Triangle list Técnicas de culling Front e backface culling Clockwise culling Counter-clockwise culling Modos de renderização Flat shaded Gouraud shading Wireframe Normais Luzes Luz ambiente Luz posicionada Luz direcional Luz holofote Material Difusão Ambiente Especular Potência Texturas Texels Multitextura Filtros de textura Minification Magnification Mip-mapping Front buffer e back buffer Quadros por segundo (FPS) Capítulo 7 - Win32 e programação com Direct3D Win32: API do Windows O que é DirectX? Primeiros contatos com o DirectX 9 Nossa primeira janela Analisando o código Capítulo 8 - Renderização simples com Direct3D Desenhando primitivas Formato de vértices Declarando os dados Criando o buffer Desenhando o triângulo DrawPrimitiveUP: renderização sem buffers Index buffers Criando um index buffer para Direct3D A criação do vertex buffer Renderizando o buffer indexado Vantagens de utilizar index buffer Desvantagens de utilizar index buffer Vértices indexados sem buffers Capítulo 9 - Renderizando polígonos texturizados Texturas D3DXCreateTextureFromFileEx Desligando a textura Limpando a memória Filtros nas texturas Minification Magnification Mip-mappingCapítulo 10 - Alpha blending Transparência - Alpha blending Alpha aditivo Alpha de subtração Color keying Multitextura Capítulo 11 - Transformações geométricas da cena 3D Translação Rotação Escala Câmera D3DXMatrixLookAt Capítulo 12 - Propriedades visuais dos objetos Materiais Iluminação por vértice Direcional Holofote Posicionada Estrutura D3DLIGHT9 Luz direcional Luz holofote Luz posicionada Registrando as luzes Efeito de névoa Ligando a neblina Definindo as distâncias Definindo a cor Ligando a neblina por vértice Ligando a neblina por pixel Definindo a densidade Observações Capítulo 13 - Elementos bidimensionais Desenho de textos Sprites 2D na tela 3D Capítulo 14 - Fundamentos da programação de jogos Tela cheia em Direct3D Dispositivo de entrada: teclado Animações interativas Dispositivo de entrada: mouse SetCursorPos GetCursorPos Movimento do cursor Billboards Capítulo 15 - Carregando objetos 3D Carregando arquivos da memória Arquivos MD2 Carregando arquivos de modelo animado Preparando o arquivo .MD2 para leitura Carregando o cabeçalho Coordenadas de textura Carregando as faces Transformações Configurando os quadros Animação Convertendo para o cache de vértices do Direct3D Calculando as normais Deletando objetos sem mais utilidade Criando o vertex buffer dinâmico Renderizando modelos animados Trabalhando com os quadros Incrementando os quadros Interpolação: obtendo o objeto final Copiando dados para o buffer E finalmente... renderizando! Renderizando quadros específicos Limpando a memória Aplicando o skin aos modelos Utilizando a classe MD2Loader Desenhando quadros específicos Trabalhando com armas para personagens Capítulo 16 - Controlando personagens Movendo os modelos na cena Movimento independente da FPS Calculando a taxa de quadros por segundo Função para movimento independente da FPS Câmeras em terceira e primeira pessoas Câmera em terceira pessoa #1 Câmera em terceira pessoa #2 Câmera em terceira pessoa #3 Câmera em primeira pessoa Capítulo 17 - Trabalhando com mapas 3D Geração de cenários 3D Estrutura do sistema de geração de mapas Criando o buffer de vértices para os tiles Criando o buffer Carregando as superfícies dos tiles Definindo os tiles Declarando o tilemap Renderizando o mapa Frustum culling: otimização para cenas 3D Montando os frustum planes Operações com os planos Detectando esferas no frustum Detectando retângulos no frustum Utilizando a classe FrustumCulling Luzes da cena Estrutura da luz por vértice Estrutura geral do mapeamento de iluminação Renderizando tiles com iluminação em multitextura Frustum culling para os mapas Criando as luzes em tempo real Culling nas luzes Utilizando a classe cSceneGen Capítulo 18 - Sistemas de colisão Detecção de colisão Colisão entre esferas Colisão entre cilindros Colisão entre caixas Colisão entre reta e triângulo Colisão entre segmento e triângulo Alternativa Colisão com o mapa Encontrando a altura do terreno Transformando apenas o segmento Colisão com as paredes O problema dos múltiplos vetores Colisão utilizando apenas um vetor Capítulo 19 - Adicionando objetos 3D à cena Fontes de luz Classe SG_OBJECT Estrutura SG_LIGHTSOURCE Posicionando as luzes automaticamente Colisão com os objetos Nem tudo o que reluz é ouro Capítulo 20 - Música e efeitos sonoros Efeitos sonoros com DirectSound Criando o objeto CSoundManager Criando o objeto CSound Funções auxiliares Músicas com DirectMusic Criando o CMusicManager Funções auxiliares Capítulo 21 - Breve introdução à IA Inteligência artificial Patrulha Avistando um invasor Reação Com quantos paus se acaba com um personagem Capítulo 22 - Projetando o jogo Escrevendo o documento de design Características a serem documentadas Informações de design Escolha do hardware mínimo Trabalhando com perfis Capítulo 23 - Programando o jogo Motores Padrões da programação em C++ Notação húngara Escrevendo em inglês Organização do código Organização de dados em jogos Entidades do jogo Níveis do jogo
Compartilhar