jogo 3d em blender - projinf.estig.ipb.ptprojinf.estig.ipb.pt/~a26023a24127/relatóriojogo3d.pdf ·...

73
Jogo 3D em Blender Patrick do Carmo Guedes nº26023 Vitor Manuel Albuquerque Mendes nº24127 Projeto realizado sob a orientação de: Professor Leonel Deusdado Engenharia Informática Junho de 2015

Upload: trinhhanh

Post on 08-Nov-2018

224 views

Category:

Documents


1 download

TRANSCRIPT

Jogo 3D em Blender

Patrick do Carmo Guedes nº26023

Vitor Manuel Albuquerque Mendes nº24127

Projeto realizado sob a orientação de:

Professor Leonel Deusdado

Engenharia Informática

Junho de 2015

ii

iii

Jogo 3D em Blender

Relatório da UC de Projeto

Licenciatura em Engenharia Informática

Escola Superior de Tecnologia e de Gestão

Patrick Guedes

Vitor Mendes

iv

v

Certifico que li este relatório e que na minha opinião, é adequado no seu conteúdo e forma como demonstrador do trabalho desenvolvido no âmbito da UC de Projeto.

___________________________________________

Professor Leonel Deusdado - Orientador

Certifico que li este relatório e que na minha opinião, é adequado no seu conteúdo e forma como demonstrador do trabalho desenvolvido no âmbito da UC de Projeto.

___________________________________________

Arguente

vi

vii

Agradecimentos

Queremos agradecer ao nosso orientador, Professor Leonel Deusdado, pela sua disponibilidade

orientação e apoio durante o desenvolvimento deste projeto que foi fundamental, pois sempre

nos motivou a não desistir mesmo quando as coisas pareciam correr menos bem.

Queremos agradecer a todos os nossos professores e a todos os colegas com que partilhamos

estes anos como alunos do IPB e como se costuma dizer: “No dia em que se chega a esta cidade,

chora-se porque se quer ir embora, mas depois chora-se porque não a queremos abandonar”.

Gostaríamos também de agradecer a toda a comunidade do fórum blenderartists e ao youtuber

arsenal rsl pelo esclarecimento de dúvidas e ajuda prestada.

Eu, Patrick Guedes, gostaria de agradecer aos meus pais, mas em especial á minha mãe porque

se estou a terminar o curso e este projeto, é graças a ela que sempre acreditou em mim, e me

apoiou em todas as decisões boas ou más que tomei ao longo destes anos.

Eu, Vitor Mendes, queria agradecer á minha família, em especial aos meus pais, por todo esforço

que fizeram e pelo apoio dado durante a realização do curso.

viii

ix

Resumo

O Mundo dos Jogos é atualmente uma das indústrias de entretenimento que mais lucro produz

á escala global e nomeadamente uma das que mais evolui. Se a tecnologia se desenvolve, os

jogos acompanham esse desenvolvimento, tornando-os uma consequência positiva.

As empresas de desenvolvimento de jogos têm apostado em diversas plataformas

nomeadamente consolas, computadores, dispositivos móveis e mais recentemente nas redes

sociais.

O desenvolvimento de jogos em 3D oferece uma perspetiva mais global e apelativa, pelo que

nesta unidade curricular de projeto iremos desenvolver um jogo 3D para computador contruído

no Motor de Jogos do software Blender, que incorpora a linguagem de programação Python para

scripts.

O jogo que irá ser desenvolvido terá como objetivo principal mover sólidos geométricos para a

obtenção de cores que se encontram em uma ou mais plataformas de jogo. Poderá ser jogado

por qualquer pessoa de qualquer faixa etária.

Palavras-chave: Jogos, 3D, Motor de Jogos, Blender, Python

x

xi

Abstract

The World Games is currently one of the entertainment industry that produces more profit on a

global scale and in particular one of the fastest evolving. The technology develops then

everything evolves and games are no exception.

Companies developing games have scheduled games for different platforms including consoles,

computers, mobile devices, and more recently on social networks.

The 3D development offers a more global perspective and appealing in our opinion, so in this

project course we will develop a 3D computer game made in Blender software Games Engine,

which incorporates the Python programming language for scripting.

The game will be developed will be aimed move geometric solids to obtain colors which are one

or more game platforms. It can be played by anyone of any age group.

Keywords: Games, 3D Games Engine, Blender, Python

xii

xiii

Conteúdos

1 Introdução ...............................................................................................................................1

1.1 Contextualização ...............................................................................................................1 1.2 Objetivos ...........................................................................................................................2 1.3 Motivação .........................................................................................................................2 1.4 Organização do relatório ..................................................................................................2

2 Estado da Arte .........................................................................................................................3

2.1 Software utilizado .............................................................................................................3 2.1.1 Blender .......................................................................................................................3 2.1.2 Game Engine ..............................................................................................................4 2.1.3 Layout do Game Engine .............................................................................................4 2.1.4 Python aplicado ao Blender .......................................................................................6

2.2 Casos de Estudo ................................................................................................................6 3 Planeamento e Desenho .......................................................................................................11

3.1 Nível 0 .............................................................................................................................11 3.1.1 Elementos presentes no nível .................................................................................11 3.1.2 Regras/Procedimentos para completar o nível .......................................................12

3.2 Nível 1 .............................................................................................................................12 3.2.1 Elementos presentes no nível 1 ..............................................................................13 3.2.2 Regras/Procedimentos para completar o nível .......................................................13

3.3 Nível 2 .............................................................................................................................14 3.3.1 Elementos presentes no nível 2 ..............................................................................15 3.3.2 Regras/Procedimentos para completar o nível .......................................................15

4 Implementação ......................................................................................................................17

4.1 Menus .............................................................................................................................17 4.2 Implementação do Nível 0 ..............................................................................................20 4.3 Implementação do Nível 1 ..............................................................................................22 4.4 Implementação do Nível 2 ..............................................................................................26

4.4.1 1ª Plataforma (Vento) ..............................................................................................26 4.4.2 2ª Plataforma (Fogo) ...............................................................................................28 4.4.3 3ª Plataforma (Perseguição e Universo)..................................................................31

4.5 Plataforma Mobile Android ............................................................................................35 5 Conclusões .............................................................................................................................39

5.1 Trabalho Futuro ..............................................................................................................39 Referências Bibliográficas ..............................................................................................................41

xiv

xv

Lista de Figuras

Figura 2.1: Layout e numeração dos painéis do Motor de Jogo .....................................................5 Figura 2.2: Controlador Python. ......................................................................................................6 Figura 2.3: Script Python..................................................................................................................6 Figura 2.4- Yo Frankie! .....................................................................................................................7 Figura 2.5: Color Cube .....................................................................................................................7 Figura 2.6: Cube Invasion ................................................................................................................8 Figura 2.7:Fun Karter Racer .............................................................................................................8 Figura 2.8: Orbito .............................................................................................................................9 Figura 2.9: I Will Escape ...................................................................................................................9 Figura 3.1: Esboço feito no papel sobre o possível cenário do Nível 0 .........................................11 Figura 3.2 - Esboço feito no papel da ilustração no Nível 1 ..........................................................13 Figura 3.3 - Esboço feito no papel da ilustração no Nível 2_Parte1 ..............................................14 Figura 3.4 - Esboço feito no papel da ilustração no Nível 2_Parte2 ..............................................14 Figura 4.1 – Menu de Instruções ...................................................................................................17 Figura 4.2 – Menu Inicial ...............................................................................................................17 Figura 4.3 – Carregamento de Nível ..............................................................................................18 Figura 4.4 – Menu de Pausa ..........................................................................................................18 Figura 4.5 – Lógica da Barra de Load .............................................................................................19 Figura 4.6 – Menu de Game Over ..................................................................................................19 Figura 4.7 – Menu de passagem de Nível ......................................................................................19 Figura 4.8 – Início do Nível 0..........................................................................................................20 Figura 4.9 – Nível 0 com cor vermelha obtida ...............................................................................20 Figura 4.10 – Lógica do cubo do Nível 0 ........................................................................................21 Figura 4.11 – Início do Nível 1 .......................................................................................................22 Figura 4.12 – Troca de sólido geométrico .....................................................................................23 Figura 4.13 – Esfera pintada ..........................................................................................................23 Figura 4.14 – Lógica da Câmara de 3ª Pessoa para o cubo ...........................................................24 Figura 4.15 – Câmara de 3º Pessoa para o cubo ...........................................................................24 Figura 4.16 – Sequência de cores completa ..................................................................................25 Figura 4.17 – Lógica para ganhar ...................................................................................................25 Figura 4.18 – Início do nível 2 (Vento) ...........................................................................................27 Figura 4.19 – Lógica da hélice ........................................................................................................27 Figura 4.20 – Lógica da torre .........................................................................................................27 Figura 4.21 – Sequência de cores do cubo completa ....................................................................28 Figura 4.22 – Lógica do cubo do nível 2 ........................................................................................28 Figura 4.23 – 2ª Plataforma (Fogo) ................................................................................................29 Figura 4.24 – Lógica do fogo ..........................................................................................................29 Figura 4.25 – Câmara 3ª pessoa ....................................................................................................30 Figura 4.26 – Lógica da esfera de perder vidas .............................................................................30 Figura 4.27 – Teletransporte .........................................................................................................31 Figura 4.28 – Última plataforma na câmara da esfera ..................................................................32 Figura 4.29 – Última plataforma (Perseguição e Universo) ..........................................................32 Figura 4.30 – Estrela ......................................................................................................................32 Figura 4.31 – Lógica da plataforma ...............................................................................................33 Figura 4.32 – Perseguição ..............................................................................................................33 Figura 4.33 – Finalização do nível e do jogo ..................................................................................34

