Baixe o app para aproveitar ainda mais
Prévia do material em texto
DESENVOLVIMENTO DE JOGOS MOBILE 1 Desenvolvimento de Jogos Mobile DESENVOLVIMENTO DE JOGOS MOBILE 2 Desenvolvimento de Jogos Mobile Introdução aos Jogos Digitais Um jogo digital refere-se a qualquer jogo eletrônico projetado para ser utilizado em um computador, console ou dispositivo móvel, entre outras plataformas eletrônicas. Os jogos digitais fazem parte da cultura de massa desde a popularização dos consoles de videogames, como o Atari Video Computer Systems (Atari VCS). Lançado em 1977, o console que seria mais tarde chamado de Atari 2600, chegou a vender 8 milhões de unidades até 1983. Um jogo digital é uma atividade lúdica, composta por uma série de ações e decisões, limitada por regras e pelo universo do jogo, dentro de um ambiente eletrônico próprio, interativo e de fácil utilização. A combinação dessas regras com objetivos específicos de cada jogo é o que caracteriza o desafio, a emoção e a diversão ao jogador em sua jornada pelo jogo. Os jogos apresentam grande heterogeneidade, e podem ser classificados de diferentes formas, sendo a própria tipologia alvo de estudos de muitos profissionais da área de projeto e criação de jogos digitais. Existem várias tipologias para proceder à classificação de jogos digitais, como: BECTA (2003), que delineou uma classificação que tenta englobar os vários gêneros de jogos digitais existentes, de acordo com os estilos, narrativas, temáticas e atividades. GRAELLS (2000), que estabelece uma tipologia para jogos digitais levando em conta a estrutura dos jogos e as principais competências mobilizadas pelo jogador no DESENVOLVIMENTO DE JOGOS MOBILE 3 desenrolar do jogo, nomeadamente a psicomotricidade, o raciocínio, a lógica, a estratégia e a memória. Projeto e Criação de Jogos Digitais O planejamento de um jogo começa com pequenos conceitos que são expandidos a partir de brainstorm. Nenhuma ideia é descartada até que todos os elementos se consolidem na espinha dorsal do jogo. Ao esboçar ideias, é interessante a construção de mapas mentais (Mind Map), um diagrama ou gráfico usado para gestão de informações, conhecimentos e para a compreensão e solução de problemas. A narrativa é um elemento essencial para um jogo digital, podendo ser apresentada em primeira ou terceira pessoa. Ela é composta por cinco partes: Enredo, Personagens, Espaço, Tempo e Clímax. Quando narrado em primeira pessoa, percebe-se que o narrador é um dos personagens e descreve sua versão da história, enquanto na terceira pessoa o narrador coloca-se ao lado do jogador. Para muitos autores, o personagem é o fundamento essencial de um roteiro. É o coração, alma e sistema nervoso de uma história. Antes de colocar uma palavra no papel, tem que se conhecer o personagem. Após formatar a ideia central de um jogo digital, o passo seguinte é a formatação de um roteiro preliminar (Story Line). É claro que surge a necessidade de entender quem são os personagens integrantes do roteiro, qual a participação de cada um na story line, bem como as relações entre diferentes personagens. Com as ideias já formuladas sobre gênero, narrativa, personagens e outros itens esboçados em mãos, o próximo passo é a criação do GDD. DESENVOLVIMENTO DE JOGOS MOBILE 4 Documento de Game Design (Game Design Document) trata do agrupamento dos diversos elementos acerca do jogo em um único documento, o qual funcionará como a espinha dorsal desse e de qualquer outro projeto envolvendo jogos digitais. Esse documento define todos os pontos de um jogo digital e guia todas as equipes envolvidas no processo de produção, e o profissional responsável pelo GDD e por todo o projeto de um jogo é chamado de Game Designer. Apesar de ter uma grande liberdade com relação ao formato, os elementos componentes de um GDD normalmente incluem: CONCEITO - nome do jogo, apresentação resumida, público alvo, estilo de jogo, história e principais regras. ESPECIFICAÇÕES TÉCNICAS - sistema operacional, hardware mínimo, requisitos de software, bem como recursos gráficos. ESPECIFICAÇÕES DO JOGO - fases, níveis de dificuldade, modo de jogo, pontuação e ranking, número de jogadores, save games, câmera, personagens, itens de jogo e cenário, evolução e mensagens. DISPOSITIVOS DE ENTRADA - suporte a mouse, uso de teclado e joystick, toque de tela, controle de menu, teclas e botões utilizados. DESIGN GRÁFICO E ARTE - abertura, layout de menus e telas, definição de fases e layout do jogo em cada fase. SONORIZAÇÃO - músicas nos menus e em cada fase, bem como efeitos sonoros em geral. DESENVOLVIMENTO DE JOGOS MOBILE 5 DESENVOLVIMENTO – planejamento envolvendo as tarefas em termos de tempo, recursos e metas. DESIGN PARA O TIPO DE JOGO - caracterização do tipo de jogo, bem como a definição da ação em terceira ou primeira pessoa. ENREDO E ROTEIRO - jogos com características de RPG possuem enredos que se desenvolvem durante o jogo, e acontecimentos relevantes devem ser registrados. CARACTERÍSTICAS GRÁFICAS - informações acerca de cenários e modo de renderização, como tipo de iluminação, uso de estilo cartoon etc. CONCEITO GRÁFICO - arte conceitual do projeto e dos mais diversos elementos, como personagens, itens e cenários. INFORMAÇÕES PARA PROGRAMAÇÃO - capacidade mínima de processamento, incluindo quantidade de memória, tipo processador e modelo de placa de vídeo. TIPOS DE MAPA - pode ser um mapa simples, visão isométrica, ou outro, dependendo do tipo de jogo. PROPRIEDADES DAS ENTIDADES –propriedades obrigatórias de cada entidade do jogo. Após o nascimento da ideia por trás de um jogo digital, e todos os processos envolvendo elementos conceituais e diretrizes artísticas até a concepção de um GDD, inicia-se o processo de desenvolvimento do jogo em si. Uma ferramenta muito facilitadora nessa fase inicial é o Storyboard, no qual os artistas irão demonstrar os textos do roteiro mediante imagens, simulando a ação dentro do jogo. DESENVOLVIMENTO DE JOGOS MOBILE 6 Tendo o StoryBoard como um guia para a produção, ocorre agora a preocupação com a área gráfica (GFX) e com o som do jogo (SFX). Considerando-se o GFX, este deve levar em consideração o tipo de ambiente a ser utilizado, podendo ser 2D ou 3D. Quanto ao SFX, todos os sons devem ser contemplados, desde um simples tiro, passos, música e até voz sintetizada, podendo ser um som plano ou em ambiente 3D. Tendo os componentes visuais e sonoros necessários em mãos, estes devem ser combinados segundo a lógica do jogo, aparecendo nesse ponto necessidades comuns à grande maioria dos jogos digitais, como a detecção de colisão, por exemplo. Há algum tempo os jogos eram criados totalmente a partir de uma linguagem de programação, como Assembly ou C++, mas atualmente as Game Engines fazem boa parte do trabalho, e a programação se concentra apenas nas características específicas do novo jogo. Gráficos e Sons nos Jogos A representação gráfica dos personagens, cenários e demais elementos é crucial para o desenvolvimento de um jogo. Esses elementos podem ser definidos em duas ou três dimensões, e, para cada caso, existe uma grande diversidade de ferramentas que podem ser utilizadas. Alguns jogos são criados utilizando apenas elementos 2D, mesmo que com efeitos de sombra, simulando efeitos 3D, o que tem sido muito comum nos jogos de plataforma. Um formato muito utilizado para as imagens 2D da atualidadeé o PNG, pois apresenta características de transparência, facilitando a sobreposição de camadas. Um componente comum no ambiente de gráficos 2D é o Sprite, o qual define uma animação quadro-a-quadro obtida a partir de imagens renderizadas previamente. DESENVOLVIMENTO DE JOGOS MOBILE 7 Os elementos 3D apresentam uma complexidade maior, pois trabalham com efeitos de iluminação e texturização em tempo real, diferentemente de um vídeo, onde a renderização ocorre toda antes da exposição da animação. A modelagem dos elementos 3D pode ser feita com ferramentas diversas, a exemplo do Blender, 3DS Max, Maya, entre várias outras, e o processo inicia-se com a construção de uma malha, sobre a qual serão dispostos materiais e texturas, utilizando-se ao final elementos de iluminação sobre o conjunto. É comum a utilização de Model Sheet, tratando de um conjunto de visões (superior, frontal, lateral) de um personagem, concebido de forma artística, para viabilizar a modelagem computacional. O maior custo computacional em termos de 3D é com relação à qualidade da imagem final. O termo shading, ou sombreamento, se refere ao nível de detalhamento e da percepção de profundidade em ilustrações e modelagens 3D. DESENVOLVIMENTO DE JOGOS MOBILE 8 Os sons mais diversos são de grande importância para um jogo pois, assim como na vida real, a audição é um de nossos sentidos mais importantes. Qualquer som dentro de um jogo deve transmitir informação, emoção ou localização, e hoje em dia as tecnologias de som 3D são amplamente exploradas por jogos como God of War, e diversos simuladores realísticos, voltados para treinamento profissional, particularmente militar. Game Engine Motor de jogo, também conhecido pelo termo em inglês Game Engine, é um programa de computador utilizado para simplificar e abstrair o desenvolvimento de jogos eletrônicos ou outras aplicações com gráficos em tempo real. A funcionalidade tipicamente fornecida por um motor de jogo inclui: um motor gráfico para renderizar gráficos 2D e 3D, um motor de física para simular a física em si ou simplesmente para fazer detecção de colisão, suporte a animação, sons, inteligência artificial, redes, gerência de memória, gerência de arquivos, gerência de linha de execução, além de controles em geral para cenas e entidades. É comum o uso de uma ou mais linguagens de programação, o que viabiliza a sua personalização para a funcionalidade requisitada por um jogo específico. DESENVOLVIMENTO DE JOGOS MOBILE 9 Existem diversos fornecedores no mercado, sendo algumas das Game Engines mais relevantes: UDK, Unreal Engine, Unity 3D, Cry Engine, Java Monkey, Blender Game Engine, entre diversas outras. Uma grande vantagem da Unity 3D, em particular, é a facilidade na criação de jogos em 2D e 3D para as mais diversas plataformas, como o Android, por exemplo. Embora aceite outras linguagens, há uma preferência natural pela programação em linguagem C# para essa Game Engine. A unidade básica de trabalho na Unity 3D são os Assets, e pode-se obter muitos deles, inclusive podendo ser gratuitos, a partir da Game Engine, pelo Asset Store. Essa engine traz de um ambiente completo e bastante intuitivo para a criação de jogos, aceitando também diversos formatos para importação de outras ferramentas, como o 3DS Max e o Blender, além de apresentar muitos tutoriais no site do fornecedor (https://unity3d.com/pt). Ela pode ser baixada e utilizada livremente, porém ressarcindo ao seu fabricante sob a forma de royalties a partir de determinada quantidade de cópias do jogo comercializadas. Na criação de um projeto Unity deve ser escolhido entre os modelos de criação 2D ou 3D. Também podem ser selecionados os Assets (recursos) que serão utilizados no novo projeto. DESENVOLVIMENTO DE JOGOS MOBILE 10 Tendo sido criado o projeto, o ambiente será iniciado, exibindo as diversas ferramentas disponíveis na plataforma. Na visualização padrão inicial serão observados: Toolbar, Hierarchy Window, Scene View, Inspector Window e Project Window. Todo elemento manipulável visualmente no Unity é um Game Object, incluindo as primitivas 3D disponibilizadas pela Engine. Por exemplo, o menu Game Object >> 3D Object >> Cube é utilizado para a criação de um cubo, o qual poderá ser visualizado e manipulado na Scene View ou pelo Inspector. DESENVOLVIMENTO DE JOGOS MOBILE 11 Além do acesso pela Toolbar, as operações básicas oferecem alguns atalhos úteis via teclado: Q move a cena como um todo, facilitando a visualização. W translada o objeto selecionado. E rotaciona o objeto selecionado. R altera a escala do objeto selecionado. O botão direito do mouse, em conjunto com as teclas W, S, A e D permitem controlar a visualização da câmera na Scene View. Para as operações de translação, rotação e escala são disponibilizados Gizmos, ou como poderiam ser descritos, eixos de transformação 3D. A divisão Hierarchy mostra os objetos da cena e seus relacionamentos, Inspector mostra todas as propriedades do objeto selecionado, permitindo manipulá-las. Com a opção Add Component é possível definir comportamentos específicos, como na utilização de física. Terrenos são elementos de grande importância para a construção de cenários 3D, e opção Game Object >> 3D Object >> Terrain oferece um ferramental muito completo para a sua criação. Com o uso das ferramentas de terreno, acessíveis a partir do Inspector, é possível aumentar, diminuir ou suavizar elevações, e com as elevações definidas, texturas podem ser aplicadas ao relevo com a opção de pintura (pincel). Também é possível DESENVOLVIMENTO DE JOGOS MOBILE 12 adicionar vegetação e detalhes ao terreno, viabilizando a criação de ambientes muito realísticos para os jogos 3D. O fornecedor da Unity 3D mantém um sistema para obtenção de Assets denominado Asset Store, o qual pode ser acessado pelo navegador pelo site da Unity, ou a partir da própria engine por Window >> Asset Store, ou CTRL + 9. Muitos componentes são gratuitos, mas também existem Assets pagos, constituindo inclusive um mercado muito interessante para desenvolvedores de jogos. Em termos de jogos 3D, as representações mais comuns para o jogador são a primeira e a terceira pessoa, e a Unity 3D fornece Assets prontos para os dois modos, devendo apenas ser acrescentado o pacote correto ao projeto e utilizado o controlador adequado. Para a utilização da representação em primeira pessoa no Unity, o caminho mais simples é a utilização de PFPSController, um elemento pré-fabricado (Prefab) presente no pacote Characters. Todo pacote, ou Asset Package, pode ser selecionado na criação do projeto ou adicionado por Assets >> Import Package >> [Pacote]. DESENVOLVIMENTO DE JOGOS MOBILE 13 Com FPSController disponível na área de Assets do Projeto, basta arrastá-lo para a Scene View e ativar a visão de Game Play para experimentar os típicos movimentos dos jogos de tiro no ambiente 3D. Oura característica interessante da Unity 3D é o Sistema de Partículas, utilizado na construção dos mais diversos efeitos, como fumaça, fogo, neve, elementos líquidos, e muitos outros. Com a utilização da Unity é bastante simples criar e configurar um sistema de partículas a partir do início, no entanto, existem vários efeitos já configurados, no formato de PreFab, disponíveis para utilização por Assets >> Import Package >>ParticleSystems. Tão simples quanto trabalhar com a primeira pessoa é trabalhar na terceira pessoa. Certamente a definição de um personagem em terceira pessoa exigirá alguma modelagem 3D, mas ThirdPersonController já está disponível no pacote DESENVOLVIMENTO DE JOGOS MOBILE 14 Characters e precisa apenas ser arrastado para a cena, assumindo a malha padrão para testes. A câmera deve ser posicionada corretamente para visualizar o personagem, e as dimensões corrigidas para a cena, e ao acionar Game Play, podem ser utilizados os comandos de controle comuns de jogos 3D. Unity traz boas ferramentas para a criação da interface de usuário, aqui se tratando de menus e avisos, entre outros elementos de interação e HUD. Os componentes para construção de GUI incluem: Painéis, Botões, Textos e Imagens, Campos de Entrada e Sistema de Eventos. Outra ferramenta muito interessante do Unity é o modelador de árvores, o qual permite criar os mais diversos tipos de árvores e arbustos com grande facilidade. Uma árvore configurada pode ser reutilizada em toda a cena, e pode conter aspectos aleatórios que irão denotar uma individualização de cada instância utilizada. DESENVOLVIMENTO DE JOGOS MOBILE 15 O uso da linguagem C# permite a criação de novos Assets e a modificação dos comportamentos da Engine, visando a especificidade para cada jogo. A classe básica de comunicação entre Unity e C# é a MonoBehaviour, e devemos estendê-la para adaptar a engine às necessidades de um novo jogo. Embora possa ser utilizada também a linguagem Java Script, a linguagem C# tem obtido a preferência dos desenvolvedores que utilizam a Engine. Linguagem C# A linguagem de programação C# é multiparadigma, fortemente tipada, e inclui paradigmas de programação imperativa, funcional, declarativa, orientada a objetos e genérica. Foi desenvolvida pela Microsoft como parte da plataforma dotNET, e como nas demais linguagens dessa plataforma, o código fonte é compilado para Common Intermediate Language (CIL) que é interpretado pela máquina virtual do dotNET, a Common Language Runtime (CLR). DESENVOLVIMENTO DE JOGOS MOBILE 16 A linguagem C# é orientada a objetos, o que faz com que tenha uma pequena quantidade de tipos nativos, como ocorre no Java, por exemplo. Para cada tipo nativo do C# existe uma classe Wrapper dotNet capaz de registrar os mesmos tipos de valores do nativo relacionado. Tipo Nativo Classe Limites e Observações byte Byte 0 a 255 sbyte Sbyte -128 a 127 int Int32 -2.147.483.648 a 2.147.483.647 uint UInt32 0 a 4.294.967.295 short Int16 -32.768 a 32.767 ushort UInt16 0 a 65.535 long Int64 -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 ulong UInt64 0 a 18.446.744.073.709.551.615 float Single -3,402E38 a 3,402E38 double Double -1,797E308 a 1,797E308 Char Char Símbolos Unicode de texto. Bool Boolean True ou False Object Object Base para os demais tipos. String String Cadeia de caracteres. Decimal Decimal Números precisos, permitindo até 29 dígitos significativos. Além dos operadores matemáticos (multiplicação, divisão, resto, soma e subtração), comuns a praticamente todas as linguagens, o C# apresenta operadores binários e DESENVOLVIMENTO DE JOGOS MOBILE 17 condicionais próximos aos da linguagem C, assim como operadores próprios, bem mais específicos. Para a comparação estão disponíveis os operadores: > Maior que < Menor que >= Maior ou Igual <= Menor ou Igual == Igualdade != Diferença Os operadores lógicos e binários são utilizados nas operações mais básicas da programação, como na combinação de condições para execução de algum processo, por exemplo. C1 C2 C1 && C2 C1 || C2 false false false false false true false true true false false true true true true true b1 b2 b1 & b2 b1 | b2 b1 ^b2 0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 1 1 0 DESENVOLVIMENTO DE JOGOS MOBILE 18 Para compreender a sintaxe C# é necessário conhecer as diversas estruturas de controle de fluxo existentes em qualquer linguagem, de forma a efetuar tomada de decisões e controle de repetições. A estrutura condicional de maior relevância para as mais diversas linguagens é SE..ENTÃO..SENÃO. Na linguagem C# não existe a palavra SENÃO (then), o que obriga a utilização de parênteses. int a, b, c; // Operações diversas sobre as variáveis... if ( ( a > b ) && ( a > c ) ) Console.WriteLine ("A tem o maior valor"); else if ( b > c ) Console.WriteLine("B tem o maior valor"); else Console.WriteLine("C tem o maior valor"); O uso de operador de decisão pode ser uma grande alternativa ao SE..ENTÃO..SENÃO em determinada condição de uso, a qual pode ser definida como: uma variável recebe dois valores distintos a partir do resultado de um condicional. if ( a > b ) c = 2; else c = ( a > b ) ? 2 : 5; c = 5; Quanto ao controle de iterações, a estrutura de repetição mais simples seria ENQUANTO..FAÇA. int a = 1; DESENVOLVIMENTO DE JOGOS MOBILE 19 while ( a <= 256 ) { Console.WriteLine( a ); a = a * 2; } Uma estrutura similar ao ENQUANTO..FAÇA, com a diferença funcional de sempre executar ao menos uma vez seria a estrutura FAÇA..ENQUANTO. int a = 1; do { Console.WriteLine( a ); a = a * 2; } while ( a <= 256 ); A estrutura mais complexa seria a PARA..FAÇA. Nas linguagens derivadas do C, como o C#, essa instrução apresenta muito mais opções que em linguagens mais próximas do algoritmo, como Pascal e Fortran. A forma geral seria for (<inicialização> ; <teste> ; <incremento>), sendo as seções de inicialização e incremento aceitam mais de uma instrução, e qualquer seção pode ser omitida. for ( int i = 1 ; i <= 10 ; i++ ) Console.WriteLine( i ); A conversão de tipo, ou type cast, faz com que o C# reinterprete um determinado tipo em situações específicas. Essa é uma técnica muito utilizada na orientação a objetos quando precisamos acessar um atributo específico de um descendente utilizado no lugar da classe inicial. float f; int a = 5, b = 2; f = a / b; // f recebe 2.0 f = a / (float) b; // f recebe 2.5 DESENVOLVIMENTO DE JOGOS MOBILE 20 f = ((float) a) / b; // f recebe 2.5 Na sintaxe C#, uma classe é definida pela palavra class, devendo ser observado o namespace utilizado. Para a definição de seus atributos e métodos, os níveis de acesso disponíveis são: public, private e protected. O método construtor deve ter o mesmo nome da classe, enquanto destrutores assumem um símbolo ~ antes do nome. // Classe com dois construtores sobrecarregados public class Pessoa { public string nome; public Pessoa() { nome = "desconhecido"; } public Pessoa(string nm) { nome = nm; } } Uma propriedade define um atributo com acesso controlado, e utiliza escritores e leitores pelas palavras set e get. public class Livro { private Pessoa pAutor = null; public Pessoa Autor { get { return pAutor; } set { pAutor = value; } DESENVOLVIMENTO DE JOGOS MOBILE 21 } } Os métodos da linguagem permitem a definição de argumentos opcionais e chamadas com argumentos nomeados. Argumentos opcionais são aqueles que apresentam um valor inicial default, podendo ser omitidos na chamada do método, e o uso dechamadas com argumentos nomeados permite que não haja preocupação com a ordem dos parâmetros nessas chamadas específicas. public void Exemplo(int id, string nome = "desconhecido", int idade = 18) { // Método com parâmetros opcionais } Exemplo( 123 ); Exemplo( nome: "Ana", id: 352); Exemplo( 478, "Carlos" ); Para a implementação de herança deve ocorrer uma referência ao ascendente por :Ascendente. Os construtores herdados, e demais elementos da superclasse, são referenciados pela palavra base, enquanto a palavra this resolve o conflito de nomes na própria classe. // Herança com chamada ao construtor da superclasse public class Profissional: Pessoa { public string profissao; public Profissional(string nome, string profissao) : base(nome) { this.profissao = profissao; } } DESENVOLVIMENTO DE JOGOS MOBILE 22 Para implementar polimorfismo em classes concretas é necessário utilizar virtual e override. public class Pessoa { public string nome; public virtual void Exibir( ) { Console.WriteLine("Nome: {0}", nome); } } public class Profissional: Pessoa { public string profissao; public override void Exibir( ) { base.Exibir( ); Console.WriteLine("Profissao: {0}", profissao); } } Na programação moderna não basta definir classes, mas também é necessário modelar comportamentos. A modelagem comportamental traz grande sustentação às diversas estruturas de dados e vários padrões de desenvolvimento, e uma das formas de modelar um comportamento é mediante o uso de classes genéricas. Na programação estruturada os arrays são a maneira mais comum para utilização de dados contíguos na memória, porém apresentam dimensão fixada na criação, o que se torna um grande limitador. Em termos de orientação a objetos, as coleções são mais interessantes, pois trabalham como listas encadeadas, permitindo a variação de tamanho após a criação. Essas coleções trabalham com classes genéricas e permitem a utilização de comandos específicos, como o foreach. DESENVOLVIMENTO DE JOGOS MOBILE 23 // Exemplo de uso de coleção do tipo List<int> List<int> lista = new List<int>( ); lista.Add(1); lista.Add(4); foreach( int numero in lista ) Console.WriteLine("Numero: {0}", numero); // No caso do ArrayList, ele trabalha com Object ArrayList colecao = new ArrayList( ); colecao.Add(2); colecao.Add(4); int[ ] valores = ( int[ ] ) colecao. ToArray( typeof( string ) ); Outra forma de implementar comportamentos é por anotações, as quais são metadados anexados ao código, e que podem mudar por completo o comportamento original da classe, ou outra estrutura anotada, a partir de ferramentas externas. Um ótimo exemplo de uso de anotações em C# é na criação de Web Services, ferramental de grande utilidade para a criação de serviços interoperáveis na Web. [WebService(Namespace= "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () { } [WebMethod] public string HelloWorld() { return "Hello World"; } } DESENVOLVIMENTO DE JOGOS MOBILE 24 Programar em C# para Unity 3D sempre envolve a criação de um descendente de MonoBehaviour. Os diversos eventos são os pontos de interferência nos comportamentos da Unity, implementados por métodos polimórficos da classe criada. Um jogo é como uma animação, mas onde os quadros de animação são gerados a cada instante, e uma técnica fundamental na sua programação é efetuar mudanças para a posição, comportamento e estado de objetos antes do processamento de cada quadro. O método Update é o lugar correto para esse tipo de código na Unity, pois é chamado antes do processamento da imagem e antes que as animações sejam calculadas. Para adicionar um Script, basta ir no Inspector, com o objeto alvo selecionado, e clicar em Add Component, selecionando New Script, e dando um nome ao script para, em seguida, editá-lo. Uma forma simples de editar o script criado seria a utilização da opção "Sync Mono Develop", clicando com o botão direito sobre o script no painel de Assets. DESENVOLVIMENTO DE JOGOS MOBILE 25 Matemática para Jogos O uso de matemática é inerente ao próprio processo de programação, podendo ser encontrada em diferentes formas para diferentes áreas do desenvolvimento. Inicialmente, a lógica booleana define a base do processo de construção de algoritmos e programação em si, enquanto álgebra relacional e cálculo relacional justificam toda a funcionalidade dos bancos de dados relacionais da atualidade. As atuais tecnologias de Big Data trabalham com processos denominados Map Reduce, baseados em procedimentos estatísticos extremamente formais, e vários sistemas de otimização, para áreas como logística, envolvem programação linear. Enfim, a matemática está em todo lugar, nas mais diversas áreas de programação, mas nos jogos ela se tornará ainda mais relevante. Como a maior parte dos jogos envolve elementos gráficos, o uso de geometria descritiva e álgebra linear tornam-se evidentes na construção dos jogos. Criado por René Descartes no intuito de localizar pontos em um determinado espaço, o plano cartesiano consiste de dois eixos perpendiculares, sendo o horizontal chamado de eixo das abscissas e o vertical de eixo das ordenadas. Todo ponto é representado em termos de coordenadas (x,y), as quais não coincidem com o sistema de coordenadas para a definição dos pixels na tela de um computador. No computador a origem fica no canto superior esquerdo, e o eixo y aumenta de valor no sentido Sul, o que exige pequenas transformações para a correta exibição das mais diversas funções matemáticas. DESENVOLVIMENTO DE JOGOS MOBILE 26 Vetores podem ser considerados como uma lista de números, a qual permite ser expressa de forma horizontal ou vertical. Em termos de sistemas de coordenadas, um ponto 2D pode ser representado por um vetor colunar de duas linhas, assim como um ponto 3D pode ser expresso por três linhas. Um vetor pode ser interpretado geometricamente como um segmento de reta orientado, contendo uma magnitude e uma direção, e a sua dimensão determina quantos números são expressos por esse vetor. Por exemplo, um vetor 2D definido pelo ponto (x,y) = (3,4), em relação à origem, apresenta magnitude 5 e direção de 53°. Para o cálculo da magnitude, basta utilizar o Teorema de Pitágoras, e para a direção pode ser utilizado o arco-tangente, arco- seno ou arco-cosseno, considerando o eixo x como a linha do cosseno e o eixo y como a linha do seno. arctan( 4 / 3 ) = 53,13° Unity permite representar vetores 2D, 3D e 4D com grande facilidade, e as classes que representam os vetores ainda trazem métodos específicos para normalização, magnitude etc. As classes em questão são: Vector2, Vector3 e Vector4. DESENVOLVIMENTO DE JOGOS MOBILE 27 float f; f = Vector2.Distance(new Vector2(1,3), new Vector2(0,1)); Vector3 v3 = new Vector3(4,5,0); float a = v3.x; Várias operações podem ser efetuadas sobre os vetores, destacando-se algumas operações de interesse direto para a área de jogos, como rotação, translação e escala, aplicáveis diretamente aos ambientes 2D e 3D. Multiplicação por escalar terá relação com as operações de mudança de escala para os vetores. [ ax, ay ] k = k [ ax, ay ] = [ k * ax , k * ay ] A Soma Vetorial é uma operação que pode representar um movimento de translação. [ ax , ay ] + [ bx , by ] = [ ax + bx , ay + by ] DESENVOLVIMENTO DE JOGOS MOBILE 28 As operações de Produto Escalar e Produto Vetorial permitem o reconhecimento do ângulo formado entre dois vetores. No Produto Escalar, o resultado da multiplicação é um escalar. [ ax , ay ] . [ bx , by ] = axbx + ayby = ||a|| ||b|| cos ( ângulo ) || w || = magnitude do vetor w No Produto Vetorial, o resultado será outro vetor. [ ax,ay,az ] x [ bx,by,bz ] = [ aybz - azby , azbx - axbz , axby – aybx ] || a x b || = ||a|| ||b|| sen (ângulo) Matrizes também são de grande interesse para a área de jogos e computação gráfica em geral, tratando de tabelas com linhas e colunas de dados. Uma matriz quadrada é aquela que tem a mesma dimensão para linhas e colunas, e os elementos diagonais são aqueles com mesmo índice de linha e coluna. Em geral, uma matriz de transformação M quadrada pode descrever qualquer transformação linear. DESENVOLVIMENTO DE JOGOS MOBILE 29 Multiplicar um vetor de posição por uma matriz M, preenchida de forma adequada, é a forma mais efetivar de executar transformações como a escala, a rotação e a translação. Algumas matrizes derivadas da matriz M de transformação podem expressar a rotação. Normalmente essas matrizes são denominadas matrizes R. Para o caso de duas dimensões é bastante simples, pois a rotação ocorre apenas em torno da origem, mas, ao trabalhar com 3D, será necessário considerar três matrizes de transformação, Rx, Ry e Rz, representando rotações em torno dos eixos x, y e z, respectivamente. A matriz de escalonamento S apresenta os fatores de escala de cada eixo, como kx e ky para o caso 2D, na diagonal, e no caso 3D bastaria acrescentar o fator kz. Provavelmente a escala é uma das operações mais simples entre as diversas transformações lineares. DESENVOLVIMENTO DE JOGOS MOBILE 30 Para efetuar a translação é mais fácil utilizar uma dimensão a mais, ou seja, para a translação 3D seria utilizada uma matriz M de 4x4. Para sua utilização será necessário também a transformação do vetor 3D em vetor 4D pelo acréscimo de um elemento unitário. A escala pode ser feita na mesma operação, bastando preencher os elementos da diagonal com os fatores de escala desejados (kx, ky e kz). As transformações de Euler representam as rotações em termos de 3 rotações simultâneas perpendiculares aos eixos (x, y e z), enquanto os Quaternions são outra forma de representar essas rotações. O nome quaternion é muito citado na literatura de jogos, e trata de uma forma de representar uma orientação com o uso de quatro números. Uma forte razão para o DESENVOLVIMENTO DE JOGOS MOBILE 31 uso de quaternions na área de animação e jogos é a possibilidade de utilizar uma operação denominada slerp (Spherical Linear Interpolation), que permite interpolações mais suaves que os ângulos de Euler. As vantagens de utilizar quaternions para posicionamento angular incluem a interpolação suave, bem como a rápida concatenação e inversão de posicionamentos. O uso de quaternions também traz algumas desvantagens, como a representação levemente maior que a de Euler, possibilidade de se tornarem inválidos devido aos dados de entrada, e o fato de serem um pouco mais complexos em termos matemáticos. As classes de vetores da Unity 3D já apresentam operações como soma, produto vetorial e escalar, entre vários outros, e as classes Transform e Matrix4x4 permitem a realização das diversas operações de escala, rotação e translação. Vector3[ ] origVerts, newVerts; void Update() { Quaternion rotation = Quaternion.Euler( eulerAngles.x, eulerAngles.y, eulerAngles.z); DESENVOLVIMENTO DE JOGOS MOBILE 32 Matrix4x4 m = Matrix4x4.identity; m.SetTRS(translation, rotation, scale); int i = 0; while (i < origVerts.Length) { newVerts[i] = m.MultiplyPoint3x4(origVerts[i]); i++; } mf.mesh.vertices = newVerts; } A maior parte dos jogos explora de uma forma mais intensa a álgebra linear, devido à parte gráfica envolvida, o que não significa que outras áreas da matemática se tornem desnecessárias, como no caso do uso de probabilidade e estatística em "jogos de azar". Física para Jogos Os cálculos da física também são de grande relevância para a criação de jogos. Efeitos como gravidade, vento, atrito, entre vários outros, irão mudar o comportamento de diversos elementos presentes nos jogos 2D e 3D. Inicialmente, para entender as relações de ordem física entre os elementos de jogo, devemos entender o conceito e utilização da colisão. Tanto em jogos 2D quanto em jogos 3D, a colisão é quase sempre o principal elemento funcional, pois: Como saber que um tiro atingiu uma nave? Como impedir que uma parede seja atravessada? Como evitar que os objetos caiam indefinidamente? Esses são apenas alguns exemplos, mas ilustram um pouco a importância de definir técnicas para identificar o momento e o espaço onde ocorre o contato (colisão) entre dois ou mais elementos do jogo. DESENVOLVIMENTO DE JOGOS MOBILE 33 As técnicas para detecção de colisão surgiram ainda nos jogos 2D mais antigos, sendo algumas delas utilizadas até hoje, a exemplo da Bounding-Box. O princípio dessa técnica é a determinação de uma área retangular invisível que envolva cada Sprite, reduzindo o problema ao simples teste da superposição dessas áreas. Essa técnica apresenta uma performance muito boa devido ao baixo números de contas e de verificações, mas, como ela testa colisões entre retângulos, em figuras muito curvas e disformes pode não apresentar um resultado satisfatório. Além da colisão, o principal elemento representativo da física nos jogos é a força. A gravidade, por exemplo, funcionará aplicando uma aceleração negativa de valor constante aos objetos no eixo y. No entanto, as forças não atuam sobre todos os elementos da cena, sendo normalmente aplicadas apenas aos corpos rígidos relacionados com elas de acordo com os parâmetros adotados pelo jogo. DESENVOLVIMENTO DE JOGOS MOBILE 34 Corpos rígidos apresentam características como: posição, velocidade, densidade, massa, rotação, velocidade angular, entre várias outras. Força e torque podem ser adicionados a um corpo rígido, modificando algumas de suas características originais. Por exemplo, se um corpo está apoiado em uma superfície sem inclinação e com atrito, e sob a ação da gravidade, ele estará inicialmente com velocidade zero, mas recebendo uma força horizontal capaz de quebrar a resistência desse atrito irá iniciar uma aceleração, modificando sua velocidade original. Nesse contexto, algumas definições básicas da física se tornam necessárias: Velocidade é medida a partir da variação da distância sobre a variação do tempo, e assumindo unidades como Km/h ou m/s. Aceleração é definida pela variação da velocidade em relação ao tempo, assume unidades como Km/h² ou m/s². A massa é medida em unidades como Kg ou g, podendo estar sujeita à ação da gravidade, definindo a força peso (P=m.g), sendo normalmente utilizada a unidade Kg.m/s², ou simplesmente Newton (N). Materiais distintos podem ser mais ásperos ou maislisos, apresentar diferentes densidades, além de outras características físico-químicas capazes de interferir diretamente nos cálculos físicos. DESENVOLVIMENTO DE JOGOS MOBILE 35 O ferramental da Unity 3D para aplicação de física nos jogos é muito vasto, a começar pelo suporte à colisão. Pela engine é possível utilizar uma grande gama de estratégias de detecção sem qualquer tipo de aprofundamento matemático, sendo as áreas (2D) e volumes (3D) de detecção denominadas colisores. Embora a metodologia seja sempre a mesma, as fórmulas de cálculo para outros formatos de áreas de colisão podem se tornar bastante complexas. Exemplos típicos de áreas e volumes de colisão são círculos, no modelo 2D, esferas e cápsulas, no modelo 3D. É possível testar todos os vértices de um polígono ou de uma malha, mas o gasto computacional envolvido pode não trazer tantos benefícios assim. Mesmo sem a necessidade de efetuar complexas implementações de colisores, devido ao suporte oferecido pela Unity 3D, é interessante observar os impactos para o jogo na escolha de colisores mais ou menos complexos, pois o aumento demasiado da quantidade de cálculos efetuados poderá trazer efeitos catastróficos para a fluidez no momento de execução. Inicialmente a Unity 3D apresenta colisores 3D, pela própria natureza da Engine, sendo mais utilizados os colisores Box Collider, Sphere Collider e Capsule Collider. Em situações de maior detalhamento pode ser utilizado o Mesh Collider, e outro colisor importante é aquele utilizado na criação de terrenos, o Terrain Collider. DESENVOLVIMENTO DE JOGOS MOBILE 36 Da mesma forma que são oferecidos colisores 3D, são oferecidos colisores 2D, aplicáveis aos Sprites e demais elementos 2D. Os colisores mais utilizados são Circle Collider 2D e Box Collider 2D, e para elementos mais detalhados pode ser utilizado o Polygon Collider 2D. A criação de um cenário simples, com um box (BoxCollider), quatro esferas posicionadas sobre o box (SphereCollider) e um controlador em terceira pessoa (CapsuleCollider), com o correto posicionamento de câmera, já seria suficiente para observar o efeito da colisão, já que o personagem não consegue atravessar as esferas. DESENVOLVIMENTO DE JOGOS MOBILE 37 Se o objetivo não for o bloqueio, podemos controlar o efeito da colisão através da programação do evento onCollisionEnter. O Script C# abaixo pode ser aplicado às esferas para que sumam quando tocadas. public class SelfDestruct : MonoBehaviour { void OnCollisionEnter(Collision collision) { DestroyObject (gameObject); } } Outro elemento interessante na física do Unity3D são as junções entre objetos, como na simulação de dobradiças (Hinge Joint) e molas (Spring Joint). Da mesma forma que existem junções 3D, existem as junções 2D, como Hinge Joint 2D. Quanto aos corpos rígidos, a Unity 3D oferece suporte simples, pelo acréscimo de um Rigidbody ou Rigidbody2D. Um exemplo típico de utilização da gravidade DESENVOLVIMENTO DE JOGOS MOBILE 38 encontra-se no controlador em terceira pessoa, no qual é utilizado um RigidBody com a opção Use Gravity marcada. Inteligência Artificial Os dicionários consideram inteligência como a capacidade de aprender, compreender e adaptar-se às situações que se apresentarem. Os modelos de Inteligência Artificial (AI, do inglês Artificial Intelligence) são aqueles cuja programação visa simular ações de inteligência similares às humanas, mas em meio computacional. Em termos computacionais, existem duas grandes áreas abordadas pela inteligência artificial: aprendizado automatizado, ou machine learning, e tomada de decisão. Essas duas grandes áreas podem ser combinadas, de forma a transmitir a característica de adaptação baseada em memórias (ações ou dados), ou podem atuar de forma totalmente independente. Hoje em dia existem várias vertentes para a implementação de inteligência artificial, tais como: Redes Neurais, Lógica Fuzzy e Algoritmos Genéticos. Normalmente essas diversas técnicas visam o aprendizado para tomada de decisão. DESENVOLVIMENTO DE JOGOS MOBILE 39 Um termo comum utilizado nesse campo da inteligência artificial é a heurística, uma regra adotada para a busca de soluções ou decisões. Uma Rede Neural Artificial (RNA) é composta por várias unidades de processamento, cujo funcionamento é bastante simples. Essas unidades geralmente são conectadas por canais de comunicação que estão associados a determinado peso. As unidades fazem operações apenas sobre seus dados locais, que são entradas recebidas pelas conexões. O comportamento inteligente de uma RNA vem das interações entre as unidades de processamento da rede, cujas saídas funcionam como entradas para outras unidades, assim como ocorre nos neurônios físicos. O uso de Lógica Fuzzy permite a utilização de valores intermediários entre o falso e verdadeiro da lógica booleana. A ideia básica por trás do Fuzzy é a simulação da percepção de valor humana, onde os elementos não são apenas verdadeiros ou falsos, mas apresentam percentuais de aceitação para as mais diversas situações. DESENVOLVIMENTO DE JOGOS MOBILE 40 Com relação aos Algoritmos Genéticos, estes se baseiam nas combinações entre genes e utilização de mutações, baseando-se na Teoria Evolucionista de Darwin. Esse tipo de algoritmo utiliza heurísticas de avaliação e combinação de soluções parciais, de forma a otimizar soluções completas, segundo princípios evolucionistas. O método mais comum para a escolha de indivíduos para cruzamento (combinação) é a roleta de seleção, a qual aumenta a probabilidade de escolha dos indivíduos mais adaptáveis, segundo uma função de avaliação. Qualquer jogo que envolva movimentos do computador, dispositivo móvel, console, ou outro além do jogador, deverá adotar regras heurísticas para a ação dos personagens. Em jogos como Xadrez e Pôquer, por exemplo, as diversas heurísticas tomam como base o conhecimento prévio de estratégias, análise estatística e árvores de decisão. As árvores de decisão buscam criar todos os cenários decorrentes de cada ação do usuário no formato de uma máquina de estados hierarquizada, o que exige a aplicação de algoritmos gulosos, classificados como força-bruta, para a determinação de todas as possibilidades e recorrente adoção da mais favorável. DESENVOLVIMENTO DE JOGOS MOBILE 41 Duas situações podem ocorrer decorrentes da aplicação de algoritmos gulosos na formação de árvores de decisão: demora na combinação de espaços maiores, e jogos impossíveis de ganhar. Para evitar essas situações, podem ser utilizadas heurísticas para a formação da árvore, as quais não tratarão de todo o espectro combinatorial de um algoritmo guloso, mas trarão resultados com níveis de qualidade e dificuldade adequados à garantia da jogabilidade. Sistemas baseados em regras são outra solução na automatização do comportamento de personagens. Basicamente é aplicado um conjunto de regras, no formato "se... então... senão...", e as decisões são tomadas a partir dos dados de entrada. No contexto da inteligência artificial, os agentes inteligentes são programas com controle autônomo, e que são capazes de perceber o ambiente e se adaptarem às mudanças. Sistemas multiagentes são aqueles que utilizam esses agentes de forma colaborativa, quer seja para operações em jogos de campanha quer seja para acrescentar certo nível de inteligênciaao comportamento dos inimigos. DESENVOLVIMENTO DE JOGOS MOBILE 42 As Máquinas de Estados Finitos, também denominadas FSM, do inglês Finite State Machine, são utilizadas para a formalização de sistemas de eventos discretos, sendo amplamente aplicáveis aos jogos. Basicamente tratam de uma representação de estados do objeto, as transações possíveis entre estados, bem como os estímulos e condições associados às transações. Para jogos que envolvem personagens animados, naves, tiros, e demais elementos autônomos, é comum o uso de heurísticas de busca para a localização do jogador e tomada de decisão acerca de movimentação, defesa e ataque. Navegação, ou Pathfinding, é uma das aplicações mais comuns de inteligência artificial em jogos eletrônicos. De fato, a construção de um mundo virtual habitado por DESENVOLVIMENTO DE JOGOS MOBILE 43 agentes autônomos que se movem em busca de algum objetivo, como a caça ao jogador, requer a introdução de mecanismos que suportem essa navegação. Um sistema de regras para cada agente fará com que siga o caminho livre que mais o aproxima do jogador, e estando em posição adequada, este pode entrar em modo de combate, segundo a máquina de estados (FSM). Um modelo muito interessante de Pathfinding é fornecido pela Unity 3D, o qual é chamado de Navigation Mesh, ou simplesmente NavMesh. Esse sistema permite a criação de uma área de movimentação e busca aproveitando o próprio formato da malha de cenário. O sistema Navigation Mesh é composto de: NavMesh - superfície sobre a qual os personagens podem se locomover, podendo ser extraída da própria geometria do cenário. NavMesh Agent - define personagens que reconhecem uns aos outros, ou aos obstáculos, e perseguem objetivos sobre o NavMesh. Off-Mesh Link - permite atalhos entre dois pontos do NavMesh, voltado para saltos e ações especiais. NavMesh Obstacle - permite a definição de obstáculos móveis para os agentes. DESENVOLVIMENTO DE JOGOS MOBILE 44 Para criar um NavMesh é necessário apenas a utilização das funcionalidades do painel Navigation. Os elementos do cenário a serem incluídos na navegação devem ser marcados como Navigation Static, configurações mais específicas na opção Bake, e para gerar a NavMesh deve ser utilizado o botão também com o nome Bake. Como passos seguintes, podem ser adicionados um Game Object, como um cilindro, configurado como NavMeshAgent, sendo adotada a programação adequada. public Tranform alvo; void Update ( ) { NavMeshAgent agente = GetComponent<NavMeshAgent> ( ); agente.destination = alvo.position; } DESENVOLVIMENTO DE JOGOS MOBILE 45 Adicionando um controlador de terceira pessoa e ajustando a propriedade alvo de MoveTo, associado ao NavMeshAgent, este irá perseguir o jogador pelo caminho definido. Geração Procedural Geração Procedural em jogos corresponde à adoção de um conjunto de algoritmos, utilizados como um ferramental para criar grandes quantidades de conteúdo em arquivos de tamanhos mínimos. Essa técnica não é nova, pois os jogos mais antigos, limitados à baixa capacidade computacional e de pouco espaço de armazenamento da época, precisavam criar elementos dinamicamente para melhor aproveitamento do hardware. O princípio matemático que serve de base para a geração procedural é a aleatoriedade numérica, determinada por uma semente de geração e uma distribuição probabilística. As gerações pseudoaleatórias permitem a repetição de um cenário ou simulação quando é utilizada a mesma semente no processo de geração. As formas mais comuns de geração procedural são o modelo matricial e uso de fractais. Em jogos 2D de visão superior, os mapas podem ser obtidos como a combinação de figuras menores de forma matricial, e alguns exemplos típicos disso são jogos de corrida infinitos, jogos de campanha, bullet hell e RPG de visão superior. DESENVOLVIMENTO DE JOGOS MOBILE 46 É fácil observar nesses jogos a repetição de elementos ao longo das cenas. Com o uso de poucos recursos de mídia, combinados de diferentes formas, em alguns momentos de forma aleatória, em outros configurados por listas de valores, é possível diminuir muito o tamanho total do jogo, ou as necessidades de transmissão em rede. Nos jogos de bullet hell o uso de aleatoriedade controlada pode trazer um desafio maior para o jogador, pois ele não será capaz de prever movimentos inimigos. Jogos como Minecraft e Spore utilizam a geração procedural para criar imensos mundos 3D, permitindo aos jogadores experiências inéditas a cada novo cenário gerado. O tipo de geração do Minecraft chama-se "Ruído de Perlin", um algoritmo utilizado na geração de texturas, mas que se popularizou na criação de terrenos em jogos. Esse tipo de algoritmo trabalha com elementos fractais para a geração do "ruído", ou área de instabilidade, o que traz informações para a geração de terrenos de forma simples e muito eficiente. Para a geração de um cenário de forma dinâmica devem ser consideradas as diferentes alturas nos diversos pontos, assumindo transações suaves na malha, o que pode ser obtido com a construção de um mapa de altura. Na área da computação gráfica um mapa de altura é uma imagem bidimensional utilizada para armazenar valores relativos à elevação de uma superfície, para a exibição como gráficos tridimensionais. DESENVOLVIMENTO DE JOGOS MOBILE 47 Para geração de superfícies com Unity 3D pode ser utilizado o método estático Mathf.PerlinNoise, onde os parâmetros utilizados (a,b) denotam o deslocamento dentro do fractal. Com a escolha de uma área do fractal, a partir de um ponto fornecido, é obtido um conjunto de valores (ruído) com boa aleatoriedade no conjunto global, e bastante suavidade nas transições, o que viabiliza a repetição do cenário através da repetição da origem, além de apresentar superfícies consistentes e sem quebras bruscas. public float xorig = 0.0f; public float zorig = 0.0f; public GameObject bloco01; void GerarTerreno(){ GameObject gobj = null; for(x=0;x<30;x++){ for(z=0;z<30;z++){ y = (int)(Mathf.PerlinNoise( (x+xorig)*10/300.0f,(z+zorig)*10/300.0f)*11); gobj = (GameObject)Instantiate(bloco01, new Vector3(x,y,z),Quaternion.identity); MeshRenderer mr = gobj.GetComponent<MeshRenderer>(); mr.material.color = new Color(y/11.0f,y/11.0f,1.0f,0.5f); DESENVOLVIMENTO DE JOGOS MOBILE 48 } } } No código anterior, xorig e zorig denotam o deslocamento desejado no fractal, segundo uma área de cobertura que varia de 0 a 29 em x e z. Como o fractal retornará um valor entre 0 e 1, ele deverá ser multiplicado pela altura máxima desejada (11). Com MeshRenderer e uso da propriedade material é possível alterar a cor de acordo com a altura gerada, seguindo o padrão RGB-Alpha. Esse código pode ser adaptado para gerar qualquer terreno 3D com grande facilidade, mas um cuidado que deve ser tomado é o de não aplicar o script ao objeto a ser replicado, pois traria ao jogo um problema de recursividade infinita. Elementos mais independentes podem ser utilizados, por exemplo, a Main Camera, artifício bastante utilizado em muitos jogos que precisam de algum tipo de configuração inicial de ambiente. Poderia também ser criado um Game Object do tipo Empty. Devem ser configurados no Inspector os valoresde xorig e zorig, bem como associar bloco01 ao objeto que será replicado, o que teria o resultado observável a seguir, se GerarTerreno for chamado no Start do script. DESENVOLVIMENTO DE JOGOS MOBILE 49 Uma forma bastante simplória de geração procedural seria com o uso de Random. Por exemplo, um jogo similar ao Breakout, mas com os blocos sendo colocados em posições totalmente aleatórias, bem como suas cores, poderia trabalhar diretamente com Random na geração. Isso pode gerar problemas com relação às sobreposições não tratadas, mas a aleatoriedade poderia ser melhor explorada, por outro lado, na concessão de bônus, vida extra, e demais elementos especiais. Interface de Usuário Uma interface pode ser considerada como uma fronteira entre dois sistemas sejam esses eletrônicos, mecânicos ou orgânicos. Exemplos de interfaces de origem eletrônica ou mecânica incluem conectores e barramentos, entre outros. O hardware para entrada de dados, como mouse e teclado, constitui uma interface física com o usuário. Partindo do âmbito físico para o lógico, ou software, este também apresenta necessidade de interação com o usuário (sistema orgânico), por um conjunto de componentes denominado interface de usuário. Como em qualquer plataforma de software, várias ações envolvendo configurações, informações e decisões no decorrer da utilização do jogo irão necessitar de uma interface de usuário padronizada, com elementos já de utilização comum em outros ambientes como, por exemplo, menus e botões. Unity 3D oferece uma API e voltada exclusivamente para a construção de interfaces, bem como ferramentais próprios, e essa API é denominada UI (User Interface). O menu Game Object >> UI dará acesso à criação dos seguintes componentes relacionados com a interface de usuário: Panel, Button, Text, Image, Raw Image, Slider, ScrollBar, Toggle, Input Field, Canvas e Event System. DESENVOLVIMENTO DE JOGOS MOBILE 50 Todo componente visual do tipo UI está associado a um Canvas, ou área de desenho, o qual pode ser utilizado com três referenciais distintos, através do Render Mode: Screen Space – Overlay apresenta a interface no topo da tela, ou seja, na camada de topo do ambiente 2D. Screen Space – Camera posiciona a interface em relação a uma câmera, de forma fixa, acompanhando a visão do jogador em primeira pessoa. World Space faz com que a interface seja integrada ao espaço do ambiente 3D, constituindo parte do cenário. Além de transformações comuns, como a rotação padrão, os componentes UI apresentam um sistema de âncoras para redimensionamento dinâmico, permitindo manter o mesmo aspecto em dispositivos distintos. A ferramenta Rect Transform permite a configuração desse tipo de comportamento. DESENVOLVIMENTO DE JOGOS MOBILE 51 A configuração dos componentes UI, no editor do Unity, é feita de forma mais fácil com a utilização da visualização 2D, a qual permite uma visão frontal das telas. Qualquer componente visual adicionado ao ambiente irá adicionar também o Canvas e o Event System, e a janela Hierarchy será muito útil no processo de criação de interfaces, pois viabilizará acesso rápido para a configuração das diversas propriedades dos componentes no Inspector. A resposta às ações sobre os componentes UI deve ser feita através da programação de resposta a eventos como onClick, para Button, e onValueChanged, para Toggle e Slider. Uma forma simples de responder aos eventos é adicionar os ouvintes corretos através do método AddListener. Um método callback deve ser criado para a resposta, e utilizado como parâmetro de AddListener. private Button btn; void Start () { btn = GetComponent<Button> (); btn.onClick.AddListener(debugClick); } void debugClick () { DESENVOLVIMENTO DE JOGOS MOBILE 52 Debug.Log("Clicado"); } Apenas para exemplificar o uso de botões em uma interface de usuário, um código similar poderia ser criado para que efetuasse a soma dos valores digitados em dois InputFields e o resultado exibido em um componente Text. Para tal, é necessário adicionar atributos públicos de ligação com os game objects necessários, além da implementação do callback responsável pela operação. Há métodos visuais de configuração de eventos, mas eles acabam se tornando mais complexos que a utilização de programação. public class SomaClick : MonoBehaviour { void Start () { GetComponent<Button>().onClick.AddListener(onSomaClick); } public InputField campo1, campo2; public Text resultado; void onSomaClick(){ int a = int.Parse (campo1.text); int b = int.Parse (campo2.text); resultado.text = "A soma de "+a+" e "+b+" vale "+(a+b); } } DESENVOLVIMENTO DE JOGOS MOBILE 53 Em termos visuais, um componente do tipo container é aquele capaz de agrupar outros sobre ele. Ao mover o container, todo o conjunto agrupado é movido junto. O aspecto e funcionalidade dos containers dependerá bastante do tipo de plataforma e do sistema operacional, sendo que o primeiro container de uma interface de usuário típica é a janela, mas podem ser utilizados outros containers internos, como painéis, por exemplo. Ainda existe a possibilidade de se utilizar containers sobrepostos, os quais podem ser alternados através do controle de visibilidade, caracterizando interfaces paginadas. Em termos da Unity 3D, um Panel funciona como container, permitindo organizar os espaços internos do Canvas. Quando um componente UI, como um botão, está ligado a um Panel na estrutura hierárquica, ao mover esse Panel o componente será movido junto, como se fosse uma janela, facilitando muito o tratamento visual do conjunto. DESENVOLVIMENTO DE JOGOS MOBILE 54 Para adicionar componentes UI ao Panel, utilize sempre a janela Hierarchy, clicando com o botão direito sobre o Panel e selecionando o componente UI de sua preferência. Podem ser criados novos elementos Panel, constituindo todo um sistema interativo de janelas. Nesse contexto, uma propriedade muito interessante é o Alpha do Panel, a qual permite a sobreposição de painéis com transparência, o que mantém a informação do anterior, ao mesmo tempo em que utiliza um sofisticado efeito translúcido. A visibilidade de cada Panel pode ser controlada, e as telas podem ser exibidas alternadamente nos momentos de utilização da interface. Para isso, basta habilitar ou desabilitar o Panel, a partir da janela do Inspector ou via programação. DESENVOLVIMENTO DE JOGOS MOBILE 55 Nesse exemplo, com o acréscimo de um Script bastante simples ao botão é possível fazer com que o clique nele torne o segundo painel visível, de forma translúcida e sobreposto ao primeiro. Esse tipo de comportamento é bastante comum em janelas de configuração, pois tendo sido completadas as alterações solicitadas, é importante informar ao jogador que a operação obteve sucesso, ou até mesmo que houve alguma falha. A forma mais simples de relacionar o Script ao segundo painel é com o uso de uma propriedade GameObject, a qual permitirá informar o relacionamento com o objeto do cenário a partir do Inspector. public class ClickConfig : MonoBehaviour { private Button btn; void Start () { btn = GetComponent<Button> (); btn.onClick.AddListener(onClickConfig); } public GameObject pMensagem; void onClickConfig(){pMensagem.SetActive (true); } } DESENVOLVIMENTO DE JOGOS MOBILE 56 As interfaces visuais são muito importantes para a definição de características e opções dos jogos, como nível de dificuldade, ativação de som e música de fundo etc. Também podem ser úteis na escolha de itens e tarefas de caracterização de personagens, essa última opção muito comum em jogos de RPG e de execução de tarefas. Alguns jogos podem ser construídos apenas com o uso dos componentes UI, principalmente os de tabuleiro como, por exemplo, o popular "Jogo da Velha". Imediate Mode GUI (IMGUI) Outra forma de criar interfaces e HUD na engine Unity 3D é com o uso de IMGUI, considerado obsoleto face à nova interface UI, porém ainda utilizado amplamente nas plataformas móveis. Como essa era a forma padrão de criação de interfaces nas versões anteriores da Unity 3D, é comum encontrar diversos exemplos de sua utilização. A vantagem do uso de IMGUI encontra-se no fato de que não há necessidade de configurar qualquer elemento Canvas, posicionamento de câmera, ou outros elementos visuais, constituindo um ambiente totalmente controlado por Script. DESENVOLVIMENTO DE JOGOS MOBILE 57 Essa forma de construção se baseia no evento OnGUI para a criação de diversos objetos GUI. Nesse ambiente, o uso de botões precisa apenas de uma simples estrutura condicional, pois o botão em questão retornará true se for pressionado na ocorrência do evento. void OnGUI() { if (GUILayout.Button("Press Me")) Debug.Log("Hello!"); } Esse método de criação de interfaces pode ser utilizado facilmente na criação de menus. Um exemplo seria a criação de um menu para escolha do nível do jogo. GUI.Box(new Rect(10,10,100,90),"Loader Menu"); if(GUI.Button(new Rect(20,40,80,20), "Level 1")) { Application.LoadLevel(1); } if(GUI.Button(new Rect(20,70,80,20), "Level 2")) { Application.LoadLevel(2); } DESENVOLVIMENTO DE JOGOS MOBILE 58 Ao invés de texto, os botões também aceitam o uso de texturas como ícones. Para isso basta associar o Script a uma textura, por uma propriedade pública do tipo Texture2D, e utilizar o ícone no lugar do texto. public class GUITest : MonoBehaviour { public Texture2D icon; void OnGUI () { if (GUI.Button (new Rect (10,10, 100, 50), icon)) { print ("you clicked the icon"); } } } Vários componentes estão disponíveis na biblioteca IMGUI, sendo alguns deles descritos a seguir: GUI.Label - representação de texto estático. GUI.Button - botão simples. GUI.TextField - apresenta uma caixa de texto. GUI.Toggle - representa valores booleanos. GUI.Toolbar - criação de uma barra de ferramentas. Em algumas situações é necessário detectar mudanças nos objetos do ambiente IMGUI, e isso pode ser feito por GUI.changed. DESENVOLVIMENTO DE JOGOS MOBILE 59 void OnGUI () { selectedToolbar = GUI.Toolbar (new Rect (50, 10, Screen.width - 100, 30), selectedToolbar, toolbarStrings); if (GUI.changed) Debug.Log("Toolbar ativado na opção: "+selectedToolbar); } HUD Em qualquer sistema interativo, a informação deve ser apresentada de uma maneira integrada ao ambiente, e de forma a não atrapalhar o campo de visão do usuário. Informações podem ser textuais, como pontuações e vidas, ou gráficas, como barras de energia e mapas de contexto. A sigla HUD significa Heads up Display, referindo-se a informações dispostas em algum visor, como o capacete dos pilotos de caças, ou simplesmente na tela de um jogo, de forma a guiar o jogador com as informações necessárias ao contexto. Alguns exemplos da literatura traduzem a sigla HUD como Hands up Display, o que não traz nenhum impacto real ao seu significado. A ideia básica é ter a informação disponível na "altura dos olhos", ou no campo de visão, de forma simples e sem atrapalhar a interatividade e visualização do ambiente. DESENVOLVIMENTO DE JOGOS MOBILE 60 Temos exemplos de HUD na vida real e na ficção científica, como os sistemas de auxílio à navegação diversos, projetados na tela de veículos, ou em óculos de realidade alternada, a exemplo do Google Glass. As aparições do personagem "Iron Man", nos filmes da Marvel, exploram de forma muito interessante o conceito, e acabam trazendo uma expectativa para o caminho que tomará o design utilizado para a construção do HUD na atualidade. Nos jogos, esse conceito é antigo, e não precisa chegar à complexidade alcançada por esses exemplos. Com a utilização da Unity é bastante simples criar elementos HUD, por componentes UI ou IMGUI. DESENVOLVIMENTO DE JOGOS MOBILE 61 As informações apresentadas no HUD podem ser bastante heterogêneas, mas algumas se tornaram bastante usuais nos jogos. Energia, ou HP (Health Points) Menus de Contexto Quantidade de Vidas Mini Mapas Tempo Restante (Cronômetro) Velocímetros e Tacômetros Armas e Munições Bússolas e Radares Experiência (XP) Opções Especiais ou Magia (MP) As informações referentes à energia (HP) costumam adotar um padrão de cores, indo de cores mais frias para cores mais quentes. Normalmente é observável como uma barra de progresso, podendo estar presente junto ao jogador e também nos inimigos. Para ambos os lados, a energia chegando a zero costuma impactar no decréscimo de uma vida, e informações como XP e MP costumam adotar o mesmo padrão de exibição. A contagem de quantidade de vidas pode ser representada de forma simplesmente numérica, ou de forma gráfica, como ocorria muitas vezes em jogos Arcade, a exemplo do antigo Galaga. DESENVOLVIMENTO DE JOGOS MOBILE 62 Cronômetros seguem o mesmo tipo de regra, podendo tratar de elementos gráficos ou não, sendo apresentado de forma numérica no jogo Sonic, por exemplo. Elementos como mapas, bússolas e radares são comuns em jogos do tipo FPS, como Counter Strike. Como são elementos auxiliares, é comum a utilização de teclas e controles específicos para ativar e desativar esses recursos por parte do jogador. Nesse mesmo tipo de jogo é crucial também a apresentação da informação acerca de munições e armas disponíveis para utilização. Velocímetros e tacômetros eram utilizados de forma textual nos primeiros jogos de corrida. Com a evolução dos gráficos, eles passaram a ter uma representação visual cada vez mais próxima dos aparelhos reais. Jogos como Need for Speed exploram muito bem a utilização desses elementos de HUD, otimizando a experiência do jogador em meio ao ambiente de corrida virtual. DESENVOLVIMENTO DE JOGOS MOBILE 63 Os componentes UI são de grande utilidade para a criação de HUD na Unity 3D. Um exemplo simples seria a utilização de componentes UI, como o texto estático, para acompanhamento da energia de um ou mais personagens. Normalmente associamos esses indicadores a elementos visuais, através do uso de imagens, e um dos posicionamentos mais simples para a concepção de HUD com componentes UI é o Render Mode do tipo Screen Space – Overlay. Como esse posicionamento a informação se mantém em frente à visão da tela, e basta posicionar os componentes UI em pontos estratégicos que não atrapalhem a visualização central. Apenas para exemplificar o início da construção do HUD, pode ser utilizado um texto simples em um projeto 2D. Esse componente pode ser programado de forma a exibira contagem regressiva de tempo, com a atualização do texto efetuada por programação C#. public class Tempo : MonoBehaviour { DESENVOLVIMENTO DE JOGOS MOBILE 64 public int tempo = 10000; public Text texto; void Update () { tempo--; texto.text = "Agora: " + tempo; } } Esse script deve ser associado ao um objeto de utilização global, como a Main Camera. Associando a propriedade texto do Script ao objeto Text da cena, o resultado final pode ser observado no Game Play. Embora não seja funcional para um jogo real, esse pequeno exemplo demonstra o posicionamento e a programação de um elemento HUD. Exemplos mais complexos e de maior qualidade gráfica podem ser observados nos diversos tutoriais do fabricante da Unity 3D. Ambiente Mobile Um dispositivo móvel caracteriza-se como um "computador" de bolso, normalmente operado por bateria, com uma tela de dimensões pequenas, além de um teclado ou entrada pelo toque direto na tela (touchscreen). Pode ser utilizado como objeto pessoal, ou com finalidade profissional, apresentando como vantagens elementos como a mobilidade, a comunicação facilitada e a versatilidade. DESENVOLVIMENTO DE JOGOS MOBILE 65 A tecnologia móvel já está presente em nosso dia-a-dia de forma corriqueira, expandindo-se agora para níveis ainda mais densos de comunicação através da Internet of Things. Apesar da categoria móvel englobar tablets, TVs inteligentes e diversos outros tipos de aparelhos, SmartPhones foram o produto de melhor absorção pelo mercado. Esses diversos tipos de aparelho são comumente chamados de handheld, e as primeiras versões popularizadas foram os Palm Pilots, dos quais alguns reconheciam a escrita. Atualmente, a maior fatia de mercado de dispositivos móveis é dividida entre o iOS, da Apple, e o Android, da Google. O mercado de Android é particularmente mais fácil de entrar, e devido ao preço e ao fato de ser uma plataforma aberta, abrange uma grande quantidade de consumidores. Nessas plataformas, assim como nas demais plataformas móveis, os jogos se tornaram um mercado de grande relevância, assumindo diversos modelos de negócios. Um grande avanço foi determinado nessas plataformas devido ao barateamento e minimização da tecnologia de sensores. Qualquer SmartPhone atual trabalha com giroscópio, GPS, acelerômetro, fora a tela de toque em si, e a possibilidade do uso de câmeras. Exemplo que explora bem esses recursos é o jogo Pokemon Go. DESENVOLVIMENTO DE JOGOS MOBILE 66 Unity 3D oferece um bom ambiente para desenvolvimento de jogos mobile, permitindo a utilização de plataformas móveis como Android e iOS, entre outras. No entanto, para utilizar qualquer uma dessas plataformas é necessário configurar ambientes e ferramentas externas ao ambiente da engine. Para a configuração do ambiente Android na Unity será necessário baixar e instalar o Android SDK. Com o SDK instalado, deve ser baixada ao menos uma plataforma Android com API Level maior que 9, ou seja, Plataforma 2.3 ou superior. O caminho para o SDK do Android deve ser indicado para a Unity 3D por Unity >> Preferences, opção External Tools. Embora seja possível utilizar o emulador do Android, apenas no aparelho físico é viável o teste de todas as características do jogo. Para depurar o jogo por um SmartPhone DESENVOLVIMENTO DE JOGOS MOBILE 67 Android, é necessário habilitar a opção de depuração USB, dentro de opções de desenvolvedor. A configuração do ambiente iOS na Unity 3D exige que seja feito o cadastro na Apple Developer Program. Deve ser instalada a versão mais recente do XCode, a qual pode ser obtida na Mac App Store. A ferramenta XCode é um ambiente de desenvolvimento (IDE) que contém um conjunto de ferramentas de software criadas pela Apple para a implementação de software para OS X, iOS, WatchOS e tvOS. Para associar o XCode ao Apple ID, devem ser seguidos alguns passos: 1. Abrir o XCode e selecionar a opção Xcode >> Preferences na barra de menu para abrir a janela preferências. 2. Selecionar Accounts na parte superior da janela para exibir informações sobre os IDs da Apple. 3. Clicar no sinal de "mais" no canto inferior esquerdo e escolher Add Apple ID. DESENVOLVIMENTO DE JOGOS MOBILE 68 Ao gerar um produto para iOS, a Unity 3D gera o projeto XCode, incluindo todas as bibliotecas necessárias, código dotNet pré-compilado e Assets serializados. Esse projeto deve ser compilado no ambiente do Xcode para implantar e executar no dispositivo escolhido. Uma vez que Unity foi usado para construir o projeto XCode é possível efetuar a compilação e executar a partir da linha de comando. xcodebuild test -destination "platform=iOS,id=400d20d00baf8d4997b47be0416cf5c44dd2d3bc" -scheme Unity-iPhone Uma solução muito interessante para depurar o jogo criado na Unity é o aplicativo Unity Remote, o qual foi projetado no intuito de ajudar no desenvolvimento para Android ou iOS. O app deve ser baixado e se conecta com o Unity enquanto você está executando o projeto no modo Play do editor. A saída visual do editor é enviada para a tela do dispositivo e o input em tempo real é enviado de volta para o projeto em execução no Unity. Isso permite uma boa impressão do funcionamento do jogo, sem precisar de uma compilação completa para cada teste. Para utilizar essa ferramenta é necessário baixar o projeto Unity na Asset Store (requer compilação), e o app na loja de seu dispositivo, iOS ou Android. Em seguida é necessário conectar o dispositivo através da USB e efetuar a configuração correta da Unity 3D, através da opção de menu Edit >> Project Settings >> Editor, selecionando em seguida a seção Unity Remote, a qual permite escolher o tipo de dispositivo, compressão utilizada e resolução de tela. DESENVOLVIMENTO DE JOGOS MOBILE 69 Programação Unity para Mobile O primeiro componente que pode ser considerado na criação de jogos para dispositivos móveis é a classe HandHeld. Essa classe permite controlar os aspectos mais globais do jogo, como o uso de vibração, modo de tela cheia e indicador de atividade. public class ExampleClass : MonoBehaviour { void OnGUI() { if (GUI.Button(new Rect(0, 10, 100, 32), "Vibrate!")) Handheld.Vibrate(); } } Unity fornece um bom suporte a giroscópios e acelerômetros. Quando surgiu o primeiro celular com uso de acelerômetro, ele automaticamente gerou uma mania entre os consumidores. Vários jogos foram lançados com uso dessa tecnologia de sensores, posteriormente substituída pelo giroscópio. Jogos denominados "runner" obtiveram grande sucesso e até hoje conseguem manter um público fiel. O uso desses recursos é muito simples, encapsulados nas classes Gyroscope e AccelerationEvent, e a informação é obtida diretamente a partir da classe Input, como as demais entradas nos projetos Unity 3D. void Update() { dir.x = -Input.acceleration.y; dir.z = Input.acceleration.x; dir *= Time.deltaTime; transform.Translate(dir * 10.0F); } DESENVOLVIMENTO DE JOGOS MOBILE 70 Com Input.gyro, é possível obter o Gyroscope padrão do dispositivo. Utilizar o Quaternion attitude, de Gyroscope, é uma forma muito simples de controlar a rotação 3D de qualquer objeto do jogo. public class ExampleClass : MonoBehaviour { void Update() { transform.rotation = Input.gyro.attitude; }
Compartilhar