xvi

Figura 4.34 – OgreKit .....................................................................................................................36 Figura 4.35 – Gamekit ....................................................................................................................36 Figura 4.36 – Finalizar projeto .......................................................................................................36 Figura 4.37 – ScreenShot Android ..................................................................................................37

xvii

Lista de Abreviaturas

BGE – Blender Game Engine

3D – Três Dimensões

GLSL – OpenGL Shading Language

“Chegar com novas ideias e converte-las em produtos reais foi sempre tão natural como respirar.”

Ralph Baer “Pai” dos vídeo jogos

xviii

1

Capítulo 1

1 Introdução

Nesta unidade curricular de projeto final de curso pretende-se implementar um jogo 3D,

originalmente para desktop. As etapas de implementação do jogo estão pendentes da definição

das regras, tipo de interface, tipo de jogo, ambiente/condições de jogabilidade.

Para o seu desenvolvimento ir-se-á recorrer ao Motor de Jogos do

Blender(blender.org(GameEngine)) que proporciona condições de movimentação, interação,

gravidade, deteção de colisões, trabalho de luz, entre outros.

1.1 Contextualização

O Mercado de jogos atingiu no ano 2013 um lucro no valor de 76 mil milhões de euros e cresce

a cada ano cerca de 9%,revelando assim que é uma indústria em constante expansão, mas

contudo controverso, pois há quem prefira os jogos de elevado nível gráfico e os que por outro

lado que pensam que já não se produzem jogos como alguns feitos antigamente(Cura 2015).

A nível interno o mercado português nos últimos anos registou um crescimento brutal desde o

cimentar dos casos de sucesso, como a Biodroid, às startups que lançam novos projetos de

potencial mundial, casos da Bica Studios ou Artbit Studios, ou o desenvolvimento com uma forte

identidade nacional, caso da Nerdmonkeys. Mas há também novos projetos ambiciosos que vão

desde Massive Multiplayer Online RPGs, como o Minimon3D, ou jogos que exploram áreas que

vão além dos ecrãs normais, como o projeto Cosmonaut da We Came From Mars que usa Oculus

Rift e Kinect(Caçador 2014).

Ou seja, tudo isto são boas sensações para os programadores visto que desde 2010 foram feitos

mais e melhores jogos do que na ultima década.

O jogo que se pretende desenvolver, quem sabe puder contribuir para ajudar o mercado interno

tem como âmbito entrar numa linha de dificuldade e divertimento independente do realismo

estabelecido, e acima de tudo obrigar o utilizador sentir-se desafiado.

2

1.2 Objetivos

Este projeto tem como principal objetivo a criação de um jogo 3D desenvolvido no motor de

Jogos Blender e aplicação da linguagem de programação Python.

Pretende-se também aplicar algum conhecimento adquirido anteriormente noutra unidade

curricular, nomeadamente Computação Gráfica e complementar com pesquisa para o

desenvolvimento do mesmo.

1.3 Motivação

Qualquer programador que se designe como tal, com certeza que aprecia jogos qualquer que

seja a plataforma ou género. Mas, melhor do que apreciar e jogar, é conseguir desenvolver.

Porque desenvolver um jogo é considerado também uma arte, pois tem-se pela frente o trabalho

de definir, moldar, construir, programar algo que no fim se consegue “sentir” o resultado prático

e que acima de tudo irá divertir pessoas libertando-as da rotina.

1.4 Organização do relatório

Para melhor orientação, o relatório está dividido em capítulos.

No primeiro é feita uma primeira introdução a este projeto, feita a sua contextualização no

mundo dos jogos atual, definição dos objetivos ao quais nos propusemos e motivação para a

realização deste projeto.

No segundo capítulo é elaborado o estado da arte, em que estudamos e analisamos alguns outros

jogos desenvolvidos no motor de jogos do Blender, e feita a introdução à tecnologia utilizada

para o desenvolvimento (Blender, Motor de Jogos do Blender, Linguagem de Programação

Python).

No terceiro capítulo de Planeamento e Desenho pretende-se começar a fundamentar o jogo,

fazendo esboços, explicando os elementos e lógica existentes.

No quarto capítulo de Implementação é explicado tudo o que foi feito para o desenvolvimento

do projeto consoante o planeamento feito.

No quinto capítulo ir-se-á concluir através de uma retrospetiva e análise pessoal do trabalho

realizado e apresentar ideias futuras para o jogo.

3

Capítulo 2

2 Estado da Arte

2.1 Software utilizado

2.1.1 Blender

O Blender, também conhecido por Blender3D, é um programa open source desenvolvido pela

Blender Foundation (Wikipédia(Foundation) 2015) para modelação, animação, textualização,

rendering, edição de vídeo e criação de aplicações interativas em 3D, como por exemplo jogos.

O seu lançamento foi em 1998 mas apenas 4 anos depois, em 2002 a empresa distribuidora do

programa acabaria por fechar devido a problemas financeiros. Nesse mesmo ano um co-

fundador do Blender, Ton Roosendaal (Wikipédia(Ton_Roosendaal) 2013) fundou a Blender

Foundation e alguns meses depois iniciou-se uma campanha para angariar €100.000 para os

investidores do programa concordarem em tornar o programa como open source. Em outubro

de 2002 foi lançada a versão livre do programa que atualmente ainda é desenvolvido pela Blender

Foundation.

O programa está disponível para diversos sistemas operativos, tendo ferramentas similares a

programas privados. Tanto o Blender como o seu motor de jogo suportam phyton como

linguagem de script(Wikipédia(Blender) 2015).

Desde o seu lançamento o Blender conta com alguns projetos de grande sucesso, como jogos e

animações. O seu primeiro grande projeto profissional foi o Homem-Aranha 2 em 2004, onde

foram criadas animações para fazer o esboço das cenas do filme.

Em 2008 a Blender Foundation e uma empresa por esta controlada, a Blender Institute (Wikipédia

2015), criaram o jogo Yo Frankie! (Wikipédia(YoFrankie) 2015), que é baseado na animação Big

Buck Bunny que foi produzida nesse mesmo ano. O jogo foi inicialmente conhecido como projeto

Apricot em que o jogador controla o Frankie, um esquilo. As personagens e cenários são

construídos no Blender Game Engine e o rendering em tempo-real foi feito no motor gráfico

Crystal Space (Wikipédia(Cristal) 2015).

4

2.1.2 Game Engine

O Blender Game Engine, também conhecido como BGE é o motor de jogo do Blender. O BGE usa

OpenGL para gráficos, OpenAL para som 3D, Bullet para física e deteção de colisão, e Python para

scripts. O uso do motor de jogo do Blender pode servir para diversas funcionalidades, desde

criação de jogos, apresentações, realidade virtual, auxílio em animação (usando a física para dar

movimentos mais reais aos objetos)(blender.org(GameEngine)).

A principal diferença entre o Motor de Jogo e o Blender em Modo Normal resume-se a:

Em Modo Normal podemos construir imagens ou animações em modo offline, e uma

vez feito render não podem ser modificadas.

No Motor de Jogo o processo de render é realizado continuamente em tempo real, e

incorpora também facilidades para o programador interagir com a cena durante o

processo de rendering.

O Motor de Jogos do Blender permite correr conteúdo no próprio programa mas é possível

também exportar o run-time para as diversas plataformas entre as quais, Windows, Linux,

MacOs(Arts 2009) e com suporte também para android. (blender.org)

Quando se pretende criar um jogo ou uma simulação usando o Motor de Jogo do Blender existem

quatro passos muito importantes:

Criar elementos visuais que podem ser alvo de rendering. Estes podem ser modelos 3D

ou imagens.

Permitir a interação dentro da cena usando blocos lógicos para um comportamento

personalizado, e determinar a maneira como a cena é invocada, usando os sensores

adequados como o teclado ou rato.

Criar uma ou mais câmaras para dar melhor perspetiva da melhor maneira para fazer

render da cena, e também modificar parâmetros de suporte do ambiente em que o jogo

vai ser exibido.

Correr o jogo, usando o player interno ou exportar para uma plataforma apropriada.

2.1.3 Layout do Game Engine

Para ajudar à conceção, construção, depuração, execução de um jogo o Blender incorpora uma

tela para esse efeito como se verifica na Figura 2.1. Alguns painéis existem no modo normal mas

5

também é adicionado um novo painel Logic Editor que é exclusivo do motor de jogo (BGE)

(Manual).

\

Figura 2.1: Layout e numeração dos painéis do Motor de Jogo

1) Game Logic

É selecionado na lista de Layouts de tela entre as várias aplicabilidades existentes.

Inclui já alguns painéis já familiares de informação, visualização em 3D, propriedades, e também

o painel Logic Editor especializado no motor de jogos.

2) Blender Game

Selecionamos esta opção no menu de motor de render.

Especifica os outputs que vão ser mostrados em tempo real pelo render do motor de jogo.

Ao selecionarmos esta opção, abre algumas outras opções de menu, entre as quais opções de

jogo e algumas propriedades entre as quais as de rendering.

3) Game

Este menu oferece várias opções para o funcionamento do Motor de Jogo. Esta opção está

disponível apenas quando o motor de render está selecionado no modo “Blender Game”.

4) Logic Editor

6

É neste painel onde a lógica, propriedades e estados estão configuradas para controlar o

comportamento dos objetos no jogo, com sensores (Ex: Teclado), controladores (Ex: Python) e

atuadores (Ex: Scene).

5) Propriedades

Painel de propriedades que se podem adicionar a qualquer objeto da cena. Boolean, Integer,

Float, String, Timer, são as propriedades disponíveis.

2.1.4 Python aplicado ao Blender

Python é uma linguagem de programação que é usada pelo Blender com o fim de correr scripts,

que podem ser utilizados para estender a funcionalidade do Blender sem ter que alterar as

versões binárias compiladas disponíveis. As versões binárias correntes do Blender vêm com uma

versão embutida e apropriada das bibliotecas do Python para ser usada.

Resumindo podemos criar um script recorrendo por exemplo a um controlador Python e criar os

nossos próprios scripts(blender.org(python)) como podemos observar nas Figura 2.2 e Figura 2.3.

Figura 2.2: Controlador Python.

Figura 2.3: Script Python.

.

2.2 Casos de Estudo

Atualmente vários jogos são criados em Blender, sendo a maioria projetos individuais

disponibilizados no fórum oficial http://blenderartists.org onde se pode encontrar projetos

completos ou ainda em desenvolvimento pela comunidade.

7

Yo Frankie!, o jogo criado pela Blender Institute em que o jogador controla um esquilo

num cenário divertido e com modo de 2 jogadores, como se pode verificar pela Figura

2.4.

Figura 2.4- Yo Frankie!

Color Cube(2010), um jogo de puzzle com 48 níveis com muita interatividade e lógica, que

é neste momento um jogo que está a ser comercializado.

Figura 2.5: Color Cube

8

Cube Invasion (2012), um projeto individual que desafia o jogador contra uma invasão de

cubos.

Figura 2.6: Cube Invasion

Fun Karter Racer (2015), uma corrida de carros em que pode obter armas e pode atingir

ou ser atingido pelos seus adversários.

Figura 2.7:Fun Karter Racer

9

Orbito (2011), jogo do estilo super-mario em que o jogador controla um macaco.

Figura 2.8: Orbito

Recentemente, a 22 de Dezembro de 2014 foi lançado o jogo I Will Escape. A primeira parte de

uma trilogia em que o jogador é um condenado que terá de escapar de uma prisão. Este é

primeiro jogo feito em Blender a estar à venda numa das maiores plataformas de jogos online, a

Steam(2014).

Figura 2.9: I Will Escape

10

11

Capítulo 3

3 Planeamento e Desenho

3.1 Nível 0

No seguimento de alguns casos de estudo de outros jogos e em conversação com o nosso

orientador reuniu-se consenso quanto ao tipo de jogo que seria desenvolvido. “Para quê criar

personagens que iriam custar muito tempo a construir, quando o Blender fornece por defeito

sólidos geométricos que podem funcionar como personagens.”

O objetivo do jogo que se realizou para ser criativo, consiste principalmente em usar sólidos

geométricos para apanhar cores espalhadas com uma certa lógica através de plataformas.

Assim sendo antes de passar á implementação propriamente dita, foi pensada a melhor maneira

de fazer um pré-visionamento do que se queria para o jogo. Nada melhor que o papel em branco

para exprimir toda a criatividade imaginada.

Para melhor perceber a ideia do ambiente de jogo, a Figura 3.1 representa um esboço pensado

para o Nível 0, que é nada mais do que um pequeno tutorial.

Figura 3.1: Esboço feito no papel sobre o possível cenário do Nível 0

3.1.1 Elementos presentes no nível

Por ser um pequeno nível para aprendizagem, não pode conter demasiada “informação” que

dificulte o entendimento da lógica do jogo.

12

Seguindo essa mesma ideia este primeiro nível apenas contém uma simples câmara bem

centralizada para a plataforma principal, em que o personagem é um cubo. Está presente desde

já uma sinalização das cores que é pretendido obter bem como a sequência que deve ser seguida.

São elementos muito simples, mas importantes no entendimento do que se pretende.

3.1.2 Regras/Procedimentos para completar o nível

Seguindo a lógica inventada, o objetivo para já como já foi referido é aprender. Para completar

o nível 0, basta movimentar o cubo primeiramente para a cor vermelha onde irá ser pintada a

cor no canto superior esquerdo. Depois de pintar a cor vermelha o cubo fica naturalmente

vermelho e assim de seguida, deve-se movimentar de novo o cubo para a cor azul. Assim se

completa a sequência de cores exigida e o nível termina de imediato. É importante referir que

quer as sequências e as cores que cada sólido deve pintar são nada mais que as formas de cada

sólido, isto é, um cubo está para um quadrado assim como uma esfera está para um círculo.

O modo de perder resume-se caso o cubo caia fora da plataforma, e o jogo reinicia

automaticamente.

3.2 Nível 1

O nível 1 de princípio foi pensado para ser o tutorial, mas foi notória alguma dificuldade para

entender o objetivo do jogo. Como ficou demonstrado aquando a nossa primeira apresentação

do projeto na primeira etapa de avaliação, assim foi decidido, melhorar alguns aspetos do

referido nível e desenvolver um muito mais básico para ser o nosso nível 0. Como se vai puder

observar na Figura 3.2, é possível começar a perceber a lógica do nível 1.

13

Figura 3.2 - Esboço feito no papel da ilustração no Nível 1

3.2.1 Elementos presentes no nível 1

A grande diferença que separa o nível 0 e nível 1 será o facto de começarem a ser usados mais

sólidos para apanhar cores. Mas isso será detalhado em pormenor no capítulo 4.

Assim sendo o nível 1 tem na sua constituição três câmaras em que uma delas se encontra numa

posição de completa visualização de todo o ambiente de jogo. Outras duas são melhorias em que

uma delas persegue o movimento do cubo, e outra segue a esfera ao estilo de jogo em 3ª Pessoa.

O mapa de jogo se assim quisermos chamar, são duas plataformas unidas por uma ponte em

subida que dificulta o movimento dos sólidos. Um temporizador no canto inferior direito é outra

nova implementação que conta no sentido descendente, para temporizar a conclusão das

sequências de cores presentes no tempo estabelecido inicialmente.

3.2.2 Regras/Procedimentos para completar o nível

O início do nível é começado desta vez com a esfera que terá que ser movida com o objetivo de

chegar á cor amarela, assim pintando a mesma e a primeira/única cor da sequência do sólido em

questão. Feito isto, é necessário trocar de sólido geométrico, e para isso terá que ser percorrido

o mapa com o intuito de encontrar o lugar correto e desconhecido pelo utilizador para trocar de

sólido, que foi devidamente sinalizado no esboço. Nesse momento a esfera sai do jogo e entra

um cubo. Assim resta ao cubo pintar de seguida a cor vermelha e a cor azul respeitando esta

14

ordem, pois outra ordem não é permitida pela sequência exigida inicialmente. A qualquer altura

do jogo é possível alternar de câmaras.

O modo de perder do nível 1 é cair no buraco (que possui uma força de atracão), cair fora da

plataforma, ou não completar o nível dentro do tempo estabelecido pelo cronómetro. Caso estas

condições aconteçam o nível reinicia automaticamente.

3.3 Nível 2

Neste item será falado sobre o último nível desenvolvido para o projeto. Trata-se de algo já mais

complexo que será detalhado ao longo deste relatório.

.

Figura 3.3 - Esboço feito no papel da ilustração no Nível 2_Parte1

Figura 3.4 - Esboço feito no papel da ilustração no Nível 2_Parte2

15

3.3.1 Elementos presentes no nível 2

Como é possível observar nas Figura 3.3 e Figura 3.4, o nível 2 é composto por duas partes.

Na Figura 3.3 existem vários elementos novos, entre os quais uma torre de vento, vasos de fogo,

que são os dois principais perigos. Existem naturalmente cores que são dos elementos principais,

vidas que convém não serem perdidas, um cubo, e uma esfera que entra em jogo na segunda

plataforma. Na segunda plataforma (assim que disponível) existe um teletransporte que conecta

a Figura 3.4 ao jogo, é a fase final do jogo em que existe uma plataforma redonda, com pedras e

outros obstáculos referenciados ao longo do capítulo.

Todas as plataformas e todos os sólidos geométricos possuem uma câmara própria para uma

melhor interação.

3.3.2 Regras/Procedimentos para completar o nível

O nível começa com um cubo em que terá como principais obstáculos alguns buracos na

plataforma, e uma torre de vento que caso se entre na sua proximidade, aplicará uma força que

o irá afastar. O objetivo passa entretanto por não ser apanhado no radar dessa torre e mover o

cubo para as cores que lhe pertencem, (no caso vermelho e amarelo por esta ordem). Feito o

primeiro objetivo de completar as cores, o cubo terá que saltar para a segunda plataforma, a qual

como já foi referido não se encontra parada, o que irá dificultar o objetivo, mas o que torna mais

fácil a mudança de sólido, pois a partir do momento em que o cubo colidir com a segunda

plataforma, irá desaparecer e entrar a esfera de imediato.

Se a primeira plataforma era relacionada com vento, a segunda é com fogo, em que a esfera não

deverá colidir, pois perderá uma vida por cada vez que o faça. O utilizador terá que conseguir

fazer face ao movimento da plataforma e mover o sólido para as cores que lhe correspondem,

assim desbloqueando um teletransporte que levará a esfera para a ultima fase do nível. Foi um

resumo da Figura 3.3.

Na Figura 3.4, segunda e última parte do nível, após o teletransporte a esfera “aterra” na

plataforma e terá como objetivo pintar a cor verde e ai sim completada a sequência de cores que

lhe corresponde, encontrar a maneira de trocar para cone.

16

Por cima de cada cor a uma altura significativa, estão rochas/pedras que estão programadas com

intervalos de tempo para cair. Caso isso aconteça, a cor que se pretendia pintar fica

automaticamente desativada o que obriga o utilizador a recomeçar o nível.

Entra então em jogo o último sólido, e por sua vez entra em cena uma espécie de pedra gigante

que faz perseguição ao cone. Com essa dificuldade acrescida, pretende-se que a serie de cores

seja cumprida e assim que a cor final (preto) for pintada, o cone é elevado até uma porta que lhe

permite sair do jogo e assim dar por encerrado o nível e finalizado o jogo.

Importante de referir que o modo de perder, pode ser por queda fora das plataformas, ou em

buracos que existam, entrar no radar da torre de vento será complicado sobreviver, colidir com

o fogo também não será uma boa opção. Ser apanhado pela pedra gigante irá fazer com que se

percam vidas também. Após a perda de três vidas o jogo entra num menu de game over o que

obriga a recomeçar. Caso se perca uma vida o jogo reinicia automaticamente podendo-se

continuar a jogar no ponto inicial de cada plataforma.

17

Capítulo 4

4 Implementação

4.1 Menus

Não existindo nenhuma API que pudesse facilitar a construção de um menu e o princípio de

desenvolvimento passou também pela mesma forma de desenvolver um nível, ou seja trabalhar

com modelação, lógica, propriedades, entre outras partes importantes.

Uma das partes mais importantes de qualquer jogo sem dúvida são os menus. Foi algo que foi

aprendido desde muito cedo no começo do desenvolvimento deste projeto. As Figura 4.1 e Figura

4.2, representam o menu inicial do jogo, e o menu principal de instruções respetivamente. Algo

que é notório é que por vezes o texto fica sem pontuação algo que nem sempre é fácil controlar.

O processo de criação de um menu consistente como o da Figura 4.2 é composto por vários

passos entre os quais iremos enumerar por tópicos:

Adicionar Câmara;

Plano para o fundo e texturizar;

Botão (plano mais texto) que para a sua criação obedece a algumas regras que

funcionaram em geral para todos os botões dos menus do jogo.

Figura 4.1 – Menu de Instruções Figura 4.2 – Menu Inicial

18

Texto para instruções ou botões (Edit Mode), (Alterar Texto), (Novo Material) (Converter

para Mesh)

Porque pensamos que fazer botões deve ser um pouco mais detalhado que o resto, a sua criação

engloba dois elementos principais: texto e um plano de fundo que irá servir de sensor, que neste

caso irá ter a lógica incorporada e que permite fazer a animação de um botão. Essa lógica é

composta por dois sensores de mouse que por sua vez ligados a dois controladores and e um

nand. Os atuadores são um scene para com o click do rato aceder a outra cena que pode ser a

Figura 4.1, um som de botão, e dois action que criam a animação da frame zero até á três e vice-

versa. A animação cria-se no sensor isto é abrindo o painel de timeline e na frame zero é inserido

o estado inicial e na frame três o estado final da animação pretendida. (Anexo 1).

O sensor e o texto para ficarem ligados é necessário criar um parentesco entre os dois objetos, o

que irá implicar que a lógica implementada no sensor atue também nas letras que é exatamente

o que se pretende visto que o sensor por fim ficando invisível não será visto pelo

utilizador.(ThaTimst3r)

A Figura 4.3 representa um carregamento com instruções próprias para cada nível criado. Por

sua vez a Figura 4.4 é um menu de pausa que permite a qualquer altura interromper o jogo.

O processo de construção de um carregamento de um nível, neste caso da Figura 4.3 é

importante referir que não carrega informação pois os níveis não contêm informação

propriamente dita. Este foi um menu pensado para uma pré-preparação antes de jogar, fornecer

Figura 4.3 – Carregamento de Nível Figura 4.4 – Menu de Pausa

19

algumas informações de ajuda. A barra de Load é o elemento que contém toda a lógica de ligação

que irá ser explicado se seguida.

A barra de carregamento do jogo para este projeto foi conseguida através dos seguintes passos:

Adicionar uma propriedade de tempo;

Dois sensores de always que sempre que a cena estiver ativa ativar,

Um controlador and e controlador python (Anexo 2);

Um atuador action e outro de scene.

Em conjunto criam uma animação que terminado o tempo treze segundos contados

decrescentemente o menu de load termina e começara o nível zero.

Os últimos dois menus mais importantes do jogo são como demonstram as Figura 4.6 e Figura 4.7, os menus de perder e ganhar o nível respetivamente.

Figura 4.5 – Lógica da Barra de Load

Figura 4.6 – Menu de Game Over Figura 4.7 – Menu de passagem de Nível

20

A lógica de construção prende-se com as dos menus anteriores descritos mas com a diferença

que ocorrem quando o utilizador estiver a jogar os níveis propriamente ditos. Não é possível

perder ou ganhar sem jogar. Os restantes menus podem ser analisados no Anexo 3.

4.2 Implementação do Nível 0

Como já foi referido no capítulo anterior o jogo é constituído por menus e níveis. Ao longo do

projeto foram conseguidos três níveis cada um deles seguindo a sua própria lógica, programação

e ideia.

Mas mais importante que desenvolver um jogo é torná-lo rapidamente apelativo no primeiro

contacto que qualquer jogador tenha pela primeira vez, e para isso contribuem os tutoriais que

servem essencialmente para aprender, mas também para atrair a atenção e curiosidade.

Nesse âmbito o primeiro nível de jogo, ao qual foi chamado de nível zero, resume-se a fazer um

primeiro contato com um dos objetivos que é movimentar um ou mais sólidos geométricos, cada

uma na sua vez, em uma ou mais plataformas a fim de completar sequências de cores. As Figura

4.8 e Figura 4.9 fazem este contato.

Na Figura 4.8 pode se observar que no canto superior esquerdo existem dois quadrados pintados

a vermelho e azul que representam a sequência de cores que o utilizador deve obedecer, e por

sua vez dois quadrados brancos que indicam quando a sequência se encontra completa.

Este primeiro nível e todos foram desenvolvidos em modo GSLS(opengl.org) que permite

melhores sombreamentos e grafismo foi construído com os seguintes objetos:

Figura 4.8 – Início do Nível 0 Figura 4.9 – Nível 0 com cor vermelha obtida

21

Um cubo que moldado e texturizado representa a plataforma de jogo;(rsl 2014)

Um cubo normal para ser o sólido principal que servirá para completar as cores.

Quatro planos moldados e texturizados que indicam a sequência e quando são obtidas

essas cores.

Desta forma a Figura 4.9 já representa um exemplo de quando uma cor é pintada no jogo. A sua

lógica de implementação obedece algumas regras que serão explicadas com a ajuda da Figura

4.10.

O processo para concretizar algo objetivo para um personagem de um jogo trata-se de algo que

não é completamente visível para quem começa a trabalhar com o motor de jogos do Blender. A

Figura 4.10 é um complemento muito importante para se perceber como se concretizam ações

com lógica para o nível zero.

Começando por partes, existem no cubo quatro sensores de keyboard que por sua vez são ligados

a quatro atuadores motion por intermédio de quatro controladores and, que basicamente

permitem “mexer” o cubo. Isto é, se inserirmos up arrow no sensor keyboard, 5 graus na rotação

e 0.09 na locação em X no atuador motion correspondente, o cubo irá andar em frente.

Para pintar uma cor(azul) neste caso destacado pela Figura 4.10 são usados dois sensores always

e collision que por sua vez são conectados por um controlador python azulN0.py(Anexo 4), a um

atuador scene. A script o que faz é quando a colisão com o objeto azul da plataforma suceder, o

Figura 4.10 – Lógica do cubo do Nível 0

22

cubo pintará de azul e a sequência terminará, e assim terminando o nível zero. O menu da Figura

4.7 é ativado.

Foi também adicionado um cubo que se encontra invisível com uma propriedade Game Over que

foi modelado para cobrir uma área restrita do nível. A sua função é em caso de o sólido colidir

com esse cubo o jogo recomeçará de imediato no ponto inicial.

A script para pintar a cor vermelha que também se encontra no Anexo 4 segue a lógica da script

azul mas com a programação correta de combinar propriedades para que a ordem seja

corretamente cumprida.

Isto é, existem na plataforma duas cores para pintar, nos quais o objeto vermelho tem uma

propriedade booleana verdadeira, e o objeto azul uma falsa. Caso o utilizador tente pintar

primeiro o cubo de azul não conseguirá porque para esse efeito a propriedade tem de ser

obrigatoriamente verdadeira, e para o conseguir terá que obter a cor vermelha que depois de

ser pintada passará a propriedade azul a verdadeira, possibilitando assim que a cor azul fique

disponível.

4.3 Implementação do Nível 1

Dando continuidade ao trabalho realizado até ao momento foi desenvolvido um primeiro nível

que vai exigir não muita, mas alguma perspicácia e atenção ao utilizador do que é pedido para

completar mais uma etapa. A Figura 4.11 serve para se puder fazer uma primeira análise.

Figura 4.11 – Início do Nível 1

23

Revelando já alguma complexidade a nível de construção, modelação e texturização de objetos

o nível um foi desenvolvido no modo multitexture, contudo numa fase mais tardia do projeto

percebeu-se que em modo GLSL o jogo se tornava mais estável quando se tentava jogar do

princípio ao fim percorrendo todos os menus e níveis.

O processo para a construção de um nível no BGE, passa essencialmente por três fases: O pensar

de como vai ser e para isso existe um planeamento e desenho, uma modelação passando do

papel à prática, e o mais fundamental a lógica que envolve. (Cookie 2011)

A modelação do nível um, englobou a modelação de vários objetos entre os quais um cubo, que

se transformou numa plataforma de jogo, para criar um ambiente de precipício modelou-se uma

esfera e aplicou-se uma textura, objetos para as sequências e cores, um plano para a porta de

saída. O temporizador é um texto que é convertido para algarismos, mas ao longo do relatório

dará para perceber melhor o que foi contruído.

A Figura 4.13 representa a primeira e única cor obtida pela esfera. Para esse efeito foi usada uma

script Python (excoramarela.py) que se encontra no Anexo 5 e o que faz é quando a colisão com

o objeto amarelo que se encontra na plataforma for positiva, a esfera adquire a sua cor e por sua

vez é pintada de amarelo o objeto no canto superior esquerdo indicando sucesso. O utilizador

ganha também uma bonificação de cinco segundos no temporizador. O código [1,1,0, True] faz

pinta o objeto de amarelo.

A Figura 4.12 é onde acontece um dos objetivos principais da lógica do jogo, ou seja a troca de

sólido geométrico, neste caso da esfera pelo cubo. A script(trocar.py) encontra-se também no

Figura 4.13 – Esfera pintada Figura 4.12 – Troca de sólido geométrico

24

Anexo 5 e é junção de duas scripts no mesmo ficheiro, no qual chama-mos a cada uma delas de

módulos.(switch e TrocarFig).

O módulo TrocaFig faz a colisão com um local da plataforma escolhido aleatoriamente acontecer

e a propriedade da esfera por verdadeira (passa a verdadeira quando pinta de amarelo), é

adicionado um cubo na cena que se encontra numa layer diferente, e a esfera desaparece.

Numa combinação de estados o módulo python TrocarFig envia também uma mensagem

através de um sensor que possibilita que assim que o cubo entre em cena, a câmara o comece a

seguir em modo de terceira pessoa ativando assim um segundo módulo switch que se encontra

também no Anexo 5. Este módulo tem a função fazer o seguimento do cubo em modo de

terceira pessoas. A lógica da Figura 4.14 resulta na Figura 4.15.(blenderArtists(Objects) 2015)

Recuando um pouco atrás foi também implementada uma força de atração para o buraco da

plataforma. Em modo invisível e abaixo do nível da plataforma na direção do buraco, encontra-

se um cubo que tem por objetivo afetar os sólidos com que se estiver a jogar. A script força.py

que se encontra no Anexo 5, é implementada na esfera, em que quando a distância para esse

cubo de atracão for menor que um determinado valor, será atraída para o buraco forçando o

utilizador a perder. Caso essa distância seja maior que o valor a atração deixa de funcionar.

O temporizador timer.py do Anexo 5 que se encontra no canto inferior esquerdo do ecrã foi

desenvolvido adicionando um texto que convertido origina algarismos. O seu funcionamento

começa a contar de ordem decrescente de 60 e quando chegar a 0, o nível recomeça do ponto

de partida seja qual for o sólido com que se esteja a jogar. A cor inicial do temporizador é azul

mas quando o tempo estiver nos 5 segundos finais a cor passa a vermelho para alertar o

Figura 4.15 – Câmara de 3º Pessoa para o cubo Figura 4.14 – Lógica da Câmara de 3ª Pessoa para o cubo

25

utilizador que o tempo para concluir o nível vai terminar.Foi também desenvolvido um método

para por exemplo, se o utilizador estiver a jogar na câmara principal, como existem outras

câmaras no jogo não serem visíveis apesar de existirem. (camera2.py Anexo 5). Existem mais

algumas scripts que foram implementadas para fazer este processo mas seguem a lógica da

referida anteriormente, no entanto foi necessário algum trabalho com propriedades para não

serem conflituosas.

Para concluir a implementação do nível um, a Figura 4.16 demonstra o objetivo completo.

Após a o utilizador conseguir pintar a última cor (neste caso o azul), é aberto um portão que

indica a saída. A lógica que possibilita este acontecimento é feita pela script portão.py que se

encontra no Anexo 6. Tem como função assim que a cor azul for pintada a propriedade

booleana do portão fica verdadeira que até aqui era falsa, ativando assim uma animação e um

som de abertura.

De seguida basta movimentar o cubo para a saída e assim se finaliza o nível um que é

concretizado pela Figura 4.17. Quando a colisão com a saída que tem a propriedade “ganhar”

for sucedida, um dos menus de sucesso de passagem de nível é mostrado ao utilizador.

Figura 4.16 – Sequência de cores completa

Figura 4.17 – Lógica para ganhar

26

O modo de perder para além do método enunciado no nível zero, pode ser também por não

finalizar o nível no tempo estabelecido ou ser atraído para o buraco da plataforma de jogo.

4.4 Implementação do Nível 2

Por ultimo, o nível dois que foi implementado neste projeto é uma amostra mais real da

capacidade do motor de jogos do Blender, embora seja uma ferramenta capaz de muitos mais.

Ao contrário dos outros níveis, este foi decidido para uma melhor perceção a sua divisão por

plataformas, onde serão explicadas as etapas mais cruciais no que à lógica e implementação diz

respeito.

Em relação ao planeamento e desenho o nível sofreu uma alteração pois continha uma

plataforma de água que mais tarde se concluir que não acrescentaria nada de objetivo ao jogo

pelo que não foi implementada.

É um nível que contém vários temas, objetivos, mais sólidos, novas funcionalidades, que assim

aumentaram o nosso conhecimento e aprendizagem sobre motor de jogos. Mais do que ser

benéfico para quem os produz é mais satisfatório saber que o utilizador final gosta e aprecia o

que foi feito.

4.4.1 1ª Plataforma (Vento)

Como demonstrado no capítulo anterior foram implementadas nas plataformas existentes um

ambiente diferente para cada uma delas. Neste caso foi decidido em que o tema principal seria

o vento.

A Figura 4.18 representa o início e a primeira plataforma do nível dois.

27

Passando pela modelação a que outros níveis também foram sujeitos as principais novidades

que se podem ver é a implementação de vidas para cada sólido que se encontram no canto

superior direito e uma torre com uma hélice geradora de vento.

A torre foi construída com dois objetos que estão ”ligados” por um parentesco selecionando os

dois objetos para os unir.

A Figura 4.19 é controlada por uma script helice.py que se encontra no Anexo 7 e tem um sensor

de radar que estabelece uma distância e um angulo para o cubo. Caso o cubo entre no radar da

hélice é aplicada uma forma de afastamento projetando o sólido.

O atuador motion tem como função fazer rodar a hélice enquanto o atuador sound simula um

som de vento, tornando o jogo o mais real possível. A Figura 4.20 faz com que a torre persiga o

cubo para todo o sítio que ele se movimente, mas sem se deslocar.

Evitando a hélice e tentando não perder vidas a Figura 4.21 demonstra um desbloqueio da

segunda plataforma de jogo, pois foi conseguido completar a sequência de cores do cubo.

Figura 4.19 – Lógica da hélice Figura 4.20 – Lógica da torre

Figura 4.18 – Início do nível 2 (Vento)

28

Para terminar a explicação da primeira plataforma a Figura 4.22 apresenta toda a lógica do cubo.

Resumindo, o cubo contém lógica para saltar, se movimentar, colisões para perder vidas e fazer

Game Over, trocar, pintar cores, e física Rigid Body com a opção actor que irá permitir atuadores

de outros objetos atuem no sólido. Para que o cubo mantenha um movimento original a massa

tem que ter um valor próximo de zero, radius igual a dez, e o form factor maior que um. A opção

collision bounds é também obrigatória caso contrário as rotações do cubo serão deficientes, isto

é, se o utilizador não completar uma rotação completa o cubo ficará esquinada e será difícil até

ter o cubo direito na plataforma de jogo.

4.4.2 2ª Plataforma (Fogo)

Como referido anteriormente cada plataforma tem um diferente tema, logo diferentes

obstáculos. O cubo após conseguir saltar para a segunda plataforma o que não se adivinha fácil

Figura 4.22 – Lógica do cubo do nível 2

Figura 4.21 – Sequência de cores do cubo completa

29

devido a esta não ser estática, transforma-se de imediato para a esfera que se pode ver na Figura

4.23.

Face á animação que atua nos eixos dos X da plataforma, o utilizador terá que ser perspicaz o

suficiente e fazer face á movimentação da placa em que a sua lógica se encontra no Anexo 8.

Da frame 0 até á 120 é reproduzida uma animação da “frente para trás” em que ativada por

sensor always, entra em loop o que permite estar sempre ativa. Foi escolhido este intervalo entre

as frames porque caso se aumentasse ou diminuísse o intervalo a animação ficaria muito rápida

ou demasiado lenta para o que era pretendido.

A script python destacada apenas tem como função igualar a propriedade booleana para falsa

que auxilia a esfera a saltar, visto que se for verdadeira o salto torna-se irreal e a esfera desloca-

se para o infinito se a tecla de espaço for constantemente pressionada.

Em relação ao fogo, foi criado graças a um emitter que é obtido através da instalação de um

addon chamado EasyEmit para o Blender. Adiciona-se quatro objetos e recorrendo às partículas

do addon cria-se dois objetos de fogo e de fumo.(blenderArtists 2013)

Figura 4.23 – 2ª Plataforma (Fogo)

Figura 4.24 – Lógica do fogo

30

A Figura 4.24 tem como função mais uma vez com a ajuda de um sensor de radar detetar a esfera

e quando a distancia for menor que 2.5 é enviado num atuador uma mensagem para a esfera

que a recebe como sensor. Se o radar for positivo a esfera fica de cor preta pois chegou perto do

fogo. Em caso de colisão total com o fogo a esfera perde uma vida que será explicada de seguida.

A Figura 4.25 demostra o que foi explicado antes, em que a esfera está de cor preta porque foi

apanhada no radar do fogo. No canto superior direito da imagem pode-se verificar que das três

esferas sobram apenas duas, pois a esfera ou colidiu com o fogo ou caiu fora da plataforma de

jogo. A Figura 4.26 que representa a lógica da esfera, destaca como foi implementada a perca de

vidas e do nível.

Os módulos Python destacados que se encontram no Anexo 9, correspondem à maneira de

perder cada vida individualmente, isto é verificando se as colisões que neles estão ligados são

positivas, nesse caso perde a vida correspondente. É também no módulo vidinha1 que a

mensagem do fogo é recebida assim possibilitando a esfera ficar preta, para além de perder a

primeira vida. Ao contrário dos outros níveis que perdendo o jogo recomeçava do início, foram

Figura 4.25 – Câmara 3ª pessoa

Figura 4.26 – Lógica da esfera de perder vidas

31

criados spawn_points que são objetos vazios que se encontram em pontos iniciais de cada

plataforma e quando uma vida é perdida, tomam a posição do sólido geométrico

correspondente. O “controlador de vidas” de cada sólido é uma propriedade inteira que é igual

a três à qual é decrementada um valor sempre que se perde uma vida. No módulo vidinha3 é

verificado se essa propriedade é igual a zero, e caso o seja a última vida é perdida, e o jogo

termina apresentando o menu de Game Over da Figura 4.6.

Caso o utilizador seja bem-sucedido, isto é, não perdendo todas as vidas e completando a

sequência de cores que se encontram disponíveis na plataforma desbloqueia um teletransporte

que se pode ver na Figura 4.27. A script responsável por permitir obter a cor laranja e

desbloquear o teletransporte é a script pintarLaranjaN2.py do Anexo 10.

A lógica implementada no teletransporte que se encontra no Anexo 10, é controlada por uma

script python teleport.py que quando a colisão com a esfera é positiva, transporta-a para a ultima

plataforma do nível. O seu funcionamento principal é obter a posição da esfera, e desloca-la do

teletransporte emissor (Port1), para o recetor (Port2).(Guedes 2015)

4.4.3 3ª Plataforma (Perseguição e Universo)

É chegada a última fase do jogo. Depois de feito o teletransporte da esfera para a última

plataforma que pode ser vista nas Figura 4.29 e Figura 4.28 seguintes.

Figura 4.27 – Teletransporte

32

O tema escolhido para a última plataforma, foi decidido que queríamos um ambiente relacionado

com o universo e as suas adversidades, em que os inimigos do utilizador são meteoritos que caem

em períodos de tempo nas cores impossibilitando de as obter e acabar o nível. A Figura 4.28

como se pode observar é a fase de obter a cor verde para completar a sequência da esfera e

assim procurar a maneira de trocar para o último sólido que será o cone.

Na Figura 4.30 vê-se uma estrela que é o objeto que permite após colisão trocar de imediato de

sólido em que o módulo python TrocarFig é o responsável para esse efeito e pode ser analisado

no Anexo 11. A estrela possui uma animação no eixo dos Y que desce até á plataforma de modo

a que a esfera a consiga atingir e que deixa de existir assim que a troca se realiza.

Figura 4.29 – Última plataforma (Perseguição e Universo) Figura 4.28 – Última plataforma na câmara da esfera

Figura 4.30 – Estrela

33

Entretanto os meteoritos já iniciaram a sua contagem para caírem sobre as cores para

impossibilitar a obtenção das cores pelos sólidos. A lógica implementada para o conseguir é

apresentada na Figura 4.31.

Quando a esfera colide com a plataforma que possui uma propriedade timer, vinda do

teletransporte faz reiniciar o tempo e assim se inicia uma contagem com os tempos

estabelecidos na Figura 4.31.Quando o valor do timer atingir os 8,22,30,35 segundos os planos

que suportam os meteoritos desaparecem e que os irá fazer cair sobre as respetivas cores,

cabendo ao utilizador obtê-las a todas antes dos meteoritos as “destruírem”. (Anexo 13)

Tudo isto é uma combinação da máquina de estados do BGE, em que os restantes estados e um

exemplo de uma script responsável por desativar as cores se encontram no Anexo 12. (Guedes

2015)

Feita a troca de sólidos, entra em jogo o cone que tem por objetivo pintar as restantes cores que

sobram pela ordem correta e terminar o jogo, no entanto o meteorito que está no centro da

plataforma começa a sua perseguição ao cone dificultando o seu objetivo como demonstra a

Figura 4.32.

Figura 4.31 – Lógica da plataforma

Figura 4.32 – Perseguição

34

A lógica para a implementação do último inimigo do jogo é mostrada no Anexo 14, mas o

módulo python switch2 do Anexo 11 é o controlador de todo o processo. É enviada uma

mensagem num sensor para um estado que se encontra em espera para ser ativado por um

sensor delay, que conectado ao módulo irá por sua vez ativar um atuador steering que serve

para perseguir objetos até á colisão.

Escapando a todos os perigos e dificuldades que o nível proporcionou ao concluir a sequência

de cores do cone, são iniciadas duas animações, na cor preta que irá permitir a subida (Anexo

15) para a porta de saída do nível que por sua vez contém também uma animação em que se

abrem as portas para a conclusão do nível dois. Essas animações são criadas com mensagens

ligadas a atuadores action que por sua vez são recebidas no cone como sensores property.

A Figura 4.33 representa assim a atuação das animações referidas e a possibilidade de concluir

o nível e o jogo por parte do utilizador.

Figura 4.33 – Finalização do nível e do jogo

35

4.5 Plataforma Mobile Android

Acabado o jogo que foi desenvolvido para PC e para além dos objetivos inicialmente

estabelecidos, com o aconselhamento do nosso orientador pareceu-nos óbvio a partir de uma

certa altura, devido as próprias características do jogo, abordar a parte mobile. Foi então feita

pesquisa sobre este tema no qual se pode retirar algumas conclusões positivas e negativas.

Pelo lado positivo destaca-se o facto de se a pessoa que desenvolver um jogo em Blender não

terá que saber programação android para conseguir fazer rodar o seu jogo num dispositivo,

mas pelo lado negativo pode-se concluir que a programação android em Blender se encontra

numa fase ainda em desenvolvimento pelo que apresenta muitas falhas, entre as quais não

aceitar textura, não aceita logic bricks e muito menos aceita python, o que resulta apenas numa

experimentação muito básica como a da Figura 4.37, em que apenas é apresentado um plano e

um cubo em que não é possível sequer movimentá-lo. As fontes que foram investigadas apenas

conseguem fazer rodar a câmara, e fazer o pressionar num objeto. Essas funções são

desenvolvidas com uma linguagem própria que se pensa ser do OgreKit e do LuaEditor.

Foi decidido seguir uns tutoriais que existem num canal do youtube, que nos pareceu ser o mais

fiável, e que apresentava algum resultado concreto. (hhhnzw 2012) (hhhnzw(touch) 2012)

Foi também iniciada uma thread no blog blenderartists (patrickguedes 2015), que entanto não

foi completamente esclarecedor sobre a possibilidade do desenvolvimento de jogos feitos no

BGE para android.

Seguindo as fontes referidas anteriormente tiveram que ser seguidos alguns passos

importantes:

Download e instalação do addon Gamekit(hhhnzw(addon) 2012)

Download do Lua Editor

Download AppOgrekit

Download e instalação do Eclipse(Network 2015)

Download e instalação do Android SDK(Crafton 2012)

Download e instalação do Android Ecplise Plug-in(Collins 2012)

36

Feitos todos os downloads e instalações, foi criado um projeto no BGE de um cubo com logic

bricks para se mover que se pode ver na Figura 4.35.

Seguindo obrigatoriamente a ordem expressa na Figura 4.35, ir-se-á obter a Figura 4.34 que é

um standalone player do Gamekit, e caso seja aceite, isto é sejam apresentados os objetos

corretamente o jogo poderá ser exportado para um sistema android.

O processo para depois criar um projeto encontra-se no Anexo 16 e que resulta na Figura 4.36.

Figura 4.34 – OgreKit Figura 4.35 – Gamekit

Figura 4.36 – Finalizar projeto

37

Basicamente o processo passa por abrir o eclipse, criar um novo projeto de Android Project from Existing Code no separador Android, de seguida procurar a pasta onde se encontra o projeto Blender no caso GameKit-Android e fazer finish. Para concluir liga-se o dispositivo android ao computador, e basta seguir os passos enumerados na Figura 4.36 que irá resultar então na Figura 4.37.

Figura 4.37 – ScreenShot Android

38

39

Capítulo 5

5 Conclusões

O interesse por este projeto surgiu pelo facto de estar ligado a uma indústria bastante

apelativa, como é a indústria dos vídeo jogos, e com isso entender melhor as etapas de criação

de um jogo assim como os problemas que podem surgir independentemente da plataforma em

que estejamos a trabalhar. Para a sua realização, foi necessário inicialmente um trabalho de

pesquisa e aprendizagem sobre o motor de jogos do Blender assim como a sua linguagem de

scripts python, de maneira a perceber previamente o que poderia ser feito com esta

ferramenta. Com o avanço do projeto e consoante as necessidades do nosso jogo fomos

descobrindo e aplicando novas funcionalidades com o objetivo de o tornar mais apelativo e

desafiante ao utilizador.

O jogo acabou por superar as nossas expetativas inicias, na perspetiva da capacidade do BGE

pela sua robustez, funcionalidades e grafismo.

Nos testes para a plataforma mobile android que foram feitos, pudemos também concluir que

se encontra numa fase inicial do seu desenvolvimento, mas que no entanto poderá com tempo

tornar-se uma maneira eficaz de produção de jogos feitos em Blender para plataformas móveis.

Em suma, estamos muito satisfeitos com o projeto/jogo que conseguimos desenvolver e por

termos conseguido cumprir todos os objetivos que foram traçados ao longo do seu

desenvolvimento, numa perspetiva desafiante dia após dia, de modo a ultrapassar os

obstáculos que fomos encontrando.

5.1 Trabalho Futuro

Assim como em qualquer jogo, também o processo de desenvolvimento nunca estaria acabado

pois há sempre algo que pode ser melhorado ou desenvolvido, como por exemplo: desenvolver

novos níveis e por consequente novos desafios ao jogador, possibilidade de escolher o som

ambiente do jogo, escolher a dificuldade ou puder salvar e carregar o seu próprio “save”.

A parte mobile também poderia ser melhorada pelo que achamos que daria uma boa

continuação para outro possível projeto ou tese de mestrado por ser uma área que se encontra

em expansão e desenvolvimento embora ainda muito primitiva.

40

41

Referências Bibliográficas

Arts, C. (2009). "Blender Engine - Criando um Jogo - 11." from https://vimeo.com/2777215.

Bart. (2014, Dezembro 2014). "Blender production 'I will Escape' debuts next week on Steam." from http://www.blendernation.com/2014/12/15/blender-production-i-will-escape-debuts-next-week-on-steam/.

blender.org. "Desenvolver em Android." from http://wiki.blender.org/index.php/Doc:2.6/Manual/Game_Engine/Android.

blender.org(GameEngine). "Introduction to Game Engine." Retrieved Dezembro 2014, from http://www.blender.org/manual/game_engine/index.html.

blender.org(python). "Python, a Linguagem de Scripts." Retrieved Fevereiro de 2015, from http://wiki.blender.org/index.php/Doc:PT/2.6/Manual/Introduction/Installing_Blender/Python.

blenderartist(Racer). (2015, Janeiro 2015). "BGMC 14 | Fun Kart Racer by Thatimst3r." Retrieved Fevereiro, 2015, from http://blenderartists.org/forum/showthread.php?358916-BGMC-14-Fun-Kart-Racer-by-Thatimst3r.

blenderArtists (2013). "easyEmit - *Update* 13.06.2013."

blenderArtists(Objects) (2015). "Ojects from layers."

Caçador, F. (2014). "Desenvolvimento de videojogos já está a "fervilhar" em Portugal." Retrieved Fevereiro, 2015, from http://tek.sapo.pt/noticias/computadores/desenvolvimento_de_videojogos_ja_esta_a_fervi_1398576.html.

Collins, T. (2012). "Eclipse Android SDK and ADT download and install."

Cookie, B. (2011).

Crafton, D. (2012). "Android SDK Installation (Windows 7 32-Bit)."

Cura, H. (2015, 19 de Fevereiro de 2015). "O rumo que levam os jogos de hoje." pplware, from http://pplware.sapo.pt/jogos/o-rumo-que-levam-os-jogos-de-hoje/.

Esau, A. (2011). "Orbito Gameplay - Blender Game." Retrieved Janeiro, 2015, from https://www.youtube.com/watch?v=ZDNcOy8N9Uo.

Guedes, P. (2015). "Restart time (timer) property."

hhhnzw (2012). "Blender 3D 2.6 & gamekit Android 3D Game Test on Nexus 7."

hhhnzw(addon) (2012). "blender 3D 2.6 Gamekit addon install and test."

hhhnzw(touch) (2012). "Blender 3D gamekit Android 3D openGL touch look on nexus 7."

Manual, B. R. "Game Logic Screen Layout." Retrieved Fevereiro, 2015, from http://www.blender.org/manual/game_engine/screen_layout.html.

Network, C. (2015). "How to Install Latest Eclipse Luna (4.4.1) IDE for Java Developers in Windows 7."

opengl.org "OpenGL Shading Language."

patrickguedes (2015). "Android Game in Blender."

quitchou94. (2010). "[trailer] ColorCube 1.6 [Video File]." Retrieved Dezembro, 2014, from https://www.youtube.com/watch?v=KKK-p1TXW7A.

42

RandomPickle97(CubeInvasion). (2012). "Cube Invasion." from http://blenderartists.org/forum/showthread.php?258250-Cube-Invasion&highlight=cube.

rsl, a. (2014). "Applying Textures in Blender ".

ThaTimst3r "How to Make a Game Menu in the Blender Game Engine."

Wikipédia. (2015, Dezembro 2014). "Blender Institute." Retrieved Fevereiro 2015, from http://pt.wikipedia.org/wiki/Blender_Institute.

Wikipédia(Blender). (2015, Janeiro 2015). "Blender." Retrieved Janeiro, 2015, from http://pt.wikipedia.org/wiki/Blender.

Wikipédia(Cristal). (2015, Fevereiro 2013). "Crystal Space." Retrieved Fevereiro, 2015, from https://pt.wikipedia.org/wiki/Crystal_Space.

Wikipédia(Foundation). (2015, Dezembro 2014). "Blender Foundation." Retrieved Fevereiro, 2015, from http://pt.wikipedia.org/wiki/Blender_Foundation.

Wikipédia(Ton_Roosendaal). (2013, Abril 2013). "Ton Roosendaal." Retrieved Fevereiro, 2015, from http://pt.wikipedia.org/wiki/Ton_Roosendaal.

Wikipédia(YoFrankie). (2015, Novembro 2014). "Yo Frankie!" Retrieved Dezembro 2014, from https://pt.wikipedia.org/wiki/Yo_Frankie!

43

Anexos

timerN0.py import bge def main(): cont = bge.logic.getCurrentController() own = cont.owner cena = cont.actuators ["cena"] tempo = (13 - own ["timeLoad"]) if tempo <= 0: cont.activate(cena) main()

Anexo 1

Anexo 2

44

Anexo 3

45

azulN0.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() cuboNivel0 = scene.objects ["cuboNivel0"] corAzulN0 = scene.objects ["corAzulN0"] azulNivel0 = scene.objects ["azulNivel0"] vermelhoNivel0 = scene.objects ["vermelhoNivel0"] colisao2 = cont.sensors ["colisao2"] cena = cont.actuators ["cena"] if colisao2.positive and azulNivel0 ["azul"] == True: cuboNivel0 ["cubo"] = False cuboNivel0.color = [0,0,1,True] corAzulN0.color = [0,0,1,True] vermelhoNivel0 ["vermelho"] = False cont.activate(cena) main() vermelhoN0.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() cuboNivel0 = scene.objects ["cuboNivel0"] corVermelhaN0 = scene.objects ["corVermelhaN0"] vermelhoNivel0 = scene.objects ["vermelhoNivel0"] azulNivel0 = scene.objects ["azulNivel0"] colisao1 = cont.sensors ["colisao1"] if colisao1.positive and vermelhoNivel0 ["vermelho"] == True: cuboNivel0.color = [1,0,0,True] corVermelhaN0.color = [1,0,0,True] azulNivel0 ["azul"] = True main()

excoramarela.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own = cont.owner TemporizadorPrincipal = scene.objects ["TemporizadorPrincipal"] TemporizadorSec = scene.objects ["TemporizadorSec"] esferaprincipal = scene.objects ["esferaprincipal"] corAmarela = scene.objects ["corAmarela"]

Anexo 5

Anexo 4

46

corAmarelaSec = scene.objects ["corAmarelaSec"] corAmarelaCubo = scene.objects ["corAmarelaCubo"] collision = cont.sensors ["collision"] if collision.positive: esferaprincipal ["prop"] = True esferaprincipal.color = [1,1,0,True] corAmarela.color = [1,1,0,True] corAmarelaSec.color = [1,1,0,True] corAmarelaCubo.color = [1,1,0,True] TemporizadorPrincipal ["timer"] -= 5 TemporizadorSec ["timer"] -= 5 main() trocar.py from bge import logic def switch(cont): cont.actuators['Camera'].object = logic.getCurrentScene().objects['cuboprincipal'] def TrocarFig(cont): scene = logic.getCurrentScene() esferaprincipal = scene.objects ["esferaprincipal"] if cont.sensors['colisao'].positive and esferaprincipal ["prop"] == True: new_obj = scene.addObject("cuboprincipal",esferaprincipal, 0) esferaprincipal.sendMessage("Set_Cam_Cube", "", "CameraCubo") esferaprincipal.endObject() timer.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own = cont.owner TemporizadorPrincipal = scene.objects ["TemporizadorPrincipal"] TemporizadorSec = scene.objects ["TemporizadorSec"] TempCubo = scene.objects ["TempCubo"] cena = cont.actuators ["cena"] tempo = (60 - TemporizadorPrincipal ["timer"]) tempo = (60 - TemporizadorSec ["timer"]) tempo = (60 - TempCubo ["timer"]) tempoJogo = round(tempo ,1) TemporizadorPrincipal.text = str(tempoJogo) TemporizadorSec.text = str(tempoJogo) TempCubo.text = str(tempoJogo) TemporizadorPrincipal.color = (0,0,1,True) TemporizadorSec.color = (0,0,1,True) TempCubo.color = (0,0,1,True) if tempoJogo >= 65: cont.activate(cena) if tempoJogo <= 0: cont.activate(cena) if tempoJogo <=5:

47

TemporizadorPrincipal.color = [1,0,0,True] TemporizadorSec.color = [1,0,0,True] TempCubo.color = [1,0,0,True] main()

força.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own = cont.owner trackTo = cont.actuators ["trackTo"] movement = cont.actuators ["movement"] cubohole = scene.objects ["cubohole"] cuboholeDistance = own.getDistanceTo(cubohole) cont.activate(trackTo) if cuboholeDistance <= 10: cont.activate(movement) else: cont.deactivate(trackTo) cont.deactivate(movement) main() camera2.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own = cont.owner CameraNivel1 = scene.objects ["CameraNivel1"] CameraNivel1Sec = scene.objects ["CameraNivel1Sec"] TemporizadorSec = scene.objects ["TemporizadorSec"] corAmarelaSec = scene.objects ["corAmarelaSec"] corAzulSec = scene.objects ["corAzulSec"] corVermelhaSec = scene.objects ["corVermelhaSec"] corsequencia1Sec = scene.objects ["corsequencia1Sec"] corsequencia2Sec = scene.objects ["corsequencia2Sec"] corsequencia3Sec = scene.objects ["corsequencia3Sec"] if CameraNivel1Sec ["camera"] == True: CameraNivel1Sec.setVisible(1) TemporizadorSec.setVisible(1) corAmarelaSec.setVisible(1) corAzulSec.setVisible(1) corVermelhaSec.setVisible(1) corsequencia1Sec.setVisible(1) corsequencia2Sec.setVisible(1) corsequencia3Sec.setVisible(1) if CameraNivel1Sec ["camera"] == False: CameraNivel1Sec.setVisible(0) TemporizadorSec.setVisible(0)

48

corAmarelaSec.setVisible(0) corAzulSec.setVisible(0) corVermelhaSec.setVisible(0) corsequencia1Sec.setVisible(0) corsequencia2Sec.setVisible(0) corsequencia3Sec.setVisible(0) main()

49

portao.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() Portao = scene.objects ["Portao"] own = cont.owner abre = cont.sensors ["abre"] abrir = cont.actuators ["abrir"] somPorta = cont.actuators ["somPorta"] if Portao ["props"] == True: cont.activate(abrir) cont.activate(somPorta) main()

helice.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own= cont.owner local = True force = [0,1,0] cuboNivel2 = scene.objects ["cuboNivel2"] radar = cont.sensors["radar"] motion = cont.actuators ["motion"] sound = cont.actuators ["sound"] cont.activate(motion) #bge.logic.setLogicTicRate(50) if radar.positive: cuboNivel2.applyForce(force,local) cont.activate(sound) else: cont.deactivate(sound) main()

Anexo 6

Anexo 7

50

PerderEsferaN2.py from bge import logic def vidinha1(cont): scene = logic.getCurrentScene() own = cont.owner esferaNivel2 = scene.objects ["esferaNivel2"] spawn_point2 = scene.objects ["spawn_point2"] spawn_point4 = scene.objects ["spawn_point4"] VidaEsf1 = scene.objects ["VidaEsf1"] VidaEsf12 = scene.objects ["VidaEsf12"] colisao4 = cont.sensors ["colisao4"] colisao5 = cont.sensors ["colisao5"] colisao8 = cont.sensors ["colisao8"] Message = cont.sensors ["Message"] FogoArder = cont.actuators ["FogoArder"] if Message.positive: esferaNivel2.color = [0,0,0,True] cont.activate(FogoArder) else: cont.deactivate(FogoArder) if colisao4.positive or colisao5.positive: esferaNivel2.setVisible(0) esferaNivel2.worldPosition = spawn_point2.worldPosition esferaNivel2.setVisible(1) esferaNivel2 ["lives"] -= 1

Anexo 8

Anexo 9

51

if colisao8.positive: esferaNivel2.setVisible(0) esferaNivel2.worldPosition = spawn_point4.worldPosition esferaNivel2.setVisible(1) esferaNivel2 ["lives"] -= 1 if esferaNivel2 ["lives"] == 2: VidaEsf1.setVisible(0) VidaEsf12.setVisible(0) def vidinha2(cont): scene = logic.getCurrentScene() spawn_point2 = scene.objects ["spawn_point2"] spawn_point4 = scene.objects ["spawn_point4"] own = cont.owner colisao5 = cont.sensors ["colisao5"] esferaNivel2 = scene.objects ["esferaNivel2"] VidaEsf22 = scene.objects ["VidaEsf22"] VidaEsf2 = scene.objects ["VidaEsf2"] if esferaNivel2 ["lives"] == 1: VidaEsf22.setVisible(0) VidaEsf2.setVisible(0) def vidinha3(cont): scene = logic.getCurrentScene() spawn_point2 = scene.objects ["spawn_point2"] spawn_point4 = scene.objects ["spawn_point4"] own = cont.owner colisao5 = cont.sensors ["colisao5"] cena1 = cont.actuators ["cena1"] esferaNivel2 = scene.objects ["esferaNivel2"] VidaEsf32 = scene.objects ["VidaEsf32"] VidaEsf3 = scene.objects ["VidaEsf3"] if esferaNivel2 ["lives"] == 0: VidaEsf32.setVisible(0) VidaEsf3.setVisible(0) cont.activate(cena1)

52

pintarLaranjaN2.py import bge def main(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() own = cont.owner esferaNivel2 = scene.objects ["esferaNivel2"] laranja = scene.objects ["laranja"] azul = scene.objects ["azul"] Port1 = scene.objects ["Port1"] TorusPort1 = scene.objects ["TorusPort1"] CorPintarEsf22 = scene.objects ["CorPintarEsf22"] CorPintarEsf2 = scene.objects ["CorPintarEsf2"] colisao3 = cont.sensors ["colisao3"] if colisao3.positive and laranja ["laranja1"] == True and esferaNivel2 ["prop"] == False: esferaNivel2.color = [255,1,0,1] esferaNivel2 ["prop"] = True CorPintarEsf2.color = [255,1,0,1] CorPintarEsf22.color = [255,1,0,1] azul ["azul1"] = False Port1.setVisible(1) TorusPort1.setVisible(1) main() Teleport.py from bge import logic cont = logic.getCurrentController() own = cont.owner scene = logic.getCurrentScene() obj = scene.objects[own['para']] esferaNivel2 = scene.objects['esferaNivel2'] ambientePlat3 = scene.objects ["ambientePlat3"] if own['Ativa'] == 0 and cont.sensors['colisao1'].positive: esferaNivel2.worldPosition = [obj.worldPosition[0],obj.worldPosition[1],obj.worldPosition[2]+1] obj['Ativa'] = 1 ambientePlat3.setVisible(1)

Anexo 10

53

from bge import logic def switch(cont): cont.actuators["Camera"].object = logic.getCurrentScene().objects["coneNivel2"] def switch2(cont): cont = logic.getCurrentController() own = cont.owner scene= logic.getCurrentScene() coneNivel2 = scene.objects['coneNivel2'] Delay = cont.sensors['Delay'] Follow = cont.actuators['Follow'] if Delay.positive: Follow.target= coneNivel2 cont.activate(Follow) else: cont.deactivate(Follow) def TrocarFig(cont): scene = logic.getCurrentScene() esferaNivel2 = scene.objects ["esferaNivel2"] estrela = scene.objects ["estrela"] if cont.sensors["colisao7"].positive and esferaNivel2 ["prop"] == False: new_obj = scene.addObject("coneNivel2",esferaNivel2, 0) new_obj.worldOrientation = [0,0,0] esferaNivel2.sendMessage("Set_Cam_Cube", "", "CameraSeguirCone") esferaNivel2.sendMessage("Set_Pedra_Cone", "", "meteoro5") esferaNivel2.endObject() estrela.endObject()

Anexo 11

Anexo 12

54

def meteorito3(cont): scene = logic.getCurrentScene() meteoro3 = scene.objects ["meteoro3"] verdeFinal = scene.objects ["verdeFinal"] colisao = cont.sensors ["colisao"] if colisao.positive: verdeFinal ["verde"] = False verdeFinal.color = [0,0,0,True]

Anexo 13

Anexo 14

55

Anexo 15

Anexo 16