UNIVERSIDADE DE LISBOA
Faculdade de Ciências
Departamento de Informática
VIDEO JOGOS EVOLUTIVOS
Rui Guilherme Mendes Esteves Nogueira
PROJECTO
MESTRADO EM ENGENHARIA INFORMÁTICA
Especialização em Arquitetura, Sistemas e Redes de Computadores
2013
UNIVERSIDADE DE LISBOA
Faculdade de Ciências
Departamento de Informática
VIDEO JOGOS EVOLUTIVOS
Rui Guilherme Mendes Esteves Nogueira
PROJECTO
MESTRADO EM ENGENHARIA INFORMÁTICA
Especialização em Arquitetura, Sistemas e Redes de Computadores
Trabalho orientado pelo Prof. Doutor Luís Manuel Ferreira Fernandes Moniz
e pelo Prof. Doutor Paulo Jorge Cunha Vaz Dias Urbano
2013
Agradecimentos
Em primeiro lugar, gostaria de agradecer aos melhores Pais do mundo, que com
muito amor, esforço e dedicação sempre me mantiveram no bom caminho (a bem ou a
mal), sem que nunca nada me faltasse. Agradeço aos meus dois irmãos, Raquel e David
que sempre foram uma inspiração a seguir e são o motivo do meu maior orgulho. Aos
meus tios, que nunca conseguirei agradecer por tudo o que fizeram por mim. Aos meus
avós, que nunca deixaram e nunca deixaram de estar presentes na minha vida.
Quero agradecer ao meu amigo e colega João Gomes, que não só fez a loucura de
aceitar o meu desafio de vir fazer o mestrado comigo, como me acompanhou durante
este longo e tortuoso caminho, e que apesar dos brutais sacrifícios que tivemos de fazer
nunca vacilou. Nunca teria chegado até aqui sem o teu apoio e companheirismo.
Agradeço aos meus dois orientadores Prof. Luís Moniz e ao Prof. Paulo Urbano por
me orientarem neste projeto e se mostrarem sempre disponíveis para ajudar e contribuir
para o sucesso deste. Em especial, ao Prof. Luís Moniz, que sempre que precisei
encontrei uma porta aberta e uma disponibilidade e apoio louváveis.
Ao meu grande amigo, colega do “JACK ASS” e parceiro do crime, Hélder Gil,
pela sua amizade ao longo destes anos todos.
Agradeço aos meus amigos de faculdade, que durante a licenciatura colaboraram
comigo no estudo e na execução de dezenas de projetos e noitadas loucas de estudo.
Agradeço em particular ao Alentejano, Gadelhudo, Partnere, Gordo, Mais velho, Pato,
Diogo Simões, Eduardo, Reis e Rui Teixeira. A vossa amizade e o companheirismo que
construímos durante este tempo foram muito importantes para mim e que nunca irei
esquecer. A dedicação e espírito de grupo fantástico que empregamos em tudo o que
fizemos, apoiando-nos e motivando-nos uns aos outros, resultou num percurso
académico exemplar à custa também de muito esforço e dedicação.
Aos meus colegas de trabalho que me apoiaram e me ajudaram todos os dias da
semana, todas as semanas do mês e todos os meses do ano…
Por fim, mas de maneira nenhuma menos importante, pelo contrário, um muito
obrigado à minha amiga, confidente, amante, paixão e namorada Marlene de Jesus. Que
devido à minha falta de tempo, sacrificou-se e me aturou ao longo destes anos todos.
Nunca poderei compensar o teu apoio, dedicação e sorriso, que nunca me deixaram
fraquejar. Pronto…também agradeço aos gatos…Mojo Jojo Smeagol e Leia Chacha -
As Bestas da Destruição!
A todos estes e aos demais que de alguma forma direta ou indireta possam ter
contribuído para o meu sucesso, o meu mais sincero obrigado!
A todos aqueles que não são especialmente dotados ou talentosos, mas que possuem
algo bem mais valioso, perseverança e força de vontade…
i
Resumo
Num jogo de computador, o requisito mais básico de um agente artificial é ser
capaz de navegar no ambiente do jogo. O sistema de navegação é responsável por
fornecer o melhor caminho entre dois pontos no ambiente e pela movimentação do
agente através do caminho com a possibilidade de correção e redefinição do mesmo.
Este trabalho propõe um processo de geração automática da representação espacial de
ambientes de jogo dinâmicos suportados em grelha, procura do melhor caminho e
movimentação do agente artificial ao longo do caminho
Palavras-chave: Jogos de vídeo, geração processual de conteúdo, representação do
ambiente, grafos de navegação, grafos em grelha, quadtree, algoritmos de procura A*,
algoritmos de procura Fringe Search, inteligência artificial.
ii
iii
Abstract
In a computer game, the most basic requirement of a non-player character is to
be able to navigate through the game environment. The navigation system has to
provide the best path between to points in the environment, the actual movement
through the path and deal with eventual correction and redefinition of the path. Our
proposal is to design a process to generate a grid supported by the spatial representation
of a dynamic environment, search for the best path, and construct the movement
sequence of a NPC over the path.
Keywords: Video games, procedural content generation, environment representation,
navigation graphs, graphs based on grid, quadtree, search algorithms A*, Fringe search,
artificial intelligence.
iv
v
Conteúdo
Capítulo 1 Introdução............................................................................................ 1
1.1 Motivação ................................................................................................... 1
1.2 Objetivos ..................................................................................................... 2
1.3 Contribuições .............................................................................................. 3
1.4 Enquadramento institucional ...................................................................... 4
1.5 Organização do documento ........................................................................ 4
1.6 Sumário ....................................................................................................... 5
Capítulo 2 Trabalho relacionado ........................................................................... 6
2.1 Geração processual de conteúdo................................................................. 6
2.1.1 Vantagens ............................................................................................ 7
2.1.2 Desvantagens ....................................................................................... 8
2.1.3 Aproximações híbridas ........................................................................ 8
2.1.4 Características ..................................................................................... 9
2.2 Sistema de navegação ............................................................................... 12
2.2.1 Locomoção ........................................................................................ 12
2.2.2 Representação do ambiente ............................................................... 13
2.2.3 Algoritmos de procura em grafos ...................................................... 30
2.3 Sumário ..................................................................................................... 35
Capítulo 3 Metodologia de investigação ............................................................. 38
3.1 Delineamento do estudo ........................................................................... 38
3.1.1 Questões e hipóteses de investigação ................................................ 38
3.2 Material e Métodos ................................................................................... 40
3.2.1 Caracterização da amostra ................................................................. 40
3.2.2 Instrumentos ...................................................................................... 42
3.2.3 Procedimentos ................................................................................... 51
3.2.4 Metodologia estatística ...................................................................... 52
3.3 Sumário ..................................................................................................... 52
vi
Capítulo 4 Trabalho realizado ............................................................................. 53
4.1 Análise do problema ................................................................................. 53
4.1.1 Geração automática e em tempo de execução de grafos ................... 54
4.1.2 Ambientes de jogo com dimensões diferentes .................................. 54
4.1.3 Múltiplos agentes .............................................................................. 55
4.1.4 Diferentes tipos de unidades ............................................................. 56
4.1.5 Deteção de obstáculos dinâmicos ...................................................... 56
4.2 Desenho da solução .................................................................................. 57
4.2.1 Sistema de navegação........................................................................ 57
4.3 Implementação.......................................................................................... 60
4.3.1 Sistema de navegação........................................................................ 61
4.3.2 Ferramenta de prova de conceito ...................................................... 87
4.3.3 Ferramenta de avaliação .................................................................... 89
4.4 Sumário ..................................................................................................... 92
Capítulo 5 Resultados ......................................................................................... 93
5.1 Apresentação de resultados ...................................................................... 94
5.1.1 Inicialização da camada de representação do ambiente .................... 94
5.1.2 Inicialização da camada de procura de caminhos ............................. 97
5.1.3 Adição de objetos antes do início do jogo ...................................... 101
5.1.4 Tamanho do espaço de pesquisa ..................................................... 104
5.1.5 Quantização ..................................................................................... 105
5.1.6 Localização...................................................................................... 109
5.1.7 Procura de caminho ......................................................................... 111
5.1.8 Conexão de vizinhos ....................................................................... 124
5.1.9 Adição de objeto.............................................................................. 127
5.2 Sumário ................................................................................................... 128
Capítulo 6 Discussão de resultados e conclusão ............................................... 130
6.1 Discussão de resultados .......................................................................... 130
6.2 Conclusão ............................................................................................... 134
vii
6.3 Limitações .............................................................................................. 135
6.4 Trabalho futuro ....................................................................................... 136
Bibliografia ........................................................................................................... 137
viii
ix
Lista de Figuras
Ilustração 1 - Sistema de navegação e as suas componentes. ..................................................................... 12 Ilustração 2 - Ambiente de jogo base. ........................................................................................................ 15 Ilustração 3 - Grafo de navegação baseado em pontos de passagem. ......................................................... 17 Ilustração 4 - Grafo de navegação baseado em pontos de visibilidade. ...................................................... 19 Ilustração 5 - Grafo de navegação baseado em pontos de visibilidade com geometria expandida. ............ 20 Ilustração 6 - Geometria das conexões das células em grelha. ................................................................... 21 Ilustração 7 - Grafo de navegação baseado em grelha com células quadradas. .......................................... 22 Ilustração 8 - Grafo de navegação baseado em grelha com células hexagonais. ........................................ 22 Ilustração 9 - Quadrantes e quadtree correspondente. ................................................................................ 24 Ilustração 10 - Grafo de navegação baseado em quadtree. ......................................................................... 26 Ilustração 11 - Grafo de navegação baseado em quadtree inválido. ........................................................... 27 Ilustração 12 - Ambiente de jogo subdividido em polígonos navegáveis. .................................................. 28 Ilustração 13 - Grafo de navegação baseado em malha de navegação. ...................................................... 28 Ilustração 14 - Algoritmo de procura Dijkstra's. ........................................................................................ 32 Ilustração 15 - Algoritmo de procura melhor-primeiro. ............................................................................. 32 Ilustração 17 - Algoritmo de procura A*. ................................................................................................... 33 Ilustração 18 - Logotipo do Blender. .......................................................................................................... 43 Ilustração 19 - Logotipo do jMonkey Engine ............................................................................................. 44 Ilustração 19 - Logotipo do Ogre. .............................................................................................................. 44 Ilustração 20 - Logotipo do Panda3D. ........................................................................................................ 45 Ilustração 21 - Logotipo do Torque Game Engine. .................................................................................... 46 Ilustração 22 - Logotipo do Unreal Development Kit. ............................................................................... 46 Ilustração 23 - Logotipo do Unity. ............................................................................................................. 47 Ilustração 24 - Menu de configuração. ....................................................................................................... 50 Ilustração 26 - Arquitetura subdividida em três módulos distintos. ........................................................... 61 Ilustração 26- Exemplo de abstração multidimensional da grelha e atribuição de Id's para cada célula. ... 71 Ilustração 27 - Exemplo de abstração linear da grelha e atribuição de Id's para cada célula. ..................... 72 Ilustração 28 - Determinação de vizinhos do nó (i, j). ................................................................................ 73 Ilustração 29 - Disposição dos vizinhos do nó (i, j) num array linear. ....................................................... 73 Ilustração 31 – Conversão do número Morton (Id) na coordenada x e z .................................................... 77 Ilustração 32 - Simulação de 600 NPC’s com esquema de divisão baseado em Grelha e algoritmo de
procura A*. ................................................................................................................................................. 89 Ilustração 33 - Simulação de 2 NPC’s com o esquema de divisão baseado em quadtree e algoritmo de
procura Fringe Search. ............................................................................................................................... 89 Ilustração 34 - Média do tempo de processamento na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente. ...................................................................... 95 Ilustração 35 - Gráfico do consumo de memória na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente. ...................................................................... 96 Ilustração 36 - Gráfico do tempo de processamento na inicialização da camada do algoritmo de procura
em grafos: Algoritmo de procura em grafos Vs. Dimensão do ambiente. .................................................. 98 Ilustração 37 - Gráfico do tempo de processamento na inicialização da camada do algoritmo de procura
em grafos no modo de execução com threadpool: Algoritmo de procura em grafos Vs. Dimensão do
ambiente. .................................................................................................................................................. 100 Ilustração 38 – Gráfico da média do consumo do tempo de processamento na adição de objetos antes da
execução do jogo: Esquema de divisão Vs. Dimensão do ambiente. ....................................................... 102 Ilustração 39 - Gráfico da média do consumo do tempo de processamento na adição de objetos antes da
execução do jogo no modo de execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
.................................................................................................................................................................. 103 Ilustração 40 - Gráfico da média do tamanho do espaço de procura: Esquema de divisão Vs. Dimensão do
ambiente. .................................................................................................................................................. 105 Ilustração 41 - Gráfico da média do tempo de processamento na localização: Esquema de divisão Vs.
Dimensão do ambiente. ............................................................................................................................ 106 Ilustração 42 - Gráfico da média do tempo de processamento na localização: Esquema de divisão Vs.
Densidade de objetos. ............................................................................................................................... 107 Ilustração 43 - Gráfico da média do tempo de processamento na quantização no modo de execução com
threadpool: Esquema de divisão Vs. Dimensão do ambiente................................................................... 108
x
Ilustração 44 - Gráfico da média do tempo de processamento na quantização no modo de execução com
threadpool: Esquema de divisão Vs. Densidade de objetos. .................................................................... 109 Ilustração 45 - Gráfico da média do tempo de processamento na localização: Esquema de divisão Vs.
Dimensão do ambiente. ............................................................................................................................ 110 Ilustração 46 - Gráfico da média do tempo de processamento na localização no modo de execução com
threadpool: Esquema de divisão Vs. Dimensão do ambiente................................................................... 111 Ilustração 47 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho: Esquema
de divisão Vs. Dimensão do ambiente. ..................................................................................................... 113 Ilustração 48 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho: Algoritmo
de procura Vs. Dimensão do ambiente. .................................................................................................... 113 Ilustração 49 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho: Algoritmo
de procura Vs. Densidade de objetos. ....................................................................................................... 114 Ilustração 50 – Gráfico da média dos resultados do nº de nós expandidos na procura de caminho:
Esquema de divisão Vs. Dimensão do ambiente. ..................................................................................... 116 Ilustração 51 - Média dos resultados do nº de nós expandidos na procura de caminho: Algoritmo de
procura Vs. Dimensão do ambiente. ......................................................................................................... 116 Ilustração 52- Gráfico da média do tempo de processamento na procura de caminho no modo de
execução: Esquema de divisão Vs. Dimensão do ambiente. .................................................................... 118 Ilustração 53 - Gráfico da média do tempo de processamento na procura de caminho: Esquema de divisão
Vs. Densidade de objetos. ........................................................................................................................ 119 Ilustração 54 – Gráfico da média dos resultados do tempo de processamento na procura de caminho:
Algoritmo de procura Vs. Dimensão do ambiente. .................................................................................. 120 Ilustração 55 – Gráfico da média dos resultados do tempo de procura de caminho: Algoritmo de procura
Vs. Densidade de objetos. ........................................................................................................................ 120 Ilustração 56 - Gráfico da média dos resultados do tempo de processamento na procura de caminho:
Esquema de divisão Vs. Dimensão do ambiente no modo de execução com threadpool. ....................... 122 Ilustração 57 - Gráfico da média dos resultados do tempo de procura de caminho: Esquema de divisão Vs.
Densidade de objetos no modo de execução com threadpool. ................................................................. 122 Ilustração 58 - Gráfio da média dos resultados do tempo de processamento na procura de caminho no
modo de execução com threadpool: Algoritmo de procura Vs. Dimensão do ambiente. ......................... 123 Ilustração 59 - Gráfico da média dos resultados do tempo de procura de caminho no modo de execução
com threadpool: Algoritmo de procura Vs. Densidade de objetos. .......................................................... 124 Ilustração 60 - Gráfico da média do tempo de processamento da conexão de vizinhos: Esquema de divisão
Vs. Dimensão do ambiente. ...................................................................................................................... 125 Ilustração 61 - Gráfico da média do tempo de processamento da conexão de vizinhos no modo de
execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente. .......................................... 126
xi
xii
Lista de Tabelas
Tabela 1 - Esquema de divisão de grafos de navegação baseados pontos de visibilidade. ......................... 19 Tabela 2 - Esquema de divisão de grafos de navegação baseados em grelha. ............................................ 23 Tabela 3 - Esquema de divisão de grafos de navegação baseados em grelha. ............................................ 26 Tabela 4 - Esquema de divisão de grafos de navegação baseados em malha de navegação. ..................... 29 Tabela 5 - Tamanho mínimo da célula e número máximo de nós com base no tamanho do ambiente. ..... 40 Tabela 6 - Tamanho do ambiente e densidade de objetos no ambiente de jogo. ........................................ 41 Tabela 7 - Objetivos vs. tipo de esquema de divisão. ................................................................................. 59 Tabela 8 - Lista de atributos físicos de um NPC usados pela camada de locomoção. ................................ 62 Tabela 9 - Lista de atributos de procura de caminho de um NPC usados pela camada de locomoção. ...... 63 Tabela 10 - Lista de atributos comportamentais de um NPC usados pela camada de locomoção. ............. 63 Tabela 11 - Lista de variáveis auxiliares usadas na camada locomoção. ................................................... 64 Tabela 12 - Pseudo-código da rotina de pedido de resolução de caminho da camada locomoção. ............ 65 Tabela 13 - Pseudo-código do ouvinte de eventos de resposta de caminhos da camada locomoção. ........ 66 Tabela 14 - Pseudo-código da rotina de determinação do próximo movimento do NPC. .......................... 67 Tabela 15 - Métodos suportados pelo gestor da camada de representação do ambiente. ........................... 68 Tabela 16 - Quadrantes e código de orientação. ......................................................................................... 77 Tabela 17 - Lista de atributos do gestor da camada de algoritmos de procura em grafos. ......................... 79 Tabela 18 - Lista de métodos do gestor da camada de algoritmos de procura em grafos. .......................... 80 Tabela 19 - Lista de atributos do algoritmo de procura em grafos genérico............................................... 81 Tabela 20 - Lista de métodos do algoritmo de procura em grafos genérico. .............................................. 81 Tabela 21 - Lista de atributos da estrutura de pedido de resolução de caminho. ........................................ 82 Tabela 22 - Lista de atributos da estrutura de resposta de resolução de caminho. ..................................... 82 Tabela 23 - Pseudo-código do método FindPath para o algoritmo de procura em grafos A* .................... 84 Tabela 24 - Pseudo-código do método DoIteration para o algoritmo de procura em grafos A* ................ 84 Tabela 25 - Pseudo-código do método FindPath para o algoritmo de procura em grafos Fringe Search* 85 Tabela 26 - Pseudo-código do método DoIteration para o algoritmo de procura em grafos Fringe Search*
.................................................................................................................................................................... 87 Tabela 27 - Parâmetros que compõe uma entrada do ficheiro XML. ......................................................... 90 Tabela 28 - Operações suportadas pela ferramenta de avaliação................................................................ 91 Tabela 29 - Especificação de ambiente de testes. ....................................................................................... 93 Tabela 30 - Resultados do tempo de processamento na inicialização da camada de representação do
ambiente. .................................................................................................................................................... 94 Tabela 31 - Média do tempo de processamento na inicialização da camada de representação do ambiente:
Esquema de divisão Vs. Dimensão do ambiente. ....................................................................................... 94 Tabela 32 - Resultados do consumo de memória na inicialização da camada de representação do
ambiente. .................................................................................................................................................... 95 Tabela 33 - Média do consumo de memória na inicialização da camada de representação do ambiente:
Esquema de divisão Vs. Dimensão do ambiente. ....................................................................................... 95 Tabela 34 - Resumo dos resultados da inicialização da camada de representação do ambiente no modo de
execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente. ............................................ 96 Tabela 35 - Resultados do tempo de processamento na inicialização da camada de procura de caminhos.
.................................................................................................................................................................... 97 Tabela 36 - Média do tempo de processamento na inicialização camada de procura de caminhos:
Algoritmo de procura em grafos Vs. Dimensão do ambiente. .................................................................... 97 Tabela 37 - Resultados do consumo de memória na inicialização da camada de procura de caminhos. .... 98 Tabela 38 - Média os resultados do consumo de memória na inicialização da camada de procura de
caminhos. .................................................................................................................................................... 98 Tabela 39 - Resultados do tempo de processamento na inicialização da camada de procura de caminhos
no modo de execução com threadpool. ...................................................................................................... 99 Tabela 40- Média do tempo de processamento na inicialização da camada de procura de caminhos no
modo de execução com threadpool: Algoritmo de procura vs. dimensão do ambiente de jogo................. 99 Tabela 41 - Resultados do consumo de memória na inicialização da camada de procura de caminhos no
modo de execução com threadpool. ......................................................................................................... 100 Tabela 42 – Média dos resultados do consumo de memória na inicialização da camada de procura de
caminhos no modo de execução com threadpool. .................................................................................... 100 Tabela 43 - Resultados do tempo de processamento na adição de objetos antes do início do jogo. ......... 101
xiii
Tabela 44 - Média do consumo do tempo de processamento na adição de objetos antes do início do jogo:
Esquema de divisão Vs. Dimensão do ambiente. ..................................................................................... 101 Tabela 45 - Média do tempo de processamento na adição de objetos antes do início do jogo: Esquema de
divisão Vs. Densidade de objetos. ............................................................................................................ 101 Tabela 46 - Resultados do tempo de processamento na adição de objetos antes do início do jogo no modo
de execução com threadpool. ................................................................................................................... 102 Tabela 47 - Média do tempo de processamento na adição de objetos antes do início do jogo no modo de
execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente. .......................................... 103 Tabela 48- Média do tempo de processamento na adição de objetos antes do início do jogo no modo de
execução com threadpool: Esquema de divisão Vs. Densidade de objetos. ............................................. 103 Tabela 49 - Número máximo de nós por dimensão de ambiente e por densidade de objetos ................... 104 Tabela 50 - Resultados do tamanho do espaço de pesquisa...................................................................... 104 Tabela 51 – Média dos resultados do tamanho do espaço de pesquisa: Esquema de divisão Vs. Dimensão
do ambiente. ............................................................................................................................................. 104 Tabela 52 - Resultados do tempo de processamento na quantização. ...................................................... 105 Tabela 53 – Média dos resultados do tempo de processamento na quantização: Esquema de divisão Vs.
Dimensão do ambiente. ............................................................................................................................ 105 Tabela 54 - Média dos resultados do tempo de processamento na quantização: Esquema de divisão Vs.
Densidade de objetos. ............................................................................................................................... 106 Tabela 55 - Resultados do tempo de processamento na quantização no modo de execução threadpool. . 107 Tabela 56 – Média dos resultados do tempo de processamento na quantização no modo de execução com
threadpool: Esquema de divisão Vs. Dimensão do ambiente................................................................... 107 Tabela 57 - Média dos resultados do tempo de processamento na quantização no modo de execução com
threadpool: Esquema de divisão Vs. Densidade de objetos. .................................................................... 108 Tabela 58 - Resultados do tempo de processamento na localização. ........................................................ 109 Tabela 59 – Média dos resultados do tempo de processamento na localização: Esquema de divisão Vs.
Dimensão do ambiente. ............................................................................................................................ 110 Tabela 60 - Resultados do tempo de processamento na localização no modo de execução com threadpool.
.................................................................................................................................................................. 111 Tabela 61 - Média dos resultados do tempo de processamento na localização no modo de execução com
threadpool: Esquema de divisão Vs. Dimensão do ambiente................................................................... 111 Tabela 62 - Nº nós visitados na procura de caminho. ............................................................................... 112 Tabela 63 - Média dos resultados do nº de nos visitados na procura de caminho: Esquema de divisão Vs.
Dimensão do ambiente. ............................................................................................................................ 112 Tabela 64 - Média dos resultados do nº de nos visitados na procura de caminho: Algoritmo de procura Vs.
Dimensão do ambiente. ............................................................................................................................ 112 Tabela 65 - Média dos resultados do nº de nos visitados na procura de caminho: Algoritmo de procura Vs.
Densidade de objetos. ............................................................................................................................... 113 Tabela 66 - Média dos resultados: Esquema de divisão vs. Algoritmo de procura .................................. 114 Tabela 67 - Nº nós expandidos na procura de caminho. ........................................................................... 115 Tabela 68 - Média dos resultados do nº de nós expandidos na procura de caminho: Esquema de divisão
Vs. Dimensão do ambiente. ...................................................................................................................... 115 Tabela 69 - Média dos resultados do nº de nós expandidos na procura de caminho: Algoritmo de procura
Vs. Dimensão do ambiente. ...................................................................................................................... 115 Tabela 70 – Custo e tamanho do caminho na procura de caminho........................................................... 117 Tabela 71 - Resultados do tempo de processamento na procura de caminho. .......................................... 117 Tabela 72 – Média dos resultados do tempo de processamento na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente. ......................................................................................................... 117 Tabela 73 - Média dos resultados do tempo de procura de caminho: Esquema de divisão Vs. Densidade de
objetos. ..................................................................................................................................................... 117 Tabela 74 – Média dos resultados do tempo de processamento na procura de caminho: Algoritmo de
procura Vs. Dimensão do ambiente. ......................................................................................................... 119 Tabela 75 - Média dos resultados do tempo de procura de caminho: Algoritmo de procura Vs. Densidade
de objetos. ................................................................................................................................................. 119 Tabela 76 - Resultados do tempo de processamento na procura de caminho no modo de execução
threadpool. ............................................................................................................................................... 121 Tabela 77 – Média dos resultados do tempo de processamento na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente no modo de execução threadpool. ................................................... 121 Tabela 78 - Média dos resultados do tempo de procura de caminho: Esquema de divisão Vs. Densidade de
objetos no modo de execução com threadpool. ........................................................................................ 121
xiv
Tabela 79 – Média dos resultados do tempo de processamento na procura de caminho no modo de
execução com threadpool: Algoritmo de procura Vs. Dimensão do ambiente. ....................................... 122 Tabela 80 - Média dos resultados do tempo de procura de caminho no modo de execução com threadpool:
Algoritmo de procura Vs. Densidade de objetos. ..................................................................................... 123 Tabela 81 - Resultados do tempo de processamento na conexão de vizinhos. ......................................... 124 Tabela 82 - Média dos resultados na conexão de vizinhos: Esquema de divisão Vs. Dimensão do
ambiente. .................................................................................................................................................. 125 Tabela 83 - Resultados do tempo de processamento na conexão de vizinhos no modo de execução com
threadpool. ............................................................................................................................................... 126 Tabela 84 – Média de resultados do tempo de processamento na conexão de vizinhos no modo de
execução com threadpool. ........................................................................................................................ 126 Tabela 85 - Resultados do tempo de processamento de adição de objeto. ............................................... 127 Tabela 86 - Média dos resultados de adição de objeto: Esquema de divisão Vs. Dimensão do ambiente.
.................................................................................................................................................................. 127 Tabela 87 - Média dos resultados do tempo adição de objeto: Esquema de divisão Vs. Densidade de
objetos. ..................................................................................................................................................... 127 Tabela 88 - Resultados do tempo de processamento de adição de objeto no modo de execução com
threadpool. ............................................................................................................................................... 128 Tabela 89 – Média dos resultados do tempo de processamento de adição de objeto no modo de execução
com threadpool: Esquema de divisão Vs. Dimensão do ambiente. .......................................................... 128
xv
xvi
Lista de Equações
Equação 1 - Cálculo do custo de n. ............................................................................................................ 33 Equação 2 – Tamanho do espaço de procura em grelhas. .......................................................................... 70 Equação 3 - Profundidade máxima em quadtree. ....................................................................................... 70 Equação 4 – Tamanho mínimo da célula em quadtree. .............................................................................. 71 Equação 5 – Id em grelha. .......................................................................................................................... 72 Equação 6 - Obtenção da coluna através do Id. .......................................................................................... 72 Equação 7 - Obtenção da coluna através da coordenada x. ........................................................................ 72 Equação 8 - Obtenção da linha através do Id. ............................................................................................ 72 Equação 9 - Obtenção da linha através da coordenada z. ........................................................................... 73 Equação 10 – Obtenção da coordenada x. .................................................................................................. 74 Equação 11 - Obtenção da coordenada z. ................................................................................................... 74 Equação 12 - Determinação do espaço de procura numa Quadtree. ........................................................... 76 Equação 12 - Determinação de Id de um nó da quadtree. .......................................................................... 78 Equação 14 – Obtenção de h(n). ................................................................................................................. 85
1
Capítulo 1
Introdução
1.1 Motivação
Cada vez mais os jogos de vídeo têm-se assumido como o instrumento preferido de
diversão do ser humano, abrangendo uma faixa etária cada vez mais alargada. Da guerra
à estratégia, passando pelo desporto e pela aventura, a aproximação do mundo virtual
dos jogos de vídeo à realidade é cada vez maior. Os jogos de vídeo não só
disponibilizam um leque alargado de escolhas, como também a forma a que chegam ao
utilizador é bastante diversificada (computador pessoal, telemóveis, televisão
inteligente, baseados na web, entre outros). O facto de uma grande variedade de meios
digitais poderem ser usados para disponibilizar e comercializar jogos de vídeo, levou a
que no ano de 2012, a comercialização de vídeo jogos tenha ultrapassado os lucros da
indústria de cinema de Hollywood, com uma previsão de aumento de lucros para os
próximos anos. Ao sucesso dos jogos de vídeo comerciais, está ligada à sua capacidade
de diversão, que depende da sua jogabilidade e do seu realismo, e é também
consequência direta da qualidade da imersão e experiência de jogo proporcionada ao
utilizador.
O desenvolvimento de um vídeo jogo comercial demora bastante tempo e implica
um investimento de milhões de euros. A maior parte do tempo de desenvolvimento é
despendida na criação de cenários realistas e de mecânicas de jogo. O aumento da
exigência dos consumidores por conteúdos multimédia de larga escala, sem que seja
comprometido o detalhe gráfico e o realismo, obrigam a indústria de desenvolvimento
de jogos a procurar formas alternativas de desenvolvimento e distribuição, para isso, é
necessário automatizar processos e diminuir o tempo de desenvolvimento. As técnicas
de geração processual de conteúdo (PCG) têm-se destacado como uma alternativa na
geração automática de conteúdos em larga escala e a baixo preço. A sua oferta de
conteúdos em quantidade, qualidade e diversidade é quase ilimitada. Contudo, não basta
apenas gerar conteúdos, é necessário continuar a assegurar o realismo e a jogabilidade
do jogo de vídeo.
2
Deste modo, a inteligência artificial de um jogo torna-se um fator preponderante no
realismo e jogabilidade, uma vez que grande parte do sucesso dos jogos de vídeo está
ligada à satisfação do jogador de “ganhar à máquina” e, mais atualmente, a cooperação
com esta para alcançar e superar objetivos (Kishimoto & Artificial, 2004). É necessário
então assegurar que os agentes inteligentes artificiais (Jogadores Não Humano – Non
Player Character - NPC) consigam interagir corretamente com os conteúdos gerados
pela PCG, principalmente se o conteúdo gerado é um cenário.
O NPC tem como requisito básico, movimentar-se corretamente dentro do
ambiente de jogo, recorrendo ao sistema de navegação para isso. O sistema de
navegação de um NPC pode ser dividido em dois componentes principais: a locomoção,
responsável pelo movimento físico do agente no ambiente do jogo; e o pathfinding,
responsável pela procura de caminhos válidos entre dois pontos. Este último
componente, pathfinding, pode ser decomposto em duas componentes: a representação
do ambiente de jogo e as técnicas de procura de caminho (Anguelov, 2011).
O problema do pathfinding é comum a outras áreas de estudo, tais como a de redes
e a de robótica. Contudo, enquanto os fundamentos da representação do ambiente são
similares, as técnicas de procura estão sujeitas aos requisitos de tempo real de múltiplos
agentes resultando no aumento de limitações a este problema (Anguelov, 2011).
Apesar de existir uma literatura alargada sobre pathfinding, esta não está
direcionada para a representação do meio ambiente e à procura de caminhos em
ambientes sem processamento prévio e dinâmico.
1.2 Objetivos
O principal objetivo deste estudo é explorar e rever um conjunto de técnicas de
pathfinding que possam ser aplicadas de forma automática (sem qualquer intervenção
do jogador ou programador), e as quais ofereçam um desempenho suficiente para serem
usadas em tempo de execução, com vista à navegação de agentes artificiais. É
pretendido, desta forma, suportar a geração processual no momento de ambientes de
jogos de vídeo.
A solução deve ainda cumprir com os seguintes requisitos principais:
suportar múltiplos agentes;
suportar diferentes tamanhos de ambientes de jogo, sem aparente redução do
desempenho do jogo de vídeo;
possibilitar a deteção de obstáculos estáticos e dinâmicos.
Foi ainda estabelecido como requisitos secundários que a solução explorada deve:
3
suportar ambientes de relevo diferenciado;
suportar diferentes tipos de unidades (ex.: agentes de diferente tamanho).
Os objetivos e requisitos desta investigação limitam consideravelmente as técnicas
que podem ser utilizadas. Embora possam ser feitas algumas alterações e melhorias às
técnicas empregues, não é o objetivo deste estudo inovar qualquer técnica em particular,
mas sim articular um conjunto de "técnicas de estado da arte" e verificar e comparar os
seus resultados, de acordo com os objetivos e requisitos descritos. Tendo em conta que
não é possível encontrar uma solução geral ideal para todos os casos, é objetivo deste
estudo o desenvolvimento de uma solução que possa ser empregue de forma satisfatória
à generalidade das situações.
1.3 Contribuições
A contribuição primária deste estudo é a compreensão sobre a problemática da
navegação de agentes em ambientes de jogo dinâmicos, e com cenários de diferentes
dimensões, em que a impossibilidade de usar técnicas que envolvem pré-processamento
agrava consideravelmente o problema de gerir a navegação de agentes em ambientes de
grande dimensão. Este desafio assume uma maior relevância quando se observa que,
ano após ano, os ambientes de jogo aumentam em detalhe visual, tamanho e
complexidade.
Por outro lado, o objetivo de suportar a geração processual de conteúdos (PCG)
nomeadamente de ambientes de jogos de vídeo, procura:
diminuir o tempo e custos envolvidos no desenvolvimento dos jogos de vídeo;
aumentar a longevidade e variedade de jogos;
suportar novos paradigmas da tecnologia (tecnologia móvel e baseada na web);
Para além das contribuições associadas à PCG, a pesquisa bibliográfica demonstra
que a maioria da bibliografia direcionada aos jogos de vídeo não é suportada em dados
científicos, mas sim na experiência de programadores de vídeo jogos. Em parte, este
fenómeno pode ser explicado pelo facto de o conhecimento não ser partilhado pelas
empresas que desenvolvem jogos de vídeo comerciais. Desta forma, este estudo procura
dar uma maior relevância à área e contribuir de alguma forma para uma melhor
compreensão da temática, nomeadamente:
fornecer uma visão alargada do estado atual do pathfinding em vídeo jogos,
sobre este tópico;
o uso maioritário do algoritmo de procura em grafos A* (Hirt, Gauggel, Hensler,
Blaich, & Bittel, 2011) e algoritmos de procura que envolvem pré-
4
processamento faz com que existam poucas informações sobre soluções que
explorem outras técnicas. Este estuda visa colmatar essa lacuna;
fornecer dados exploratórios e comparativos entre diversas técnicas de
representação de ambiente de jogo e algoritmos de procura em grafos;
a bibliografia muitas vezes fala de técnicas e procedimentos sem fornecer dados
e detalhes de implementação (ex.: algoritmo Fringe Search e a determinação de
vizinhos numa quadtree). Este estudo visa fornecer dados e detalhes concretos
de implementação de um sistema de navegação de agentes;
demasiadas vezes os estudos referem uma técnica inovadora, falhando
posteriormente em estudos de replicação e comparação de dados. Pretendemos
fornecer dados relativos ao algoritmo de procura em grafo Fringe Search.
Queremos enfatizar a importância dos dados colhidos do algoritmo Fringe Search
com estrutura de dados quadtree.
Outro aspeto importante da avaliação é a comparação dos resultados, entre usar
uma ou mais threads nas instâncias de pathfinding. Procuramos fornecer dados válidos
para esta questão, uma vez que este assunto ainda levanta algum debate dentro da
comunidade do desenvolvimento de jogos.
1.4 Enquadramento institucional
Projeto realizado em regime externo à faculdade com o suporte do LabMAg,
Laboratório de Modelação de Agentes Inteligentes, uma das unidades de investigação
do Departamento de Informática da Faculdade de Ciências da Universidade de Lisboa.
Ao longo da realização do presente trabalho foram realizadas diversas reuniões de
supervisão sob a orientação atenta do Prof. Doutor Luís Manuel Ferreira Fernandes
Moniz e do Prof. Doutor Paulo Jorge Cunha Vaz Dias Urbano.
1.5 Organização do documento
A organização do documento segue a estrutura especificada pela cadeira de projeto
em que a presente investigação se insere. O documento está organizado da seguinte
forma:
Capítulo 1 – introdução ao tema, onde são expostas as motivações, objetivos e
contribuições dos autores para a conceção do presente estudo. É ainda feito um
enquadramento institucional e resumo do trabalho realizado.
Capítulo 2 – apresentação de trabalhos e investigações, relevantes e atuais, ao
campo de estudo da investigação. Este capítulo encontra-se dividido em dois
5
subcapítulos. O primeiro subcapítulo é introdutório à geração processual de
conteúdo. O segundo subcapítulo aborda o sistema de navegação de um NPC,
sendo dado um maior enfâse ao pathfinding, nomeadamente às diferentes
abordagens existentes para representar o espaço físico do ambiente dos jogos de
vídeo.
Capítulo 3 – descrição da metodologia de investigação, nomeadamente
especificação dos objetivos e delineamento do estudo, material e métodos e o
planeamento de atividades.
Capítulo 4 – descrição do trabalho realizado e demonstra a solução proposta pelos
autores.
Capítulo 5 – apresentação e análise dos resultados obtidos e caracterização da
amostra.
Capítulo 6 – discussão dos resultados, finalizado com uma conclusão onde são
apontados rumos futuros com base no trabalho desenvolvido.
1.6 Sumário
Secção introdutória ao presente trabalho, onde é descrita a sua motivação, objetivos
e contribuições.
Este trabalho procura suportar a geração processual de conteúdos, nomeadamente
de ambientes de jogo. O processo de geração de ambientes de jogo tem como requisito
o automatismo e tempo de execução. Este estudo pretende suportar esta funcionalidade
e os requisitos associados, através do desenvolvimento de um sistema de navegação de
NPC’s. O estudo para além de contribuir para uma melhor compreensão da temática e
dos requisitos envolvidos, procura fornecer dados e comparar um conjunto de diversas
técnicas de representação de ambiente de jogo e algoritmos de procura em grafos,
usadas no desenvolvimento do sistema de navegação.
A secção é finalizada com uma descrição sumária dos diversos capítulos que
compõem o documento.
6
Capítulo 2
Trabalho relacionado
2.1 Geração processual de conteúdo
Os avanços tecnológicos têm tornado os consumidores de multimédia mais
exigentes quanto ao detalhe gráfico, realismo e conteúdos multimédia de larga escala.
Esta exigência tem sido respondida tradicionalmente com um aumento do número de
artistas especializados e projetos cada vez mais longos. Tal resposta faz aumentar os já
elevados custos de desenvolvimento que acabam por ser pagos pelo consumidor final
(Kelly & Mccabe, 2006; Kelly, 2008). Por outro lado, à medida que a qualidade gráfica
e realismo crescem, aumentam também as dificuldades de entrada de novas empresas
competitivas no mercado, acabando por fazer diminuir a inovação (Kelly, 2008).
Tornou-se assim importante encontrar alternativas que permitam gerar
conteúdos em larga escala, a baixo preço e sem que isso se reflita no detalhe gráfico e
realismo do conteúdo. Uma potencial solução é o uso das técnicas de geração processual
de conteúdos (Ebert et. al cit. por Kelly, 2008 e Kelly & Mccabe, 2006). As técnicas
processuais de conteúdo em jogos consistem na aplicação de computadores para gerar
automaticamente conteúdos de todo o tipo. Este conjunto de técnicas pode ser definido
como a automatização do processo de criação de conteúdos através de um conjunto de
instruções computacionais (Ramteke, 2011). Estas desmarcam-se das aproximações
tradicionais que se baseiam na criação de conteúdos estáticos para definir o ambiente.
Os conteúdos estáticos são inflexíveis, difíceis de modificar e limitados na sua
reutilização, as técnicas processuais oferecem a possibilidade de gerar conteúdos mais
flexíveis e reutilizáveis (Kelly, 2008).
Embora estas técnicas já venham a ser empregues no campo dos vídeo jogos há
mais de 20 anos, a sua aplicação resumia-se à geração aleatória de conteúdos com um
papel secundário nos vídeo jogos (Cardamone, Yannakakis, Togelius, & Lanzi, 2011).
Nos últimos tempos estas técnicas têm assumindo um papel mais preponderante, sendo
usadas na geração de elementos principais como mapas, sons, níveis e outros aspetos
(Cardamone et al., 2011), sendo atualmente cada vez mais explorada pela indústria
7
multimédia: filmes, anúncios comerciais, televisão e videojogos (Kelly & Mccabe,
2006; Kelly, 2008).
A PCG aplicada à área dos videojogos pode ser usada na geração de geometrias,
texturas, comportamentos de agentes, animações, cenários, personagens, sons, músicas,
itens, vegetação, terrenos, entre outros (Cardamone et al., 2011). Hoje em dia é possível
criar mundos virtuais inteiros de forma processual (Kelly, 2008; Pandromeda, 2006 cit.
por Kelly & Mccabe, 2006).
De seguida iremos abordar as vantagens e desvantagens destas técnicas.
2.1.1 Vantagens
As técnicas PCG estão associadas a um conjunto de vantagens:
Aumento da longevidade dos jogos. Apesar dos milhões gastos no desenvolvimento
de vídeo jogos comerciais estes possuem uma longevidade curta., Um jogo do tipo
atirador em primeira pessoa (First person shooter - FPS) por exemplo, possui
apenas uma duração média de 10 horas no modo de jogador único e alguns mapas
no modo de jogadores múltiplos (Cardamone et al., 2011). Se novos conteúdos
puderem ser gerados com uma variedade suficiente em tempo real, então é possível
criar jogos com inúmeros cenários (Togelius et al., 2011).
Jogos sem repetições. A PCG confere a capacidade de o vídeo jogo se adaptar ao
desempenho, experiência, capacidade e preferências de um ou vários jogadores
(Cardamone et al., 2011). A capacidade de gerar mapas em tempo de execução
permite dar aos jogadores novos desafios. Por exemplo, depois de um jogador ter
finalizado a estória principal de um jogo de interpretação de personagem (Role-
playing game - RPG) tem poucas razões para o voltar a jogar ao jogo, com a geração
de mapas o jogador pode explorar novos locais desconhecidos ou até mesmos os
mesmos locais mas com algumas modificações (ex.: “Mass effect 3”).
Transposição de limitações técnicas como o espaço em disco ou memória (como por
exemplo os jogos “elite” e “kkrieger”). À medida que os jogos se tornam mais
complexos e detalhados, o espaço ocupado em disco aumenta proporcionalmente ao
seu conteúdo (Kelly & Mccabe, 2006). Estas técnicas podem ser vistas como
técnicas de compressão de dados (ex.: o jogo FPS “kkrieger” ou o jogo RPG “elite”)
que através de algoritmos determinísticos transformam parâmetros de entrada dede
tamanho reduzido em conteúdos diversos e complexos (Kelly, 2008; Togelius,
Yannakakis, Stanley, & Browne, 2011). Esta capacidade é extremamente útil nos
dias de hoje quando pensamos em transferência de conteúdos pela rede ou na
capacidade limitada de hardware dos dispositivos móveis.
8
Grandes paisagens a custos razoáveis. Mapas muito extensos podem ser difíceis de
criar: cada árvore, casa, carro, entre outros elementos além de criados necessitam de
ser posicionados. Mesmo com uma grande equipa de designers, este processo pode
ser longo (ex.: “Grand Theft Auto”). Os projetos muito longos são um risco para as
produtoras devido aos custos que acarretam, perda de competitividade comparando
a companhias com ciclos de desenvolvimento mais rápido, lançamento de produtos
semelhantes, tecnologia usada tornar-se ultrapassada entre outros.
Possibilidade de ir além da imaginação do desenhador. É possível criar novos tipos
de jogos com mecânicas de jogo construídas inteiramente a partir da PCG (Togelius
et al., 2011).
2.1.2 Desvantagens
Apesar das vantagens no uso das técnicas PCG, existem também desvantagens que
devem ser enumeradas:
Limitação na liberdade de desenho. Como todos os conteúdos são gerados por
algoritmos é difícil gerar elementos específicos. A geração de conteúdos baseada
unicamente em algoritmos não possibilita indicar o aparecimento de elementos
específicos e se a sua aparência ou ordem de aparecimento corresponde à história do
jogo. Caso do jogo não possuir estória este aspeto deixa de ser importante.
Look and feel de paisagens genéricas. Se os algoritmos não estiverem corretamente
configurados, o seu resultado pode ser paisagens que se repetem ou que não
constituem um desafio de exploração a longo prazo. Um designer humano é capaz
de criar paisagens atraentes ao olho humano e excitantes de explorar. Os algoritmos
podem ser afinados por programadores experientes, mas isto por sua vez também
constitui um custo.
Áreas inacessíveis e mapas partidos. Da mesma forma que um designer humano
pode errar, um algoritmo pode não estar correto. Isto pode originar por exemplo
mapas em que não seja possível ganhar, por exemplo, não permitam o jogador
alcançar objetos chave ou mapas que são seja possível ganhar (Togelius et al.,
2011).
2.1.3 Aproximações híbridas
Os conteúdos gerados de forma processual muitas vezes não são adequados para o
jogo. Por outro lado os conteúdos criados por humanos geralmente apresentam uma
qualidade muito superior. Contudo, não existe nenhuma razão para que ambos os
métodos não possam coexistir (Ramteke, 2011; Wu, 2008). A combinação entre
designers humanos e PCG pode ser usada por exemplo para geração de mapas de larga
9
escala que sejam interessantes e que proporcionem uma boa experiência de jogo ao
utilizador. Isto pode ser conseguido de diversas formas:
Cenários gerados através da PCG, com adição posterior ao mapa de salas criadas por
designers humanos. Estas salas são desenhadas para caber no mapa auto gerado,
desta forma embora o seu conteúdo possa não ser modificável a sua localização é. O
jogador apenas se iria aperceber da repetição destas salas se repetisse o jogo (ex.:
“Diablo”).
Mapas criados por designers humanos e posteriormente povoado pela PCG. Os
designers criam o mapa e a PCG cria as paisagens como por exemplo árvores (ex.:
“Elders Scrolls: Oblivion”).
Mapas gerados em tempo de execução. Os mapas são gerados em tempo de
execução, contudo os algoritmos usados estão configurados para colocar elementos
importantes da estória. Desta forma a personagem começa sempre na mesma
posição e acaba sempre em localizações pré-definidas. A inclusão de outras secções
críticas estão cuidadosamente restritas para evitar conflitos. Isto limita a
aleatoriedade, mas por outro lado assegura que estes elementos sejam colocados
corretamente (ex.: “Valion”) (Togelius et al., 2011).
2.1.4 Características
Ao longo de mais de duas décadas diversas técnicas de PCG têm sido aplicadas no
desenvolvimento de diversos aspetos dos vídeo jogos, contudo a comunidade académica
poucos esforços realizou para estudar estas técnicas. Não existe assim nenhum corpo
teórico ou taxonomia que suporte a PCG. Para um melhor entendimento da área iremos
enumerar um conjunto de distinções para clarificar alguns aspetos da utilização da PCG,
que julgamos ser pertinentes e uteis na clarificação do estudo da PCG. Os autores
referem que estas distinções devem ser encaradas como um continuum e não como
distinções dicotómicas, possíveis de serem alteradas no futuro com o amadurecimento
do conhecimento na área.
Online vs. Offline
A aproximação online é usada durante a execução do jogo por exemplo o
servidor sugere diariamente novos mapas a um grupo de jogadores com base no tipo de
jogo de cada um deles. Outro exemplo é a criação de um segundo nível do jogo após o
primeiro ter sido completado. Este segundo nível simplesmente não existe antes disso
(Togelius et al., 2011).
A aproximação offline é usada para criar conteúdos de jogo antes do seu
lançamento comercial. Um exemplo disto é a criação de grandes zonas de vegetação ou
10
secções de jogo que necessitam de uma grande carga de trabalho por partes dos
designers (Blanchard & Jesper, 2012; Togelius et al., 2011).
Conteúdos necessários vs. Conteúdos opcionais
Existem conteúdos que são necessários para que o jogador possa progredir no
jogo. Por exemplo os caminhos devem permitir a passagem do jogador, monstros serem
mortos, regras cruciais ao jogo, etc. (Blanchard & Jesper, 2012; Togelius et al., 2011).
Conteúdos opcionais são descritos como conteúdos sobre o qual o jogador pode
escolher, como por exemplo armas ou salas que o jogador pode entrar ou ignorar (ex.:
“Borderlands”).
A grande diferença entre estes dois tipos de conteúdos é que o conteúdo
necessário deve obrigatoriamente de estar sempre correto ou o jogador não é capaz de
completar o jogo. Alguns tipos de conteúdos podem ser opcionais ou necessários em
alguma parte do jogo (ex.: grutas). Desta forma a análise sobre se um conteúdo é
opcional ou não deve ser feita de partida a partida (Togelius et al., 2011).
Sementes aleatórias vs. Vetores de inicialização
Os algoritmos PCG normalmente recorrem a um conjunto de parâmetros para
criar conteúdos “expandidos” de um determinado tipo baseando-se numa representação
compacta. Esta representação pode variar bastante e descrever conteúdos de quase todo
o tipo. Os parâmetros podem ser usados como uma forma de controlo ou
“aleatoriedade” do conteúdo criado.
A semente é uma representação compacta de um conteúdo que através de um
sistema de geração de números aleatórios irá gerar o conteúdo com base na semente e
nos números aleatórios indicados por parâmetro de entrada (Blanchard & Jesper, 2012;
Togelius et al., 2011).
O vetor de inicialização corresponde a um vetor multidimensional de parâmetros
de valor real que o algoritmo usa como parâmetro de entrada (Togelius et al., 2011).
Quer a sementes aleatórias, quer os vetores de inicialização, podem ser usados
em simultâneo (Blanchard & Jesper, 2012).
Geração estocástica vs. Geração determinística
A geração de conteúdos baseada em parâmetros pode ser caracterizada pelo seu
resultado.
11
Na geração estocástica, o algoritmo de geração de conteúdos com base nos
mesmos parâmetros de entrada gera resultados diferentes. Este tipo de geração permite
gerar conteúdos dinâmicos.
Na geração determinística, o algoritmo de geração de conteúdos gera sempre o
mesmo resultado com base no mesmo parâmetro de entrada. A geração é baseada no
que o parâmetro realmente representa (Blanchard & Jesper, 2012).
Algoritmos inteiramente determinísticos podem ser vistos como um processo de
compressão de dados. O jogo de atirador em primeira pessoa kkrieger é um exemplo
disso, apesar da sua grande componente gráfica apenas ocupa 95 Kb em disco rígido,
segundo os seus criadores caso não tenham sido empregues técnicas PCG o jogo
ocuparia entre 200 a 300 MB em disco rigido (ex.: o jogo “kkrieger”) (Togelius et al.,
2011).
A escolha entre estas duas aproximações é uma questão de design. Contudo, na
maioria das vezes é mais fácil personalizar um sistema que não recorre a uma
aproximação de geração determinística (Blanchard & Jesper, 2012).
Algoritmo construtivo vs. Algoritmo gerar-testar
Na geração de conteúdos é possível distinguir dois tipos principais de
algoritmos.
No algoritmo construtivo, a geração do conteúdo ocorre apenas uma só vez,
sendo esta final, não sendo alvo modificações de posteriores. Esta aproximação é a
melhor opção para a geração de conteúdos online onde a velocidade e performance são
um problema. Na aproximação construtiva é importante que o conteúdo gerado esteja
correto uma vez que não há espaços para correções (Blanchard & Jesper, 2012).
No algoritmo por aproximações, o conteúdo é gerado e depois testado de acordo
um determinado critério. Se o conteúdo gerado não preenche um determinado critério,
todo ou parte do conteúdo será regerada. Este processo irá repetir-se até que todos os
critérios estejam reunidos. Este método permite o sistema errar e assegurar que o
conteúdo final esta sempre correto (é necessário que caso os critérios estejam corretos).
O aspeto negativo desta aproximação é que a execução de muitas iterações durante a
geração pode demorar muito tempo o que não satisfaz a geração online (Blanchard &
Jesper, 2012).
Não serão abordados algoritmos de PCG uma vez que sai da esfera de interesse
do presente estudo.
12
2.2 Sistema de navegação
Cada vídeo jogo é único, e cada jogo requer uma implementação única da
inteligência artificial para suportar as mecânicas específicas desse jogo (ex:. tipo de
jogo). O sistema de navegação é apenas uma das componentes da inteligência artificial.
Contudo existem aspetos comuns entre os diversos jogos. Neste capítulo iremos
descrever esses aspetos baseando-nos no tipo de jogo atirador em primeira pessoa e
jogos em terceira pessoa uma vez que partilham os mesmos pressupostos.
O sistema de AI de um jogo de vídeo constitui uma camada específica do motor
de jogo, onde está incluído o sistema de navegação. O sistema de navegação pode ser
dividido em duas componentes principais (ver Ilustração 1): locomoção (encarregue
pelo movimento efetivo do agente) e pathfinding (responsável pelo planeamento de
caminhos no ambiente do jogo de vídeo). A componente pathfinding por sua vez pode
ser subdividida em duas componentes: representação do ambiente e algoritmos de
procura (Anguelov, 2011).
2.2.1 Locomoção
A componente locomoção está encarregue do movimento efetivo do agente, é o
sistema de controlo do movimento, esta determina como o NPC se deve mover no
ambiente de jogo. As funcionalidades suportadas por esta componente variam de
implementação para implementação, consoante o contexto e complexidade da IA do
jogo de vídeo. As suas principais funções são:
fazer pedidos de resolução de caminho à camada pathfinding quando existe a
necessidade de planear uma rota; e
executar os planos retornados pelo pathfinding.
Representação do ambiente
Locomoção
Algoritmos de Procura
Pathfinding
Sistema de Navegação
Ilustração 1 - Sistema de navegação e as suas componentes.
13
Esta componente não determina para onde o agente se deve mover, mas sim como
o fazer. Esta solicita pedidos de caminho entre dois pontos e é responsável por assegurar
que o agente se move de forma correta de um ponto para outro.
Para a realização eficaz do plano retornado pelo pathfinding o NPC deve ser capaz
de identificar obstáculos (objetos do ambiente de jogo ou outros NPC’s) e validar o
caminho devolvido, A identificação de obstáculos e validação do caminho é um
problema complexo que varia consoante o tipo de jogo, complexidade da inteligência
artificial do agente e o realismo do jogo. Existem diversas abordagens, as quais apenas
iremos referir algumas:
dotar o NPC de sensores como por exemplo fazer raycasting para a identificação de
obstáculos.
se o mapa de navegação dispor de informação da área navegável, a repetição
periódica de pedidos de caminho permite ao NPC descartar caminhos que podem
não estar atualmente corretos.
2.2.2 Representação do ambiente
Para os algoritmos de procura de caminhos poderem desempenhar a sua função, é
necessário em primeiro lugar que estes consigam entender o ambiente, e isto implica
que o ambiente esteja guardado de forma simples e que permita realizar procuras de
forma fácil e rápida. O detalhe visual do ambiente de jogo 3D é irrelevante para o
planeamento de caminhos e o formato que este se encontra guardado não é adequado à
procura de caminhos. Desta forma, os programadores de jogos para a procura de
caminhos, recorrem a abstrações simples do ambiente complexo do vídeo jogo. Estas
abstrações contêm toda a informação essencial para a navegação do NPC e que
possibilitam a procura de caminhos (Anguelov, 2011). O seu objetivo não é descrever
toda a geometria navegável, mas sim fornecer marcas que servem como localizações e a
forma como lá chegar (Borovikov, 2011).
Abstração de grafo de navegação
A representação do ambiente assume a forma de grafo uma vez que é uma
estrutura de dados simples, capaz de conter todos os dados de navegação. Um grafo é
definido por dois conjuntos finitos: vértices (nós) e arestas (conexões). Os vértice
contêm os dados enquanto as arestas fazem a ligação entre dois vértices. Um vértice
pode ter uma ou mais arestas que o conecta com outros vértices do grafo. Os grafos que
contem dados de navegação e que representam um ambiente de jogo são chamados de
grafos de navegação (navgraph). Estes grafos delimitam o espaço de procura para
algoritmos de procura. Cada nó do grafo representa uma localização possível do
14
ambiente 3D e contem as propriedades dessa localização e uma lista de localizações
(nós) acessíveis diretamente a partir desse nó (Anguelov, 2011). Cada aresta representa
a conexão entre as duas áreas, e esta por sua vez está associada a um custo que no caso
mais simples representa a distância entre os dois nós que conecta (Buckland, 2004).
Em resumo, a geometria do mapa e a capacidade de movimento do agente são
traduzidos em nós, conexões e em funções de custo que os valoriza (Millington &
Funge, 2009).
Geralmente os navgraph são incluídos no jogo de vídeo durante a fase de
desenvolvimento, com o objetivo de evitar o consumo de recursos (tempo de execução e
memória) na sua geração durante a execução do jogo de vídeo. Esta decisão é a mais
apropriada, nos jogos de vídeo em que cenários são imutáveis.
Esquema de divisão
Embora a ideia de construir um grafo de navegação a partir de um ambiente
complexo pareça simples, a implementação da teoria à prática está associada a inúmeros
problemas (Buckland, 2004). Para a construção do grafo é necessário dividir o espaço
do jogo em regiões e conectá-las. Os diversos métodos que permitem fazer isto
designam-se por esquemas de divisão (division schemes).
Propriedades
Cada esquema de divisão possui três importantes propriedades:
quantização/localização (quantization/localization), geração (generation) e validade
(validity).
Quantização/localização
Os grafos de navegação são mais simples que o ambiente de jogo, desta forma é
necessário recorrer a um mecanismo que traduza as localizações no ambiente de jogo
em nós no grafo, a isso se chama quantização. Esta propriedade é usada por exemplo
quando um NPC decide alcançar um item dentro do ambiente de jogo, neste caso é
necessário converter a sua posição e a posição do item em nós do grafo. A localização é
o processo inverso da quantização, em que é usado um mecanismo que traduza os nós
no grafo em localização no ambiente de jogo. Após um algoritmo de procura determinar
um caminho entre dois pontos, o agente necessita de saber as coordenadas desses pontos
no ambiente de jogo.
Geração
A propriedade geração distingue cada método relativamente ao seu grau de
automatismo que pode variar entre manual ou automático. O processo automático é
15
caracterizado por gerar menos nós para cobrir o cenário, resultando em mapas de
navegação mais simples que permitem processar respostas mais rápidas. O processo
manual caracteriza-se por gerar grafos mais complexos (maior número de nós), mas que
oferece melhores resultados em relação ao realismo do comportamento dos NPCs uma
vez que o processo é específico a cada mapa do jogo.
Validade
A validade refere-se à capacidade do agente de realizar o plano traçado. Se um
plano delineia um percurso ao longo da conexão do nó A ao nó B, então o agente deverá
ser capaz de realizar esse movimento. Se a quantização das regiões à volta de A e B não
permitem esse movimento então o grafo de navegação criou um plano de navegação
inútil.
Um esquema de divisão é válido se todos os pontos, de duas regiões conectadas,
possam ser alcançados entre elas. A maioria dos esquemas de divisão não verifica a
validade, podendo ainda haver diversos níveis de validade (Millington & Funge, 2009).
Tipos
Existem três principais tipos de esquema de divisão: baseados em pontos de
passagem, baseados em malha de navegação e baseados em grelha. O método de
abstração usado para representar o ambiente de jogo irá determinar o tamanho e
complexidade do grafo (Anguelov, 2011).
Ilustração 2 - Ambiente de jogo base.
16
Para permitir entender melhor para cada um método de abstração é fornecido um
exemplo da sua aplicação com base no ambiente de jogo mostrado na Ilustração 4.
Baseado em pontos de passagem
O método de abstração baseado em pontos de passagem é considerado como o
método tradicional de criar grafos de navegação uma vez que era o método usado nos
jogos de vídeo antigos como os jogos de aventura animada e first person shooter (FPS),
ex.: “Monkey Island”, “Half-Life 2”. Este tipo de abstração consiste na adição de pontos
de passagem (nós) de forma manual ou automática ao cenário, sendo posteriormente
ligados (arestas) de forma manual ou automática formando desta forma o grafo de
navegação.
As abordagens inteiramente manuais, embora confiram ao agente artificial um
movimento menos artificial, não são consideradas como perfeitas uma vez que não
garantem a cobertura total do ambiente. Em comparação, as abordagens automáticas
caracterizam-se por cobrir eficazmente todo o espaço navegável, contudo este tipo de
abordagem está associada a um grande custo computacional e à possibilidade de
originarem um elevado número de nós redundantes resultando no aumento do espaço de
procura. Por norma assiste-se ao uso das duas abordagens, de forma a obter o melhor
dos dois mundos e a compensar os pontos negativos de cada abordagem (Tozour, 2008).
Podemos dar como exemplo de abordagem automática os algoritmos: “art gallery”
(onde se recorre à abstração de uma galeria de arte em que o algoritmo determina o
número mínimo de guardas necessários para que todas as paredes da galeria estejam no
raio de visão dos guardas), os pontos de visibilidade e geometria expandida (estas duas
ultimas são abordadas com maior detalhe mais à frente). Embora as técnicas enunciadas
possibilitem diversos graus de automatização é sempre necessário algum tipo de
intervenção humana (Tozour, 2008).
17
Vantagens
Apesar de ser necessário inúmeros pontos de passagem para garantir o
movimento adequado dos agentes artificiais, o grafo de navegação resultante desta
abordagem potencialmente possui o menor espaço de procura quando comparados com
as demais abordagens.
Existe a possibilidade de incluir informação adicional nos nós que compõe o
grafo de navegação, como por exemplo atributos de orientação, ou tipos de animação
que o agente deve realizar face a esse objeto. Esta característica é útil quando se
pretende incluir pontos pré-definidos no ambiente de jogo, como assinalar pontos de
abrigo, de passagem, de patrulha ou até mesmo, pontos chaves da estória do jogo. É
possível por exemplo incluir um ponto de passagem numa porta com um atributo de
orientação, desta forma um NPC ao aproximar-se saberá como se orientar face à porta
de forma a poder abri-la corretamente.
No caso de haver a necessidade de incluir pontos pré-definidos que identifiquem
posições chave no mapa, as outras abordagens para além do próprio grafo de navegação
necessitam de uma segunda representação baseada em pontos de passagem que
indiquem à AI como usar o ambiente de jogo (Tozour, 2008).
Desvantagens
A única informação que os agentes artificiais possuem do mundo são os pontos
de passagem e as arestas que os une. Os agentes são assim forçados a manterem-se no
caminho delineado como se estivessem a deslocar-se num trilho de caminho-de-ferro.
Isto implica que o agente ao movimentar-se ao longo do trajeto caminhe com uma
aparência artificial (“zig-zag”) ou não opte pelo caminho ótimo (Tozour, 2008).
Ilustração 3 - Grafo de navegação baseado em pontos de passagem.
18
A informação limitada que o agente dispõe do ambiente de jogo dificulta a
aplicação desta abordagem a ambientes dinâmicos. O agente ao verificar que o caminho
está obstruído tem de adotar um novo caminho, invés de se desviar do obstáculo
(Tozour, 2008). Por outro lado caso ocorra um evento de alteração do ambiente de jogo,
a geração automática de pontos de passagem não oferece garantias quanto à validade do
caminho gerado (Anguelov, 2011).
Impossibilidade de usar o mesmo grafo de navegação para agentes com
propriedades diferentes como o peso, tamanho, taxa de viragem e outros parâmetros.
Muitas vezes é necessário usar diferentes grafos de navegação baseados no tamanho,
forma e capacidade de movimentação de cada agente (Tozour, 2008).
Problemas na simulação de multidões uma vez que todos os elementos movem-
se através das arestas, o que não é natural (Tozour, 2008).
Impossibilidade de prever o resultado das animações do agente. O agente ao
realizar uma animação pode entrar numa posição inválida como uma parede ou
precipício. (Tozour, 2008).
Técnicas de colocação de pontos
Pontos de visibilidade
Os gafos de navegação baseados em pontos de visibilidade (POV) são uma
variante dos grafos de navegação baseados em pontos de passagem. Os grafos de
navegação baseados em POV são criados através da colocação automática de pontos de
inflexão (pontos em que a direção do caminho altera) nos vértices dos polígonos
convexos, assinalando desta forma as obstruções do cenário. Estes pontos de inflexão
são posteriormente conectados através da verificação da linha de visão (Anguelov,
2011).
Esquema de
divisão
Os pontos de inflexão ocorrem naturalmente no caminho mais curto, estes
podem ser transformados em nós e usados na procura de caminhos. A ligação
entre pontos de inflexão pode ser feita através da técnica de raycasting em que
a conexão entre dois pontos acontece se o raio colidir como a geometria de
um. A ideia é verificar se um ponto pode ver o outro (Millington & Funge,
2009).
Quantização
e localização
Uso do dominó de Dirichlet (Millington & Funge, 2009).
19
Validade Uso do dominó de Dirichlet (Millington & Funge, 2009).
Tabela 1 - Esquema de divisão de grafos de navegação baseados pontos de visibilidade.
Ilustração 4 - Grafo de navegação baseado em pontos de visibilidade.
Vantagens
Este tipo de grafo de navegação é fácil de expandir de forma a incluir outros nós
que forneçam informações para além dos dados de conectividade (Buckland, 2004).
Desvantagens
Espaço de procura e fator de ramificação grande quando comparado com grafos
de navegação baseados em pontos de passagem. Obstáculos com uma geometria
complexa (ex.: pilares circulares) podem gerar grafos com um grande número conexões
devido à geração de múltiplos pontos de inflexão próximos uns dos outros (Anguelov,
2011).
Geralmente é necessário a intervenção humana para juntar diversos pontos de
inflexão com o objetivo de reduzir o espaço de procura. Em cenários grandes e
complexos o designer do mapa, pode gastar muito tempo a criar e a afinar os pontos de
inflexão.
Geometria expandida
A técnica de geometria expandida é uma técnica que permite colocar pontos de
inflexão de forma automática. Se o ambiente do jogo for constituído por polígonos é
possível usar a informação presente nessas formas geométricas para automaticamente
criar um grafo POV permitindo poupar imenso tempo no caso de grandes ambiente de
20
jogo. Este processo é feito da seguinte forma, primeiro são expandidos os polígonos por
uma quantidade proporcional ao raio dos agentes do jogo, de seguida os vértices
definidos, por estas geometrias expandidas, são adicionados como nós ao grafo de
navegação. Por último, é executado um algoritmo para testar a linha de visão entre os
vértices, e são acrescentadas as arestas ao grafo.
Como os polígonos estão expandidos por uma quantidade maior ou igual ao raio
do agente, um agente pode procurar o grafo de navegação resultante para criar caminhos
sem esbarrar contra paredes.
Apesar do automatismo desta técnica, ainda é necessário a intervenção humana
para remover a redundância de pontos de inflexão (Buckland, 2004).
Ilustração 5 - Grafo de navegação baseado em pontos de visibilidade com geometria expandida.
Baseado em grelha
Grafos de navegação baseados em grelha são criados através da imposição de uma
grelha sobre o ambiente de jogo, dividindo o ambiente em regiões regulares designadas
por telhas (tiles) ou células. A conversão da grelha em grafo é feita através da geração
de um nó abstrato por cada célula da grelha e de seguida, através da geometria de
conexão das células em grelha (propriedade de vizinhança), são determinadas as arestas.
A geometria de conexão de células é determinada pelo tipo de células usado para formar
a grelha, este tipo pode variar entre células quadradas com 4 ou 8 vizinhos, células
hexagonais com 6 vizinhos (ver Ilustração 6). Sendo a célula quadrada com 8 vizinhos a
mais popular (Anguelov, 2011).
21
Cada célula dispõe de um limiar de navegabilidade que é usado para determinar
se uma célula é navegável ou está obstruída. No caso de uma célula ter atingido esse
limiar então a célula é considerada como obstruída e o agente não irá tentar mover-se
para elas caso contrário é considerado como navegável (Millington & Funge, 2009).
Desta forma, ao contrário das outras abordagens, os grafos de navegação baseados em
grelha contêm a informação quer das áreas navegáveis, quer das áreas obstruídas. Este
tipo de grafo possui assim a representação total do ambiente de jogo, incluindo todas as
posições possíveis.
No que diz respeito a ambientes de jogo dinâmicos, a reflexão de alterações do
ambiente no grafo de navegação têm baixos custos, uma vez que apenas implicam o
recálculo do indicador de navegabilidade das células que englobam a área afetada, não
ocorrendo a modificação ou a reconstrução do grafo.
A representação simples de todo o ambiente de jogo, assim como atualizações
sem custos, tornam esta abordagem na primeira escolha a ser usada em jogos de
estratégia em tempo real (Real-time strategy - RTS) (Anguelov, 2011).
Célula quadrada (4 vizinhos)
Célula quadrada (4 vizinhos)
Célula quadrada (8 vizinhos)
Célula quadrada (8 vizinhos)
Célula hexagonal (6 vizinhos)
Célula hexagonal (6 vizinhos)
Ilustração 6 - Geometria das conexões das células em grelha.
22
Esquema de
divisão
Os nós do grafo de navegação representam as células do ambiente de jogo.
Cada célula no mundo do jogo tem um conjunto de vizinhos (baseado no tipo
de célula), as arestas do grafo de navegação representam os vizinhos imediatos
(Millington & Funge, 2009).
Quantização
e localização
Na quantização a determinação da célula em que um determinado ponto do
ambiente se localiza é rápida.
Na localização pode ser usado um ponto de representação da célula
Ilustração 8 - Grafo de navegação baseado em grelha com células hexagonais.
Ilustração 7 - Grafo de navegação baseado em grelha com células quadradas.
23
(normalmente o centro da célula) para converter o nó numa localização dentro
do ambiente.
Desta forma, a quantização e a localização são constantes (Millington &
Funge, 2009).
Geração A geração dos grafos baseados em telha é automática, devido a estes serem
regulares (têm sempre o mesmo número de conexões) (Millington & Funge,
2009).
Validade Pode ocorrer erros de validade quando a célula está parcialmente bloqueada
mas ainda não atingiu o limiar de navegabilidade (Millington & Funge, 2009).
Tabela 2 - Esquema de divisão de grafos de navegação baseados em grelha.
Vantagens
Pode ser aplicada em ambientes dinâmicos, qualquer alteração ao ambiente
resulta numa operação de custo baixo uma vez que apenas implica o recálculo do limiar
de navegabilidade dos nós da área afetada e não requer qualquer alteração ou
reconstrução do grafo (Anguelov, 2011).
Jogos de mesa, de estratégia em tempo real (real-time strategy - RTS) ou de
interpretação de personagens (role-playing game - RPG) são normalmente divididos em
células onde são colocados os modelos 3D. Esta grelha pode ser facilmente convertida
de forma a representar um grafo de navegação (Buckland, 2004; Millington & Funge,
2009).
Os grafos de navegação podem ser gerados automaticamente no momento sem
qualquer intervenção de programadores e em tempo de execução. De todas as
abordagens é a que necessita de menos envolvimento por parte do programador
(Millington & Funge, 2009).
A posição do início e do fim do caminho existe como nós no grafo de
navegação, não requerendo procuras adicionais para descobrir o nó do grafo mais
próximo a estas localizações.
Este método é simples e eficiente uma vez que a geometria de conexão das
células em grelha é constante e não necessita de examinações complexas do ambiente
(ao contrário dos grafos de navegação baseados em malha de navegação) (Anguelov,
2011).
24
Desvantagens
Os grafos resultantes deste método contêm o maior espaço de procura em
comparação com as outras abordagens, uma vez que englobam os espaços navegáveis e
obstruídos (Anguelov, 2011).
Existência de células de igual tamanho para representar um espaço vazio (Yahja,
Stentz, Singh, & Brumitt, 1998).
Os agentes possuem um número limitado de ângulos de direção consoante o
número de vizinhos associados à tipologia da célula. Desta forma, é possível observar
alterações abruptas de direção durante a movimentação, é possível usar outras técnicas
para atenuar este efeito, contudo sem garantias que o caminho suavizado convirja para o
caminho ótimo (Yahja et al., 1998).
O fator de ramificação depende do tipo da célula, quanto maior o fator de
ramificação pior o desempenho e o custo de memoria na procura de caminhos. Se a
célula tiver 8 vizinhos, então o grafo irá ter o maior fator de ramificação (Anguelov,
2011). Por exemplo um mapa com células 100 x 100 necessita de um grafo com 10,000
nós e 78,000 arestas aproximadamente.
O caminho gerado com base neste tipo de abstração é considerado sub-ótimos uma
vez que o caminho está limitado ao centro das células que compões o caminho (Hirt et
al., 2011).
Quadtree
A quadtree é uma estrutura de dados em árvore em que cada nó interno tem
exatamente quatro nós filhos, cada um representa um quadrante (sudoeste – SW, sudeste
– SE, nordeste – NE e noroeste – NO) (ver Ilustração 9).
Esta estrutura é geralmente usada na divisão do espaço 2D caracterizando-se por
dividir o espaço em 4 regiões uniformes, podendo cada uma destas regiões ser
subdividida recursivamente em 4 regiões. O número de divisões é geralmente designado
NENENWNW
SESESWSW
NorteNorte
SulSul
EsteEsteOesteOeste
NENE NWNWSESESWSW
Ilustração 9 - Quadrantes e quadtree correspondente.
25
por profundidade. Cada célula tem um limiar (capacidade máxima) que ao ser alcançado
irá gerar a subdivisão dessa região em 4 regiões.
Embora a quadtree possa ser catalogada como um método de abstração baseado em
grelha, esta é uma estrutura de dados inteiramente diferente, sendo a sua principal
diferença o uso de células não regulares.
Os grafos de navegação baseados em quadtree são criados pela imposição desta
estrutura ao ambiente de jogo, dividindo-o em regiões de tamanho não regular (células),
até uma profundidade máxima definida. Tal como as células da grelha existe um
indicador que assinala a navegabilidade das células. Quando é adicionado um objeto ao
ambiente de jogo a quadtree irá dividir essa região até a profundidade máxima possível
e irá assinalar a região ocupada pelo objeto como obstruída e as restantes regiões
resultantes como navegáveis. As quadtrees que apresentam este comportamento
designam-se por quadtree adaptativas. Desta forma, é possível representar o ambiente
jogo de forma mais precisa possível com o menor número de nós (Hirt et al., 2011).
As quadtree possuem inúmeras aplicações e diversas implementações. Contudo
nem todas estas aplicações e implementações implicam a procura de vizinhos. A nossa
pesquisa bibliografia não revelou estudos científicos que abordam especificamente a
procura de vizinhos em jogos de vídeo, a maioria de algoritmos e implementações não
contempla esta funcionalidade e a maioria dos estudos que abordam a problemática são
destinados ao processamento de imagem.
Podemos definir o nó B como vizinho de A quando estes partilham uma fronteira.
Ao contrário do que acontece nas grelhas, a determinação de vizinhos numa quadtree
não pode recorrer à geometria de conexão das células, uma vez que as células podem
não ser regulares. Trata-se assim de um problema não trivial.
26
Esquema de
divisão
Os nós do grafo de navegação representam as células não regulares do ambiente
de jogo. Cada célula no mundo do jogo tem um conjunto de vizinhos (aqueles
cujo partilham fronteira), as arestas do grafo de navegação representam os
vizinhos imediatos.
Quantização
e localização
Na quantização a determinação da célula em que um determinado ponto do
ambiente se localiza é rápida.
Na localização pode ser usado um ponto de representação da célula
(normalmente o centro da célula) para converter o nó numa localização dentro
do ambiente.
Desta forma, a quantização e a localização são constantes.
Geração A geração dos grafos baseados em quadtree é automática. (Millington & Funge,
2009).
Validade Pode ocorrer erros de validade quando:
a célula está parcialmente bloqueada mas ainda não atingiu o limiar de
navegabilidade;
o ângulo de direção entre o ponto médio da célula de origem ao ponto
médio da célula vizinha de destino passa por um vizinho ocupado (ver
Ilustração 11).
Tabela 3 - Esquema de divisão de grafos de navegação baseados em grelha.
Ilustração 10 - Grafo de navegação baseado em quadtree.
27
Vantagens
O baixo número de nós permite reduzir a memória e tempo requerido na procura de
caminhos (Hirt et al., 2011).
Desvantagens
Tal como no esquema de divisão baseados em grelha o caminho gerado é
considerado sub-ótimo uma vez que o caminho está limitado ao centro das células (Hirt
et al., 2011).
Baseado em malha de navegação
Os grafos de navegação baseados em malha de navegação (navmesh) têm-se
tornado bastante popular entre os programadores de jogos e podem ser encontrados em
diversos vídeos jogos comerciais (ex.: “HALO” 2 e 3, “F.E.A.R.”, “Counter-Strike:
Source”, “Jak and Daxter”, e “Uncharted: Drake’s Fortune”). Esta técnica utiliza uma
rede de polígonos convexos chamada de malha de navegação (navmesh), que representa
o chão do ambiente e descreve as áreas onde é possível caminhar no jogo. Os polígonos
convexos têm a propriedade de permitir viajar sem impedimento a partir de qualquer
ponto do polígono para outro ponto do polígono. O ambiente de jogo pode ser então
representado como um grafo, em que cada nó representa um polígono convexo, sendo
usado geralmente como coordenada de localização o ponto central do polígono
(Borovikov, 2011).
Ilustração 11 - Grafo de navegação baseado em quadtree inválido.
28
Existem diversas técnicas de subdivisão do ambiente em malha de navegação,
contudo saem do âmbito deste estudo. Na subdivisão, são usadas normalmente formas
geométricas triangulares devido ao seu baixo número de conexões (número de atestas
menor ou igual a 3), o que resulta em um baixo fator de ramificação no grafo final e por
outro lado confere flexibilidade na representação de ambientes de jogo complexos
(Anguelov, 2011).
Ilustração 13 - Grafo de navegação baseado em malha de navegação.
Ilustração 12 - Ambiente de jogo subdividido em polígonos navegáveis.
29
Esquema de
divisão
O ambiente de muitos jogos de vídeo é constituído inteiramente por polígonos,
cada polígono pode ser usado como um nó no grafo de navegação. Cada nó é
conectado aos nós (polígonos) que partilham uma aresta em comum.
A criação da malha de navegação envolve o programador, uma vez que é
necessário identificar os polígonos que constituem o chão do ambiente de jogo.
O programador inclui então etiquetas que podem incluir diversas informações
(Millington & Funge, 2009).
Quantização
e localização
A identificação do polígono a que um ponto corresponde pode ser feita através
da pesquisa do espaço procura ou através do pressuposto de coerência. A
assunção de coerência postula que se se souber a localização do agente na
última frame é então possível que este se encontre no mesmo polígono ou no
polígono vizinho.
Para a localização de um determinado polígono, pode ser escolhido um ponto
qualquer desse polígono, contudo por norma é escolhido o centro da geometria
(válido para triângulos ou figuras geométricas côncavas) (Millington & Funge,
2009).
Validade As regiões formadas por malhas de navegação podem ser problemáticas, devido
ao pressuposto que através de um ponto de uma região se pode aceder a
qualquer ponto de uma outra região a que esteja conectado, contudo isto pode
não se verificar (Millington & Funge, 2009).
Tabela 4 - Esquema de divisão de grafos de navegação baseados em malha de navegação.
Vantagens
Estas técnicas geralmente geram um número mínimo de nós necessários para
representar o ambiente, garantindo ao mesmo tempo uma cobertura do ambiente quase
perfeita (Anguelov, 2011).
O número baixo de nós e o baixo fator de ramificação confere aos grafos
baseados em navmesh um espaço de procura pequeno (Anguelov, 2011; Borovikov,
2011).
Este tipo de técnicas gera a representação de área navegável mais fiel de
ambientes de jogo complexos (Anguelov, 2011).
Jogos 3D, como a maioria dos FPS, são construídos inteiramente por polígonos,
desta forma é possível usar algoritmos que usem estes polígonos (Buckland, 2004).
30
As malhas de navegação podem ser atualizadas em tempo de execução, contudo
isto constitui um desafio devido às restrições de desempenho.
Permite um elevado grau de automatização aos agentes artificiais (Anguelov,
2011). O agente ao detetar obstáculos através de técnicas como o raycasting pode
ajustar o seu trajeto de forma a evitar o obstáculo, mas mantendo-se dentro da malha de
navegação e no trajeto mais perto (Tozour, 2008).
O agente dispõe de informação das zonas em que pode caminhar, podendo o seu
trajeto ser suavizado (diminuindo o efeito do “andar robótico”) desde que seja
certificado de que o agente não saia da malha de navegação (Tozour, 2008).
É necessário um menor envolvimento de programadores do que a abordagem
baseada em pontos de passagem, uma vez que o papel deste é reduzido a identificar a
malha poligonal que constitui o terreno (Millington & Funge, 2009).
Esta abordagem permite usar o mesmo grafo para diversos tipos de unidade, o
percurso é calculado e posteriormente é adaptado, por exemplo, às dimensões do agente.
No que diz respeito às animações dos agentes, é possível prever se a localização
do agente no final da animação é válida, através da comparação da posição final com a
malha de navegação (Tozour, 2008).
Desvantagens
A subdivisão inicial do chão do ambiente de jogo requer um grande custo
computacional e sendo esta a principal razão dos grafos de navegação baseados em
malhas de navegação serem geralmente gerados de forma offline.
Os grafos baseados nesta técnica possuem uma grande desvantagem em
ambientes dinâmicos devido ao grande custo computacional envolvido na geração da
malha de navegação. Uma alteração ao ambiente de jogo irá resultar na subdivisão em
diversas partes da região do polígono alterado e por sua vez a reconstrução do grafo de
navegação dessa região (Anguelov, 2011). Uma possível forma de lidar com este
problema é usar pequenas porções da malha, uma de cada vez (Borovikov, 2011).
2.2.3 Algoritmos de procura em grafos
A abstração de grafo de navegação tem como principal objetivo fornecer uma
estrutura simples que possibilite realizar procuras rápidas. Os algoritmos de procura em
grafos têm por objetivo procurar o caminho mais curto de um nó do grafo (vértice
inicial) a outro nó do grafo (vértice final).
O pathfinding recorre a algoritmos de procura de grafos para descobrir o caminho
ótimo ou próximo de ótimo. Caso exista um caminho entre os dois nós e se este for o
31
caminho com o menor custo possível então diz-se que estamos perante um caminho
ótimo. O pathfinding está condicionado à complexidade do algoritmo (heurísticas) e ao
tamanho do espaço de procura.
No contexto dos jogos de vídeo o pathfinding está relacionado com a forma como
as entidades chegam a um determinado objetivo tendo para isso de lidar com obstáculos
(Koefoed-hansen, 2012). Neste contexto o pathfinding tem de respeitar o requisito de
tempo real de múltiplos agentes e está sujeito à limitação de memória e desempenho do
sistema de computacional, devendo, desta forma, os custos de processamento e
memória serem minimizados (Anguelov, 2011).
Dijkstra’s
O algoritmo Dijkstra’s foi apresentado por Edsger Dijkstra em 1959 como um
método de encontrar o caminho mais curto de um vértice inicial a um vértice final numa
árvore de suporte (weighted graph) (Anguelov, 2011).
O algoritmo Dijkstra’s recorre a duas listas, uma que guarda os vértices já visitados
(lista fechada) e a segunda que contém um conjunto de nós candidatos (lista aberta). A
cada iteração o algoritmo começa por examinar (expandir) o nó com a menor distância
ao vértice inicial dentro da lista dos nós candidatos. Caso o vértice expandido não seja o
nó final, este é retirado da lista aberta e adicionado à lista fechada, os vértices
adjacentes (nós vizinhos) a este vértice que ainda não foram examinados são então
adicionados à lista aberta. O processo é repetido até o vértice final ser encontrado. O
algoritmo irá falhar no caso de o vértice ter um custo negativo. Quando o vértice final é
encontrado, como o primeiro nó examinado é sempre o vértice com a distância menor
ao vértice inicial, o caminho encontrado é o caminho ótimo (Koefoed-hansen, 2012).
A grande desvantagem apontada a este algoritmo é o grande custo resultante das
operações à lista fechada e aberta. Cada vez que um nó é selecionado da lista aberta é
necessário procurar pela lista inteira pelo vértice mais próximo do vértice inicial. Da
mesma forma que sempre que é adicionado um vértice à lista aberta é necessário
verificar se ele já existe na lista fechada.
De forma a reduzir o custo de computação de operações à lista aberta e fechada
várias otimizações podem ser feitas, e estas mesmas otimizações fazem parte de
algoritmos como o A*. Um exemplo de otimização da lista aberta é o uso de uma lista
ordenada, para que o primeiro vértice da lista seja sempre o próximo nó a ser
expandido. Relativamente à lista fechada, cada vértice pode guardar uma variável que
assinale se o vértice já foi adicionado ou não à lista aberta. Esta otimização evita a
implementação de uma lista fechada bastando apenas verificar o estado do vértice
(Anguelov, 2011).
32
Melhor-primeiro
Este algoritmo tem um comportamento similar ao Dijkstra’s contudo possuiu uma
heurística que verifica a distância do vértice inicial ao vértice final. Invés do algoritmo
expandir o vértice mais perto do vértice inicial, começa por expandir o vértice mais
perto do vértice final (ganancioso). Este algoritmo não assegura que seja encontrado o
caminho mais curto, contudo é mais rápido que o algoritmo Dijkstra’s uma vez que a
sua heurística guia a procura em direção ao nó final.
O algoritmo melhor-primeiro tem a desvantagem de uma vez que é “ganancioso”,
tenta mover-se diretamente para o nó final mesmo que o caminho não seja o correto.
Vértice inicialVértice inicial Vértice finalVértice final-- --
+ perto do vértice final+ perto do vértice final + longe do vértice final+ longe do vértice final
Ilustração 15 - Algoritmo de procura melhor-primeiro.
Vértice inicialVértice inicial Vértice finalVértice final-- --
+ perto do vértice inicial+ perto do vértice inicial + longe do vértice inicial+ longe do vértice inicial
Ilustração 14 - Algoritmo de procura Dijkstra's.
33
A*
O algoritmo A* foi apresentado em 1968 por Hart et. al (cit. por Anguelov, 2011)
como uma alternativa superior ao algoritmo Dijkstra’s. O A* baseia-se no algoritmo
Dijkstra’s e nas heurísticas do algoritmo melhor-primeiro. Este destaca-se pela sua
flexibilidade e possibilidade de utilização em diversos contextos. Este algoritmo recorre
a heurísticas, tal como o algoritmo Dijkstra’s favorece os vértices mais próximos ao
vértice inicial e ao mesmo tempo tal como o algoritmo melhor-primeiro favorece os
vértices perto do nó final. Dependendo da heurística escolhida o A* garante o caminho
ótimo ou quase ótimo.
O A* atribui um custo f(n) a cada vértice expandido, este custo é igual custo do
caminho do vértice inicial ao vértice n g(n) mais o custo estimado do vértice n ao
vértice final h(n).
O custo estimado é determinado por uma heurística que representa a menor
distância possível entre o vértice n e o vértice final. É desta forma que o A* elimina
caminhos mais longos quando um caminho é descoberto.
O algoritmo de procura A* apresenta uma eficiência ótima para determinadas
heurísticas, porém, na prática, o A* apresenta um problema relativamente ao consumo
de memória e tempo. Este problema é agravado se os caminhos tiverem de ser
calculados com uma elevada frequência. A complexidade do processo de procura de
caminho aumenta com o tamanho do ambiente e a precisão requerida (Hirt et al., 2011).
Ilustração 16 - Algoritmo de procura A*.
Vértice inicialVértice inicial Vértice finalVértice final-- --
+ H - G+ H - G - H + G- H + G
Equação 1 - Cálculo do custo de n.
34
Fringe Search
O algoritmo Fringe Search foi introduzido por Björnsson et al. em 2005
(Björnsson, Enzenberger, Holte, & Schaeffer, 2005) como uma solução aos problemas
inerentes à variante do A* o Iterative Deepening A* (IDA*). Segundo os autores a
procura do melhor primeiro associado ao A* tem o seu preço em recursos
computacionais. A ordenação da lista de nós abertos do A* é bastante dispendiosa, este
problema não é solucionável com o baixo armazenamento de nós como acontece no
IDA*, uma vez que o algoritmo acaba por ter visitar os mesmos nós diversas vezes.
Enquanto o A* recorre a uma lista de nós abertos para manter a fronteira de
procura, o Finge Search guarda um conjunto de nós a ser usado em cada iteração. Este
conjunto não necessita de ser ordenado o que constitui uma vantagem face ao A* e ao
IDA*
O Fringe Search tal como o A* determina um custo f(n) a cada vértice que
expande, baseado na mesma fórmula: o custo do caminho do primeiro vértice ao vértice
corrente g(n), mais a heurística para estimar o custo do vértice corrente ao vértice final
h(n).
A estrutura de dados usada pelo algoritmo Fringe Search pode ser conceptualizada
como duas listas:
“agora” (now) lista destinada para a iteração atual;
“depois” (later) lista destinada para a próxima iteração.
Esta estrutura de dados guarda ainda o vértice da cabeça da lista “agora” designado
por head.
O algoritmo Fringe Search guarda um limiar de procura.
Durante a etapa inicial do algoritmo a lista “agora” é preenchida com o vértice raiz
(root), a lista “depois” é inicializada a vazio e o limiar de procura é valorizado com o
maior número possível.
Na etapa seguinte, o algoritmo repete os seguintes passos:
O vértice head é examinado e duas ações podem ocorrer:
se f(head) é maior que o limiar, então o nó head é removido da lista “agora”
e colocado no fim da lista “depois”. Isto significa que o vértice head não é
necessário ser considerado nesta iteração, sendo guardado para a próxima
iteração;
35
se f(head) é menor ou igual ao limiar, então iremos expandir o vértice head,
sendo os seus vizinhos adicionados ao inicio da lista “agora”. O vértice head
é descartado depois deste passo.
No final de cada iteração, caso o vértice final não tenha sido encontrado, o limiar de
procura é aumentado, a lista “depois” é copiada para a lista “agora” sendo
posteriormente inicializada a vazio.
A principal diferença entre o algoritmo A* é que o algoritmo Fringe Search,é que
no último não ocorre a ordenação das suas listas o que resulta num ganho significativo
em relação ao A*, que muitas vezes necessita de manter a ordem das listas. Esta
diferença pode justificar os resultados dos estudos que indicam que o Fringe Search em
grelhas apresenta uma performance superior ao A* de cerca de 25%. Contudo, são
apontadas também algumas desvantagens a este algoritmo:
necessidade de maior quantidade de memória alocada, uma vez que, para cada nó
encontrado é também armazenada o nó anterior. Este consumo é ainda maior
quando comparado com o A*, uma vez que o número de nós visitados é
significativamente maior (Björnsson et al., 2005).
repetição de visitas ao mesmo vértice;
visita de vértices considerados como irrelevantes para a iteração corrente. Isto é,
vértices que apresentam um valor f(n) muito alto, que só são necessários nas
próximas iterações, onde o limiar de procura é mais alto. Apesar das desvantagens,
o custo de cada visita é constante em comparação com o pior cenário na ordenação
da lista do A* que apresenta uma complexidade logarítmica (Björnsson et al., 2005).
2.3 Sumário
Esta secção pode ser dividida em duas partes: geração processual de conteúdo e
sistema de navegação.
Na primeira parte foi enfatizada a importância da geração processual de conteúdo,
tendo sido descrito as vantagens e desvantagens associadas a este tipo de técnicas. Esta
parte da secção foi finalizada com a descrição das características que podem ser usadas
na classificação das diversas técnicas de geração processual de conteúdo.
Na segunda secção foi discutida a necessidade de converter o ambiente de jogo 3D
complexo em grafos de navegação indicados utilizados pelos algoritmos de procura.
36
Foram apresentados três métodos de abstração principais do ambiente de jogo. Para
cada um dos métodos foi dado um exemplo e destacadas as suas vantagens e
desvantagens.
Na primeira abordagem o navgraph é construído pela adição e ligação de pontos de
passagem através de um processo manual e/ou automático. Este método oferece o
espaço de procura mais pequeno das três técnicas, contudo a necessidade obrigatório da
intervenção humana e o tempo de processamento inerente ao processo de adição/ligação
de pontos de passagem faz desta abordagem imprópria para ser aplicada a ambientes
criados em tempo de execução e ambientes dinâmicos.
A segunda técnica é a mais simples e consiste em adicionar uma grelha com células
de tamanho regular ao ambiente de jogo e posteriormente calcular a navegabilidade de
cada célula. Neste método a ligação das células é feita através da geometria de
conceção. Este método tem o efeito negativo de gerar o espaço de procura maior das
três técnicas abordadas, contudo os ganhos inerentes a esta abordagem, nomeadamente
a geração e atualização rápida, tornam esta técnica aplicável a ambientes gerados em
tempo de execução e ambientes dinâmicos.
A última técnica consiste em usar a malha de polígonos do chão do ambiente de
jogo como nós do grafo e conectar cada nó com base nas arestas comuns. Esta
abordagem permite gerar mapas de navegação de grande qualidade, contudo a criação e
atualização desta malha é uma operação dispendiosa em recursos computacionais
fazendo esta técnica inapropriada para os objetivos do presente estudo.
Para além disso, foi ainda discutido uma variedade de algoritmos de procura em
grafos. Verificou-se a relação que o processamento dos algoritmos e os custos de
memória estão associados ao número de nós expandidos. A diminuição do espaço de
procura pode resultar na diminuição do custo de processamento e memória.
O algoritmo Dijkstar’s foi o primeiro algoritmo de procura em grafos abordado.
Devido à pesquisa do espaço de procura não ser orientada ao vértice final, o algoritmo
acaba por explorar um grande número de vértices resultando num grande custo de
processamento e memória, o que o faz deste algoritmo não indicado para o pathfinding
em vídeo jogos.
37
O segundo algoritmo explorado, o melhor-primeiro é uma melhoria ao algoritmo
anterior uma vez que direciona a pesquisa do espaço de procura ao vértice final.
Contudo como tenta mover-se diretamente para o vértice final sem ter em consideração
o caminho já efetuado pode levar o algoritmo a desperdiçar poder de processamento e
memória a explorar um caminho incorreto.
O A* é o algoritmo de procura em grafos mais popular, este fato justifica-se devido
à sua eficiência e à possibilidade de otimização do algoritmo em termos de custo de
memória e processamento.
Por último, o algoritmo Fringe Search mostrou-se ser mais rápido do que o A*
com um custo de memória mais alto. Este algoritmo pode ser considerado como uma
boa opção para a resolução de caminhos quando a memória não é um limite.
38
Capítulo 3
Metodologia de investigação
3.1 Delineamento do estudo
Estudo de carácter correcional e comparativo de dois esquemas de divisão do
ambiente de vídeo jogos (esquema de divisão baseado em grelha e baseado em
quadtree) e dois algoritmos de procura em grafos (A* e Fringe Search).
Num primeiro momento pretendeu-se caracterizar o tempo de processamento e
consumo de memória de cada esquema de divisão de ambiente comparativamente a
operações elementares como a geração do grafo de navegação, quantização e
localização, conexão de vizinhos, inserção de objetos e número de nós.
O segundo momento consistiu em aplicar os algoritmos de procura a cada um dos
grafos de navegação gerados por cada esquema de divisão. Neste momento
contabilizou-se o processamento computacional, número de iterações, número de nós
visitados e expandidos, custo e tamanho do caminho.
Para a análise e tratamento dos dados foi utilizado o programa Microsoft Excel
2010.
3.1.1 Questões e hipóteses de investigação
Foram colocadas as seguintes questões de investigação:
1. É possível aplicar e gerir em tempo de execução o esquema de divisão baseado
em grelha e em quadtree?
2. Existe alguma diferença em tempo de processamento e memória na gestão do
grafo de navegação baseado no esquema de divisão em grelha e em quadtree?
3. De que forma o tempo de processamento e memória são influenciados pela
dimensão do ambiente de jogo em cada tipo de representação do ambiente?
39
4. De que forma o tempo de processamento e memória são influenciados pelo
número de objetos presentes no ambiente de jogo em cada tipo de representação
do ambiente?
5. É possível o esquema de divisão baseado em grelha e quadtree suportar
múltiplos agentes?
6. O esquema de divisão baseado em grelha e quadtree podem ser aplicados em
ambientes dinâmicos?
7. É possível usar o algoritmo Fringe Search no contexto dos vídeo jogos?
8. Existe alguma diferença na procura de caminhos entre o algoritmo A* e o Fringe
Search?
9. De que forma o tempo de processamento na procura de caminhos é influenciada
pela dimensão do ambiente de jogo?
10. De que forma o tempo de processamento na procura de caminhos é influenciada
pelo número de objetos presentes no ambiente de jogo?
11. Existe alguma relação entre o algoritmo A* e Fringe Search e o tipo de
representação do ambiente?
As seguintes hipóteses foram colocadas ao longo deste projeto:
1. Sim, para ambos os esquemas de divisão do ambiente de jogo é possível aplica-
los e gerir em tempo de execução.
2. Sim, o grafo de navegação baseado no esquema de divisão baseado em grelha
apresenta um tempo de processamento e consumo de memória superior ao
esquema de divisão baseado em quadtree.
3. A dimensão do ambiente influencia diretamente a memória e o tempo de
processamento necessário para cada tipo de representação do ambiente.
4. O número de objetos presentes no ambiente de jogo influencia o tempo de
processamento e memória no esquema de divisão baseado em quadtree sem
contudo influenciar o esquema de divisão baseado em grelha.
5. Sim, é possível o uso de ambos os esquemas de divisão do ambiente de jogo no
suporte múltiplos agentes.
6. Sim, é possível o uso de ambos os esquemas de divisão do ambiente de jogo no
suporte a ambientes dinâmicos.
7. Sim, é possível o uso do algoritmo Fringe Search no contexto dos vídeo jogos.
40
8. Sim, o algoritmo Fringe Search apresenta um tempo de processamento na
procura de caminhos inferior e menor número de nós expandidos do que o
algoritmo A*. Contudo, apresenta um número superior de nós visitados.
9. A dimensão do ambiente influencia diretamente o tempo de processamento na
procura de caminhos em ambos os algoritmos de procura em grafos.
10. O número de objetos presentes no ambiente de jogo influencia diretamente o
tempo de processamento na procura de caminhos em ambos os algoritmos de
procura em grafos.
11. Os algoritmos de procura em grafos apresentam ambos um tempo de
processamento menor na representação do ambiente baseado na quadtree quando
comparado com a grelha.
3.2 Material e Métodos
3.2.1 Caracterização da amostra
No contexto do estudo a amostra consistiu em nove ambientes de jogo. Cada
ambiente é caracterizado por duas componentes: dimensão e densidade de objetos
contidos no ambiente. A dimensão do ambiente pode variar entre pequena (20
unidades), média (160 unidades) e grande (512 unidades). Ao lidar com dois tipos
diferentes de esquemas de divisão houve a necessidade de assegurar que o número
máximo de nós gerados e a dimensão mínima de cada célula fossem iguais para cada
representação (ver Tabela 5).
Dimensão mínima da célula Nº máximo de nós
Pequena 2.5 Unidades 64
Média 2.5 Unidades 1024
Grande 2 Unidades 65536
Tabela 5 - Tamanho mínimo da célula e número máximo de nós com base no tamanho do ambiente.
A categoria densidade de objetos contidos no ambiente de jogo, expressa o
número de obstáculos existentes no ambiente. Com vista a gerar o mesmo número de
nós ocupados, foi assegurado de que cada objeto ocupe uma célula e que cada célula
só contenha um só objeto. Desta forma, para cada esquema de divisão foi assegurado
de que cada objeto corresponde a um nó ocupado. A densidade de objetos pode variar
41
entre: pouco povoado (25% dos nós ocupados), povoado (30% dos nós ocupados) e
muito povoado (35% dos nós ocupados).
Pouco povoado (25%) Povoado (30%) Muito povoado (35%)
Pequena 16 19 22
Média 256 307 358
Grande 16384 19660 22937
Tabela 6 - Tamanho do ambiente e densidade de objetos no ambiente de jogo.
Com base nestas duas categorias cada ambiente foi gerado de forma aleatória,
tendo sido colocado dois pontos de passagem em cada ambiente com o objetivo de
serem usados na procura de caminho entre esses dois pontos (A e B). A seleção de
cada ambiente obedeceu a uma série de critérios de inclusão e exclusão.
Critérios de inclusão
o tamanho do ambiente corresponde a uma dimensão da categoria dimensão;
o número de objetos corresponde a uma densidade da categoria densidade de
objetos;
cada esquema de divisão divide o ambiente em células de dimensão mínima igual;
cada esquema de divisão gera um número máximo de nós igual;
cada esquema de divisão apresenta o mesmo número de nós ocupados;
cada objeto ocupa apenas uma célula;
cada célula é ocupada apenas por um objeto;
Critérios de exclusão
impossibilidade de navegar do nó A ao nó B e vice-versa;
o nó A e/ou o nó B ocupados por um obstáculo;
Para a recolha de dados cada elemento da amostra foi submetido a um conjunto
de operações, sendo este processo repetido 200 vezes com a excepção da operação de
procura de caminhos que foi repetida 500 vezes. A recolha da amostra foi feita num
42
único período de tempo, com a duração de 4 dias. Pensamos que o número de
ambientes e situações (operações) avaliadas permitiu-nos estudar as questões em
estudo.
3.2.2 Instrumentos
Neste subcapítulo abordamos os instrumentos, neste caso as ferramentas usadas na
realização do presente estudo. Para além da ferramenta de desenvolvimento de software
usada no desenvolvimento da nossa solução, houve a necessidade de recorrer a outros
dois tipos de ferramentas: a ferramenta de prova de conceito e a ferramenta de
avaliação. Esta decisão justifica-se pela necessidade de provar o conceito aprofundado
no Capítulo 4 e de o avaliar.
Ferramenta de desenvolvimento de software
A ferramenta de desenvolvimento de software tem por objetivo fornecer a
tecnologia sobre a qual a nossa solução será desenvolvida. A natureza e os requisitos do
nosso estudo para além de implicar o desenvolvimento de um módulo que suporte a
nossa solução, implica ainda o desenvolvimento de artefactos que explorem este
módulo com o objetivo de o testar e avaliar. Enquanto o desenvolvimento do módulo e
do artefacto de avaliação necessita apena de uma linguagem de programação, o
artefacto de prova de conceito implica o desenvolvimento de um protótipo funcional de
um jogo de vídeo que permita verificar e aperfeiçoar as técnicas discutidas em
funcionamento. Começamos por verificar os recursos disponíveis para o
desenvolvimento de jogos de vídeo e dos seus módulos: código máquina (assembly),
bibliotecas (ex.: OpenGL/DirectX/SDL), Toolkits (ex.: Ogre3D, Crystal Space),
Software Development Kit’s (SDK’s) (ex.: Dark Game SDK) e motores de jogos (game
engine) (ex.: Unreal Engine).
Biblioteca: define-se por um conjunto de funções que desempenha uma tarefa;
Toolkit é uma coleção de classes que fornecem um conjunto de serviços;
SDK é uma biblioteca usada para no desenvolvimento do software;
Motor de jogo é um programa de computador e/ou conjunto de bibliotecas que
disponibiliza um conjunto de funcionalidades que visam facilitar o desenvolvimento
de um jogo. As funcionalidades típicas de um motor de jogo são: motor gráfico
(renderização gráfica 2D e/ou 3D), motor de física (aplica os princípios da física a
modelos 3D e deteção de colisões), animações, som, inteligência artificial, redes,
gestão de memória, gestão de ficheiros e linguagem script. O motor gráfico inclui
características como a luminosidade, texturas e sombras.
43
Para cumprir os objetivos de desenvolvimento descritos e cumprir com os prazos
inerentes ao estudo, o recurso escolhido deve assegurar a interoperabilidade entre o
módulo e os dois artefactos, e ainda evitar perda de tempo em desenvolvimentos
desnecessários aos nossos objetivos procurando assim evitar o reinventar da roda. Dos
recursos disponíveis selecionamos como recurso o motor de jogo. Esta escolha deve-se
ao facto deste recurso ser uma tecnologia bastante completa, com uma curvatura de
aprendizagem e tempo de desenvolvimento rápidos. Para a escolha do motor de jogo
mais indicado procedemos à pesquisa e análise dos motores de jogo mais populares na
atualidade. O resultado desta pesquisa é descrito brevemente em baixo, mostrando,
deste modo, a escolha para o estudo.
Software Livre
Blender
O Blender é um programa de computador de código aberto, criado inicialmente
pelo estúdio de animação holandês NeoGeo Studio. Atualmente é desenvolvido pela
Blender Foundation para modelagem, animação, texturização, composição,
renderização, edição de vídeo e criação de aplicações interativas 3D. É um software
multiplataforma estando disponível para os principais sistemas operativos: Microsoft
Windows, Linux, Mac OS X.
O Blender disponibiliza um motor de jogo conhecido por Blender Game Engine
para a criação de aplicações interativas 3D, tais como jogos, apresentações,
planeamentos arquitetónicos, entre outros.
Este programa fornece ainda um conjunto de ferramentas avançadas de
simulação: dinâmica de corpo rígido, dinâmica de corpo macio e dinâmica de fluidos,
ferramentas de modelagem baseadas em modificadores, ferramentas de animação de
personagens, cenas e imagens, editor de imagem e vídeo com suporte a pós-produção.
Como linguagem de script usa o Python.
jMonkey Engine
O jMonkey Engine , também conhecido por jME, é um motor de jogo baseado
em gráficos API de código aberto sob a licença BSD. A versão mais atual vem integrada
Ilustração 17 - Logotipo do Blender.
44
num SDK. Este motor é escrito em Java e usa como renderizador gráfico o LWJGL
(Lightweight Java Game Library) com suporte a OpenGL (Pedro & Nunes, 2009).
Ogre
O Ogre (Object-oriented Graphics Rendering) foi desenvolvido em 2001 sob a
licença de software livre (GNU LGPL). Não realidade não é um motor de jogo, mas sim
um motor gráfico que possibilita: desenvolvimento de jogos, planeamento arquitetónico,
simulações ou qualquer aplicação que necessite de renderização gráfica. O Ogre insere-
se na categoria de toolkit e é composto por um conjunto de bibliotecas em C++ como
um motor de renderização 3D em tempo real. Além da biblioteca principal é ainda
disponibilizado um conjunto de plug-ins, ferramentas e add-ons que possibilitam a
criação de diferentes aplicações gráficas. É bastante utilizado no aperfeiçoamento de
videojogos uma vez que os seus recursos aumentam o desempenho durante a
renderização de cenários e objetos tridimensionais. O Ogre suporta diferentes
configurações de hardware e é compatível com DirectX e OpenGL (Netto, Machado,
Marcos, Pedro, & Nunes, 2006).
O Ogre possui ainda uma comunidade ativa e recentemente apresenta suporte
para Linux, Windows, Mac OSX, IOS, Windows Phone 8 e Android.
Ilustração 19 - Logotipo do Ogre.
Panda3D
O Panda 3D é um motor de jogo, constituído por conjunto de bibliotecas C++ que
usa como linguagem de script o Python para invocar estas bibliotecas, aumentando o
nível de abstração durante o desenvolvimento e permitindo assim uma aprendizagem
Ilustração 18 - Logotipo do jMonkey Engine
45
rápida. Este motor de jogo é de código aberto sob a licença BSD e lidera o topo de
preferências dos utilizadores de motores de jogo de código livre.
Esta ferramenta usa o conceito de objetos e nós, com o objetivo de aumentar o
desempenho na renderização das cenas. Este conceito permite que os filhos do mesmo
nó partilhem os mesmos atributos do pai, como por exemplo iluminação, transparência,
entre outros.
O Panda 3D disponibiliza efeitos de iluminação, efeito de sombra, motor de
física (com deteção de colisões), sistema de partículas, texturas e motor de som (Netto
et al., 2006).
Este motor permite a visualização do desempenho em tempo real, disponibilizando
ainda ferramentas de otimização de desempenho e de debug (Pedro & Nunes, 2009).
Por detrás do Panda3D existe uma comunidade pequena, mas ativa.
Ilustração 20 - Logotipo do Panda3D.
Software comercial
Torque Game Engine 3D
Torque Game Engine 3D também conhecido por TGE é um motor de jogo 3D
criado originalmente pela Dynamic e atualmente desenvolvido pela GarageGames. É o
motor de jogo comercial eleito pela maioria dos programadores de jogos, possuindo
dois tidos de licenciamento: uma para programadores independentes e outra para
programadores profissionais.
Destaca-se uma biblioteca de rede para múltiplos jogadores, criação de
interfaces e colisões até 256 jogadores. Disponibiliza um editor integrado em tempo de
execução e apresenta um conjunto de ferramentas de edição de terreno, sombras,
texturização, pintura entre outros.
O Torque 3D suporta o carregamento de ficheiros das ferramentas de arte mais
conhecidas como: 3ds Max, Maya, Blender.
46
A linguagem de programação utilizada é o C++ e como linguagem script o
TorqueScript.
É multiplataforma com suporte aos sistemas operativos: Microsoft Windows,
Mac OS X, Wii, Xbox 360, iOS e Linux. Possibilita ainda a publicação do jogo
desenvolvido na Web com suporte aos principais explorares de internet.
Ilustração 21 - Logotipo do Torque Game Engine.
Unreal Development Kit
O Unreal Development Kit (UDK) foi criado e desenvolvido pela Epic Games
tendo a sua primeira aparição no jogo FPS mundialmente conhecido, o Unreal (1998).
Este toolkit foi usado para a criação de alguns dos jogos comerciais de FPS mais
conhecidos: “Unreal Tournament”, “Deus Ex”, “Turok”, “Tom Clancy’s Rainbow Six
3: Raven Shield”, “Tom Clancy’s Rainbow 6: Vegas”, “America’s Army”, “Red Steel”,
“Gears of War”, “BioShock”, “BioShock 2”, entre muitos outros.
O seu núcleo é escrito em C++, o que possibilita um grau elevado de
portabilidade, suportando muitas plataformas: Mac OS X, Linux, PlayStation 2 e 3, Wii
U, iOS, Xbox 360, Dreamcast, Android e suporta DirectX e Open GL.
Ilustração 22 - Logotipo do Unreal Development Kit.
Unity 3D
O Unity é uma plataforma de desenvolvimento de aplicações interativas 2D e
3D. Esta ferramenta para além de disponibilizar as funcionalidades típicas de um motor
47
de jogo, disponibiliza ainda um editor visual, que possibilita visualizar o jogo e criar um
jogo completo a partir desse ambiente de desenvolvimento. Este motor tem alcançado
alguma notoriedade devido à possibilidade de criar jogos de grande complexidade de
uma forma simples e com gastos reduzidos.
Outra característica do Unity é a possibilidade de exportar o mesmo jogo para as
plataformas mais conhecidas da atualidade, sendo este procedimento na maioria das
vezes transparente ao programador. As plataformas suportadas no momento são:
Windows, Mac OS X, iOS, Android, Navegador Web, Nintendo Wii, Xbox360 e PS3.
O motor de jogo do Unity é construído com a linguagem de programação C++,
sendo possível usar essa linguagem para criar Plugins. Para a criação de jogos de video,
o Unity suporta as seguintes linguagens de programação: C# (framework 3.5), Boo (um
dialeto da linguagem Python) e UnityScript (que é considerado uma variante própria de
javascript).
O Unity 3D possui sete tipos de licenças distintas, cada uma destinada a um tipo
de programador ou plataforma.
Ilustração 23 - Logotipo do Unity.
O desenvolvimento através do Unity 3D é feito através do editor disponibilizado
para o efeito. O editor do Unity 3D é composto por um conjunto de janelas, existem 5
janelas principais:
Projeto: contem todos os recursos usados na criação do jogo ex.: modelos, prefabs,
terrenos, texturas, scripts entre outros;
Cenário: onde são posicionados os objetos de jogo (GameObjects), permite
visualização do ambiente de jogo e adicionação de recursos através de drag and
drop;
Jogo: mostra aquilo que o jogador irá ver;
Hierarquias: lista todos os GameObjects presentes cenário, nesta janela é possível
identificar as dependências entre os objetos;
48
Inspetor: permite ajustar as propriedades e adicionar novos componentes aos
objetos listados na janela de hierarquias.
A criação tradicional de um jogo em Unity 3D consiste resumidamente em
construir cenários. A cada cenário são adicionados manualmente recursos da janela
projeto ou do próprio Unity 3D. Cada objeto adicionado pode ser visualizado na janela
hierarquias, esta janela permite ainda verificar e manipular a dependência entre os
objetos. Na janela Inspetor podemos manipular as propriedades dos diversos objetos e
adicionar novas componentes (ex.: scripts) a esse objeto. Depois de todos os recursos
adicionados e configurados o utilizador pode verificar o resultado final através da janela
Jogo. Este processo pode ser descrito como fácil e intuitivo, contudo muito manual.
O Unity 3D possibilita ainda adição e manipulação de recursos
programaticamente quando necessário.
Após o estudo e análise dos diferentes motores de busca disponíveis no mercado,
foram escolhidos como opções finais o UDK e o Unity. Ambas as ferramentas são
bastante completas e fornecem tudo, ou quase tudo, para o desenvolvimento de um
jogo. O UDK é um motor poderoso e flexível com resultados provados. Contudo este é
recomendado a utilizadores experientes. Desta forma, a nossa escolha recaiu sobre o
Unity 3D pois para além de reunir todos os requisitos necessários para o
desenvolvimento da solução, é um motor de jogo poderoso e flexível com uma reduzida
curva de aprendizagem que conta com uma vasta comunidade de utilizadores e uma boa
coleção de documentação de apoio ao desenvolvimento.
Embora o Unity 3D possua uma versão livre que pode ser usada tanto para
investigação como para fins comerciais, foi usada uma licença Pro disponibilizada
gratuitamente.
Outro fator preponderante à escolha apresentada é a possibilidade do
desenvolvimento poder ser feito inteiramente em C# e, desta forma, usufruir das
características inerentes a esta tecnologia como o modelo de orientação a objetos, uso de
interfaces, gestão de memória, entre outros. O C# é uma linguagem de programação
usada largamente em escala mundial com o suporte da Microsoft e de uma gigante
comunidade de programadores. Outra vantagem é a possibilidade da utilização do
ambiente de desenvolvimento integrado (IDE) Microsoft Visual Studio juntamente com
o Unity. Este IDE fornece um conjunto valioso de ferramentas como a deteção de erros,
intelli-sense, entre outros, e permite ainda um desenvolvimento organizado e dividido
em projetos. Foi usada a versão Microsoft Visual Studio 2012, uma vez que é a versão
49
mais recente, com suporte à framework 3.5 e disponibilizada gratuitamente pelo portal
MSDNAA.
Ferramenta de prova de conceito
A ferramenta de prova de conceito consiste num protótipo funcional de um jogo de
vídeo gerado automaticamente em tempo de execução com o objetivo de permitir
observar em ação as diversas técnicas estudadas. Neste subcapítulo serão abordados
algumas características desta ferramenta, sendo os detalhes de implementação
abordados no subcapítulo 4.3.2 .
Esta ferramenta foi construída sobre o motor de jogo Unity 3D recorrendo a
bibliotecas desenvolvidas em C# (framework 3.5). A versão atual do sistema permite
gerar automaticamente e em tempo de execução um ambiente de jogo de vídeo (terreno,
agentes e obstáculos) com base num conjunto de atributos definidos manualmente antes
da execução, através do menu de configuração e/ou informação contida em ficheiros do
tipo XML.
Cada ficheiro do tipo XML contém a informação de um ambiente de jogo
(simulação). Neste ficheiro é possível indicar:
o terreno e especificar as suas características (resolução da malha, número de
subdivisões, localização, tamanho e amplitude);
obstáculos e descrever para cada um o seu tamanho e localização;
NPC’s e especificar para cada um destes a velocidade máxima de movimentação e
rotação e ainda um caminho pré-determinado (conjunto de pontos de passagem).
As simulações são geradas automaticamente por geradores, consoante o tipo de
simulação, podendo esta ser ou não aleatória tendo por base um conjunto de regras. A
inclusão de uma nova simulação implica a adição de um gerador e alteração do menu da
interface.
O menu de configuração da aplicação permite escolher a simulação que se pretende
efetuar através da seleção do ficheiro XML, podendo ser alterada algumas
configurações dessa simulação através da interface. Para além disso, é possível definir o
tipo de esquema de divisão e o algoritmo de procura que se pretende aplicar, podendo
ser especificado algumas opções como o esquema de cores entre outros (ver Ilustração
24).
50
Ilustração 24 - Menu de configuração.
Embora o menu de configuração já apresente essa opção, a componente Path
Smooter ainda não é inteiramente suportada.
Ferramenta de avaliação
A ferramenta de avaliação consiste numa aplicação de processamento batch, na
qual não é exigida a interação do usuário e onde ocorre o processamento de dados
contidos em um ou mais ficheiros XML com vista à avaliação da arquitetura descrita no
Capítulo 4.
Neste subcapítulo serão abordados algumas características desta, ficando os
detalhes de implementação reservados para o subcapítulo 4.3.3 .
Esta ferramenta foi construída sobre as bibliotecas desenvolvidas em C#
(framework 3.5) e recebe como parâmetro um ficheiro de configuração em que cada
entrada do ficheiro representa uma simulação que se pretende avaliar. Cada entrada é
constituída por um conjunto de parâmetros em que cada um aponta para um ficheiro
XML específico. Os parâmetros atualmente disponíveis são: esquema de divisão
(baseado em grelha ou em quadtree), algoritmo de procura em grafos (A* ou Fringe
Search), dimensão do terreno (pequena, média ou grande), procedimentos e número de
repetições a efetuar dos procedimentos.
Os procedimentos são constituídos por um conjunto de operações que são
executadas de forma linear, sendo o resultado de cada operação avaliado (tempo de
51
processamento e memória) e guardado num ficheiro específico com base na operação e
simulação. O sistema atualmente suporta as seguintes operações:
inicialização do grafo de navegação;
inicialização do algoritmo de procura;
adição de objetos durante a inicialização do grafo de navegação (implica apenas
uma conexão de vizinhos);
adição de objeto (implica uma conexão por de vizinhos por cada objeto adicionado).
dimensão do espaço de procura;
quantização (conversão de uma posição do ambiente de jogo em nó);
localização (conversão de um nó em uma posição do ambiente de jogo);
conexão de vizinhos;
procura de caminho.
Para a geração do ficheiro XML de procedimentos foram construídos dois tipos
geradores: um independentemente da ferramenta de prova de conceito e outro que
recorre à aplicação de prova de conceito com o objetivo de avaliar os ambientes.
3.2.3 Procedimentos
Num primeiro momento realizou-se uma pesquisa bibliográfica geral sobre o tema
dos jogos de vídeo, com o objetivo de aumentar o conhecimento na área e perceber o
estado da arte. Devido ao campo dos vídeos jogos ser bastante vasto, o conhecimento
inicialmente adquirido foi usado em reuniões de supervisão para debater ideias e
colocar/descartar de hipóteses de estudo.
Num segundo momento, com o objeto de estudo mais amadurecido procedeu-se
a uma nova pesquisa bibliográfica, desta vez mais focada aos objetivos traçados na fase
anterior. A revisão bibliográfica dividiu-se principalmente em três campos:
representação de espaços físicos do vídeo jogo com vista à navegação, resolução do
problema de procura de caminhos e locomoção de agentes artificiais em jogos de vídeo.
Realizou-se novamente um conjunto de reuniões onde desta vez procedeu-se ao
planeamento e delineamento do estudo. A pesquisa efetuada permitiu perceber o estado
da arte nesta área de estudo e ainda entender melhor os desafios que se pretende superar.
Foi ainda possível realizar uma pesquisa dos motores de jogo mais atuais e usados no
mercado com vista ao desenvolvimento do projeto. Esta fase terminou com a elaboração
do relatório preliminar.
52
Na fase seguinte procedeu-se ao desenho do sistema com base nos objetivos
traçados e nos conhecimentos adquiridos até então. Durante esta fase procedeu-se ainda
a pesquisa bibliográfica contínua, de forma a limar arestas do estudo, como por exemplo
questões não contempladas até então. Nesta fase ocorreu também a familiarização com
tecnologia a ser usada. Embora só na fase seguinte estivesse planeada a implementação
do desenho do sistema, também se procedeu a um conjunto de provas de conceito.
As provas de conceito foram importantes na medida que permitiram guiar o
desenvolvimento do sistema com base em dados reais. Desta forma, foi possível
proceder a otimizações, evitar o uso de técnicas mais complexas e estimar prazos de
forma mais precisa e realista.
Com a implementação acabada foi possível testá-la e avaliá-la de forma geral
através da ferramenta prova de conceito. Contudo, só depois do desenvolvimento da
ferramenta de avaliação foi possível avaliar, de forma concreta, o sistema. A avaliação
do sistema para além de permitir proceder a algumas alterações, com vista ao aumento
do desempenho, possibilitou a recolha de dados para o presente estudo.
O momento final consistiu na elaboração do relatório final onde foram indicados
os resultados dos dados obtidos, e feita uma análise critica e discussão dos mesmos.
3.2.4 Metodologia estatística
Para o tratamento estatístico, dos dados recolhidos foram removidos os 50
melhores e piores resultados. Posteriormente foi calculada a média dos dados recolhidos
para cada operação e modo de execução, tendo posteriormente sido feita a comparação
dos resultados obtidos.
3.3 Sumário
Neste capítulo foi descrito em detalhe a metodologia de investigação usada para
alcançar os objetivos propostos. Foi delineado o estudo e o material e métodos usados,
tendo sido descrito a amostra alvo as ferramentas e procedimentos usados.
53
Capítulo 4
Trabalho realizado
4.1 Análise do problema
No desenvolvimento de um projeto é fundamental realizar uma análise antes da
conceptualização de qualquer desenho da aplicação. É necessário olhar para os objetivos
do estudo (ver Capítulo 1.2 ), para os trabalhos relacionados existentes até então (ver
Capítulo 2 e 2.2 ) e compreender os problemas que se pretendem resolver, para depois
ser possível conceber um desenho capaz de ser implementado de acordo com os
requisitos funcionais especificados.
É importante perceber o contexto onde o projeto se insere, tais como as limitações
e restrições a que se está sujeito. O problema do pathfinding em jogos de vídeo está
relacionado com requisitos: de tempo real e de múltiplos agentes. Estes requisitos, por
sua vez, estão limitados aos recursos do sistema computacional, nomeadamente a
velocidade de processamento e memória. A natureza finita destes recursos e a noção de
que a IA de um jogo de vídeo é apenas uma das diversas componentes de um jogo e que
apenas tem uma pequena fatia destes recursos reservada para ela, mostram a
importância da utilização e gestão correta destes recursos. Desta forma, a análise do
nosso problema deverá ter sempre por base estas premissas.
Na análise dos desafios propostos para o projeto é também essencial estudar as
alternativas capazes de responder aos requisitos funcionais.
O presente estudo tem como problema principal o desenvolvimento de um sistema
de navegação baseado em grafos de navegação gerados automaticamente durante o
tempo de execução, com o objetivo de suportar a geração on-line de ambientes virtuais.
A geração automática de ambientes virtuais afasta a possibilidade do uso de
técnicas que usem dados pré processados do ambiente de jogo, como por exemplo o uso
54
de grafos de navegação hierárquicos. Isto limita o leque das técnicas possíveis de serem
empregues e aumenta o problema de lidar com ambientes de jogo de grande dimensão.
Para além do requisito de automatismo e tempo de execução inerentes ao objetivo
principal, a complexidade do estudo é agravada com o delineamento dos requisitos
primários e secundários (ver Capítulo 1.2 ). Está-se, portanto, perante um problema
complexo com implicações nas diversas componentes do sistema de navegação. Para
melhor entendimento da problemática recorremos à técnica “Divisão e Conquista”,
analisando cada problema separadamente e o seu impacto nas componentes do sistema
de navegação.
4.1.1 Geração automática e em tempo de execução
de grafos
A construção de um grafo de navegação é feita através do esquema de divisão. O
esquema de divisão é responsável por dividir o espaço físico do ambiente de jogo em
nós e conectá-los posteriormente. A geração automática e em tempo de execução de um
grafo de navegação baseado num ambiente de jogo inteiramente novo, implicam um
processo:
que não necessite da intervenção do ser humano;
geração rápida o suficiente, de modo a passar despercebida ao utilizador;
construção de um grafo de navegação inteiramente novo;
4.1.2 Ambientes de jogo com dimensões diferentes
O número de nós de um grafo de navegação está associado ao tipo de esquema de
divisão usado e ao tamanho do ambiente de jogo. Quanto maior a dimensão do ambiente
de jogo, maior o número de nós do grafo necessário para cobrir o ambiente na sua
totalidade.
Um grande número de nós, para além de ter repercussão na memória do sistema,
que necessita de armazenar toda esta informação, por cada procura de caminho
efetuada, o sistema vai alocar mais memória e despender mais tempo de processamento
na resolução do caminho, uma vez que tem de percorrer um maior número de nós.
Os programadores para lidarem com ambientes de jogo muito grandes geralmente
recorrem a grafos de navegação hierárquicos, de modo a diminuir os custos durante a
procura de caminhos. Esta técnica implica dividir o ambiente em regiões e fazer
corresponder cada região a um nó, o qual será ligado aos restantes nós das outras
regiões. Cada região tem um grafo de navegação, em que um dos nós corresponde ao nó
que representa a região. Para simplificar as procuras, os programadores ainda recorrem
55
a tabelas de indexação das regiões. Contudo esta técnica não é possível ser aplicada no
presente estudo, uma vez que o processo de identificação das regiões implica um custo
de processamento elevado e necessita do envolvimento do ser humano. Esta técnica é
aplicada durante a fase de desenho do mapa sendo as tabelas usadas, na procura de
caminho, pré-geradas.
4.1.3 Múltiplos agentes
A gestão de múltiplos agentes é um problema complexo e comum a outras áreas de
estudo como por exemplo a robótica. Nos vídeo jogos:
está limitada aos recursos do próprio sistema;
gerida de forma central ou distribuída;
ao encargo de uma ou mais componentes do sistema de navegação.
A gestão de múltiplos agentes difere de jogo para jogo, consoante o tipo de jogo,
tipo de agente e complexidade da IA. A gestão de múltiplos agentes no presente estudo
diz respeito ao suporte de múltiplos agentes, e não à resolução da problemática em si,
como por exemplo a colisão de NPC’s. A finalidade é possibilitar de forma genérica a
aplicação das técnicas abordadas a ambientes com múltiplos agentes, disponibilizando
os meios e não a forma de o fazer. A resolução da problemática fica então ao encargo do
programador consoante as especificações do vídeo jogo, procuramos assim simplificar o
objeto de estudo.
O suporte de múltiplos agentes deve ter em conta os recursos limitados do sistema,
devendo consumir o menor número possível de recursos. É possível responsabilizar
uma ou mais componentes pelo suporte a múltiplos agentes, podendo esta
responsabilidade estar centralizada ou distribuída.
O tipo de esquema de divisão deve gerar um grafo de navegação que forneça mais
informação do que simples pontos-chave do ambiente de jogo, caso contrário os agentes
irão deslocar-se sempre pelo mesmo trajeto apresentando um comportamento artificial.
Esta componente deve ser central a todos os NPC’s, com vista a minimizar o consumo
de recursos e evitar a atualização e manutenção da congruência de diversos grafos de
navegação.
A camada responsável pela procura de caminhos pode ser centralizada ou
descentralizada. A centralização implica uma instância da camada de procura de
caminhos, responsável pela resolução de todos os pedidos de caminhos de todos os
NPC’s. A descentralização desta camada implica várias instâncias a resolver pedidos de
caminho simultaneamente. Trata-se de um trade off entre o número de pedidos a
resolver ao mesmo tempo e o número de recursos consumidos por cada instância.
56
A complexidade da camada locomoção no suporte de múltiplos agentes está
condicionada à distribuição de responsabilidades pelas diversas camadas e
centralização, ou não, de camada locomoção.
4.1.4 Diferentes tipos de unidades
Na maioria dos jogos de vídeo em que existe diferentes tipos de unidade, cada
tipo possui um grafo de navegação distinto. Esta abordagem permite assim que o
caminho retornado seja sempre correto para esse tipo de NPC. Esta abordagem
apresenta as seguintes desvantagens:
armazenamento em memória de um grafo de navegação, por cada tipo de
unidade;
em ambiente de jogo dinâmico quando existe uma alteração ao ambiente, todos
os grafos de navegação necessitam de ser atualizados;
não pode ser aplicada em mapas gerados automaticamente durante o tempo de
execução, uma vez que esta informação é incluída durante a fase de
desenvolvimento.
Outra abordagem possível é incluir, no algoritmo de procura de grafo,
heurísticas que verifiquem, por exemplo, o tamanho da unidade e determinem um
caminho válido para esta unidade. Esta abordagem tem duas desvantagens:
aumento do processamento, devido ao número de heurísticas avaliadas a cada
procura realizada;
uso de informação pré-processada do ambiente de jogo.
A impossibilidade de utilizar estas duas abordagens com base nos requisitos
propostos remete-nos para uma terceira hipótese, que consiste na responsabilização da
camada locomoção, na validação dos caminhos devolvidos pelo algoritmo de procura e
solicitação de novo caminho caso este não seja possível. Contudo, esta abordagem tem a
desvantagem de que cada agente irá ter de continuamente validar o caminho devolvido
pelo pathfinding, o que consome bastantes recursos no caso de haver muitos agentes.
4.1.5 Deteção de obstáculos dinâmicos
Os agentes que navegam em ambientes dinâmicos, devem conseguir detetar a
presença de obstáculos dinâmicos. A deteção de obstáculos dinâmicos consiste na
deteção de alterações ao ambiente de jogo, como por exemplo, a adição de uma caixa ao
ambiente de jogo que anteriormente não existia. As alterações ao ambiente podem fazer
com que, os caminhos determinados anteriormente pelo pathfinding, estejam agora
57
inválidos, por exemplo o caminho intersetar a localização onde agora se encontra a
caixa.
A deteção de obstáculos dinâmicos é normalmente efetuada através de duas
abordagens diferentes.
A primeira abordagem é semelhante à abordagem descrita para a lidar com
diferentes tipos de unidade (ver capítulo 4.1.4 ). Nesta abordagem, existe a
responsabilização da camada locomoção, pela deteção de alterações ao ambiente de
jogo. Ao ser detetado um novo obstáculo a camada deve solicitar a resolução de um
novo caminho.
A segunda abordagem envolve a modificação do grafo de navegação, de forma a
representar corretamente o ambiente de jogo e a invalidação de todos os caminhos
determinados até então. A atualização do grafo de navegação está ligada ao tipo de
esquema de divisão do ambiente usado.
A invalidação de caminhos é necessária, uma vez que ocorre a alteração do grafo
de navegação, desta forma é possível invalidar caminhos ainda válidos. Esta
aproximação constitui um problema uma vez que todos os agentes em movimento irão
solicitar novos caminhos, o que pode sobrecarregar o sistema.
4.2 Desenho da solução
Após a análise do problema é então necessário desenhar uma solução possível de
ser implementada, que cumpra com todos os requisitos e solucione os problemas
identificados anteriormente.
4.2.1 Sistema de navegação
A complexidade da problemática em estudo e o conjunto de requisitos traçados
implicam uma solução integrada dos componentes do sistema de navegação como um
todo. A análise centrada no problema dá lugar, neste capítulo, ao desenho da solução
centrada em cada componente do sistema de navegação.
Locomoção
A camada locomoção é descentralizada pelos diversos agentes, esta decisão visa
endereçar um conjunto de problemas:
aumentar a escalabilidade do sistema;
suportar ambientes dinâmicos.
suportar diferentes tipos de agentes;
58
permitir definir pontos-chave no mapa, ex.: ronda de patrulha.
O aumento da escalabilidade é alcançando com a independência de cada agente ou
tipo de agentes. Embora não faça parte dos objetivos do presente trabalho, será nesta
camada que, por exemplo, se pode resolver o problema de colisão de agentes através por
exemplo de algoritmos determinísticos.
O suporte a ambientes dinâmicos é alcançado através da realização de pedidos
frequentes de resolução de caminho, permitindo assim que o agente detete as alterações
ocorridas ao grafo de navegação.
Desta forma evita-se a adição de heurísticas à camada de procura de caminhos, esta
decisão reflete o tradeoff, entre o número de heurísticas avaliadas em cada procura de
caminho e o custo de utilização de técnicas como o raycasting. Embora as técnicas,
como o raycasting, estejam associadas ao consumo de recursos do sistema, o número de
validações de caminho pode ser inferior ao número de caminhos retornados. A
validação de caminhos é destinada a dar suporte a diferentes tipos de unidade, e não à
deteção de obstáculos dinâmicos.
Como cada agente ou tipo de agente possui uma camada de locomoção é possível
especificar pontos-chave a esse agente específico ou tipo de agente.
Representação do ambiente
O esquema de divisão é responsável pela geração do grafo de navegação sendo
uma peça fundamental na solução do problema em análise. Deste modo, foi dada
especial atenção aos diversos tipos de esquemas de divisão, tendo sido analisado as
vantagens e desvantagens de cada abordagem (ver 2.2 ) em comparação com os
objetivos em estudo (ver Capítulo 4.1 ). A Tabela 7 sintetiza a análise efetuada.
Pontos de passagem Grelha Malha de navegação
Espaço de procura Mais pequeno Maior: espaço
navegável e não
navegável
Melhor rácio: nº de nó
vs. dimensão do
ambiente
Geração 100%
automática
Não Sim Não
Geração em tempo
de execução
Não Sim Não
Suporte de
ambientes
Não, a operação de
atualização/geração dispendiosa
Sim, a operação
de atualização
Não, a operação de
atualização/geração
59
dinâmico em recursos computacionais e
informação limitada do
ambiente de jogo.
de baixo custo. dispendiosa em
recursos
computacionais.
Tabela 7 - Objetivos vs. tipo de esquema de divisão.
A análise da tabela mostra, que o objetivo de geração automática e tempo de
execução do grafo de navegação, limitam os esquemas divisão ao esquema baseado em
grelha.
O esquema de divisão baseado em grelha tem a vantagem de poder ser aplicado a
ambientes dinâmicos, devido às operações de atualização serem rápidas e de não haver a
necessidade de refazer o grafo de navegação. Outra vantagem é que cada nó deste tipo
de representação possui informação que pode ser usada no suporte de diferentes tipos de
unidade.
O esquema de divisão baseado em grelha tem, como principal desvantagem, o
grande espaço de pesquisa e o grande fator de ramificação que têm efeitos negativos no
consumo de memória e tempo de processamento em cada pesquisa efetuada pelo
pathfinding (Anguelov, 2011). Esta desvantagem é crítica relativamente ao requisito de
suporte de diferentes tamanhos de ambientes de jogo. Existem algumas técnicas
propostas desenvolvidas para aliviar o consumo de recursos e acelerar o pathfinding.
Estas técnicas são geralmente categorizadas em três grupos: redução do espaço de
procura através da abstração usada, aperfeiçoamento da precisão das heurísticas que
guiam a pesquisa (aplicada aos algoritmos de procura) e por último, a deteção de becos
sem saída ou métodos de poda de espaço (Harabor, 2011). A maioria das técnicas
usadas, na primeira e terceira abordagem, envolvem pré-processamento, desta forma
optamos por mitigar o problema do pathfinding pela redução do espaço de procura,
usando a abstração quadtree. A quadtree reduz consideravelmente o espaço de procura
e, no pior caso, apresenta um espaço de procura igual à grelha regular. Com esta
abordagem procuramos diminuir o espaço de procura e aliviar o consumo de recursos
do sistema computacional na procura de caminhos.
Segundo a análise realizada no capítulo 4.1 , a nossa solução recorre a uma camada
de representação do ambiente centralizada numa única instância. Embora esta decisão
limite a escalabilidade da aplicação, tem por objetivo diminuir a alocação de memória e
tempo de processamento na atualização de diversas instância.
60
Algoritmos de procura em grafos
O requisito de geração automática e em tempo de execução limita a escolha de
algoritmos de procura em grafos, que não baseiem o seu algoritmo em dados pré-
processados do ambiente de jogo (ex.: “Hierarchical Path-Finding” (HPA*) (Botea,
Martin, Schaeffer, & Tg, 2004), o HAA* (Harabor & Botea, 2008), ou soluções de
pathfinding dinâmico como o LPA*, o DHPA* ou SHPA* (Kring, Champandard, &
Samarin, 2010) e ao mesmo tempo apresentem um desempenho rápido com baixo
consumo de recursos do sistema computacional. Selecionamos dois algoritmos que
iremos estudar e comparar:
A*, uma vez que se trata de um algoritmo bastante conhecido e utilizado
praticamente em todos os vídeo jogos;
Fringe Search, que mostrou resultados de processamento mais rápidos e um
consumo de memória maior quando comparado com o A* (Björnsson et al., 2005).
A primeira escolha baseia-se por ser o algoritmo “padrão” usado nos vídeos jogos e
a segunda escolha justifica-se devido a ser um algoritmo pouco conhecido e estudado,
que aponta resultados superiores ao A*.
Com vista ao suporte de múltiplos agentes, a nossa solução recorre às
potencialidades da tecnologia multithreading existente em algumas plataformas de jogo,
desta forma várias instâncias desta camada podem ser criadas e usadas na resolução de
caminhos. A solução consiste então em ter várias instâncias a iterar sobre um espaço de
procura comum, resultando no aumento do número de pedidos processados com pouco
custo de memória.
4.3 Implementação
Este capítulo descreve a implementação da solução, tendo em consideração os
requisitos técnicos e funcionais identificados e seguindo a especificação da arquitetura
descrita anteriormente. A arquitetura foi definida como uma biblioteca e é o núcleo da
solução. Este núcleo contém todas as estruturas e algoritmos necessários ao sistema de
navegação os quais aprofundamos neste capítulo. Para o desenvolvimento e exploração
do sistema de navegação foram desenvolvidas duas ferramentas distintas: ferramenta de
prova de conceito e ferramenta de avaliação (ver Ilustração 25).
61
A caracterização de cada uma destas ferramentas é feita no capítulo 3.2.2 ,neste
capítulo são abordados os detalhes de implementação de cada uma.
4.3.1 Sistema de navegação
O sistema de navegação, foi implementado como uma biblioteca usando a
tecnologia C# Framework 3.5, versão suportada pela versão mais atual do Unity 3D
4.0.l. A construção da arquitetura como biblioteca permite separar a lógica de negócio
(sistema de navegação), das aplicações em si (ferramenta de prova de conceito e
ferramenta de avaliação), possibilitando o uso da biblioteca por qualquer aplicação
desenvolvida em C# com Framework 3.5, ou superior.
Do ponto de vista técnico a implementação do sistema de navegação recorreu ao
paradigma da programação orientada a objetos usando os artefactos de abstração,
encapsulamento, herança e polimorfismo, sendo promovido a simplificação da
implementação e a reutilização de código.
O sistema de navegação é composto por 4 módulos:
comum: conjunto de variáveis, funções e classes partilhada pelos restantes módulos
e por aplicações desenvolvidas que explorem esta biblioteca;
locomoção: responsável por gerir agentes. Esta camada interage com a camada de
algoritmos de procura para a resolução de caminhos;
representação do ambiente: responsável por gerir a representação do ambiente na
forma de grafo de navegação;
algoritmos de procura: responsável por gerir os algoritmos de procura. Esta camada
interage com a camada responsável pela gestão da representação do ambiente;
Ilustração 25 - Arquitetura subdividida em três módulos distintos.
62
Os módulos representação do ambiente e algoritmos de procura são geridos
respetivamente por um gerente. Cada gerente é responsável por inicializar e gerir uma
ou mais instâncias desse módulo e responder a pedidos.
Locomoção
A descentralização desta componente implica que cada NPC implemente uma
instância da camada de Locomoção, cada instância dispõe de:
conjunto de atributos, que podem ser omissos, destinados a um NPC específico ou a
um tipo de NPC. Dentro destes atributos é possível definir um caminho pré-
definido, constituído por um conjunto de localizações do ambiente de jogo
(semelhante aos pontos de passagem);
conjunto de métodos, responsável pela gestão da locomoção do agente. Tal como os
atributos, estes métodos também podem ser omissos, destinados a um NPC
específico ou a um tipo de NPC.
É da competência desta camada fazer deslocar corretamente o NPC pelo ambiente
de jogo ao longo do caminho pré-definido, e tendo por base um conjunto de atributos.
Para a realização desta tarefa, cada NPC envia pedidos de resolução de caminho ao
gestor de procura de caminhos. Cada pedido é composto por duas posições: posição
inicial (localização do NPC no ambiente de jogo) e posição final (uma localização do
caminho pré-definido). Cada pedido será respondido, sendo cada resposta composta por
um indicador do resultado da procura e por uma lista de localizações (caminho entre a
posição inicial e posição final).
A complexidade desta camada difere de jogo para jogo, a implementação realizada
destina-se a um comportamento básico, nomeadamente a um comportamento de
patrulha. Este comportamento é destinado ao cumprimento dos objetivos e requisitos do
estudo, podendo esta implementação ser facilmente estendida para atingir outros fins.
Os atributos base desta camada são:
atributos físicos do NPC, inerentes à locomoção:
Atributo Descrição
canMove Indicador que assina-la se se o NPC pode movimentar-se ou não.
maxSpeed Velocidade máxima em unidades por segundo.
rotationSpeed Velocidade de rotação em unidades por segundo.
minMove Movimento mínimo que o agente pode realizar.
Tabela 8 - Lista de atributos físicos de um NPC usados pela camada de locomoção.
63
atributos de procura de caminho:
Atributo Descrição
refreshPathSearchRate Determina com que frequência é realizada uma procura de caminho.
canSearch Indicador que assinala se a procura de caminhos pode ser realizada.
Tabela 9 - Lista de atributos de procura de caminho de um NPC usados pela camada de locomoção.
atributos de comportamentais do NPC:
Atributo Descrição
reachedNavPointDistance Distância do nó ao agente em que se considera que o agente
alcançou o nó.
slowDownDistanceToNavPoint Distancia do nó ao agente em que este irá abrandar ao
aproximar-se.
Tabela 10 - Lista de atributos comportamentais de um NPC usados pela camada de locomoção.
A especificação dos algoritmos por detrás do movimento do NPC, não será
descrita, uma vez que saem do âmbito do trabalho. Contudo iremos descrever os
métodos responsáveis gestão de pedidos e respostas de resolução de caminho. A
implementação desta componente usa duas rotinas como base (pedido de resolução de
caminho e decisão do próximo movimento) e um ouvinte de eventos de retorno de
resposta a pedidos de resolução de caminho. Devido à complexidade começamos por
definir as variáveis auxiliares usadas pelo sistema:
Variável Descrição
system.time Tempo atual de sistema.
lastTimeRefreshPath O último tempo em que foi realizada uma procura de caminho.
isSearching Indicador que assinala se o sistema está à procura de caminho.
waitingForRepath Indicador que assinala se o sistema está à espera de caminho.
initialPoint Ponto 3D com a posição inicial.
destinyPoint Ponto 3D com a posição final.
64
navPointList Lista que contem localizações chave do ambiente de jogo (pontos de
passagem).
navPointIndex Índex do ponto de passagem atual (navPointList).
pathFinderResponse Estrutura de resposta do gestor de procura de caminhos.
SearchResult Indicador que assinala o resultado da procura realizada pelo algoritmo de
procura (valores possíveis: PATH_FOUND, PATH_NOT_FOUND e
PATH_INCOMPLITED).
Path Lista de localizações (path) que descreve o caminho entre dois pontos.
pathIndex Índex da localização de destino atual do NPC.
nodePathEndReached Indicador que assinala se o NPC ao final do caminho.
Tabela 11 - Lista de variáveis auxiliares usadas na camada locomoção.
O pseudo-código seguinte descreve a rotina de pedido de resolução de caminho do
NPC. Depois da inicialização do agente, esta rotina irá estar constantemente em
execução:
# Descrição
1. O sistema inicia as variáveis auxiliares:
Destino Origem
navPointIndex 0
lastTimeRefreshPath -9999
isSearching False
waitingForRepath False
2. O sistema inicia um ciclo infinito.
2.1. O sistema tenta enviar um pedido de procura de caminho:
2.1.1 Se o tempo desde a ultima vez que foi realizada uma procura de caminho for maior ou
igual à frequência de procura de caminho e se o sistema não se encontra à procura de
caminho (system.time – lastTimeRefreshPath >= refreshPathSearchRate e isSearching
= false):
O sistema procura caminho:
2.1.1.1 O sistema valoriza as seguintes variáveis:
65
O sistema envia um pedido de procura de caminho ao gestor com o ponto inicial e
o ponto de destino (para mais informação sobre o pedido de procura de caminho
ver capítulo 0.0.1073790981 )
Destino Origem
lastTimeRefreshPath system.time
isSearching false
initialPoint Posição onde NPC se encontra atualmente no
mapa.
destinyPoint navPointList[navPointIndex]
2.1.2 Caso contrário, o sistema espera até poder enviar um pedido de resolução de caminho:
2.1.2.1 Se o sistema está à espera de resolução de caminho (waitingForRepath = true):
O sistema interrompe o ciclo uma vez que já existe uma rotina em execução;
Caso contrário:
O sistema valoriza a variável waitingForRepath = true e espera x
milissegundos até ser tempo de enviar um pedido de procurar caminho, onde:
O sistema valoriza a variável waitingForRepath a false e volta a tentar enviar
um pedido de procura de caminho (2.1)
2.2 O sistema espera durante o tempo definido pelo atributo refreshPathSearchRate.
Tabela 12 - Pseudo-código da rotina de pedido de resolução de caminho da camada locomoção.
O pseudo-código descrito em baixo está encapsulado num ouvinte de eventos, e é
executado quando uma instância de algoritmo de procura em grafos retorna uma
resposta. Este método tem por objetivo atualizar o caminho que o NPC vai realizar:
# Descrição
1. Se a resposta do gestor de procura de caminho não estiver vazia (pathFinderResponse =
null):
O sistema valoriza a variável isSearching = false e sai da função;
2. Caso contrário:
66
2.1 Se foi encontrado um caminho (pathFinderResponse.Path != null e
pathFinderResponse.SearchResult = PATH_FOUND):
2.1.1 O sistema valoriza a variável pathIndex com o valor 0
2.2 Caso contrário:
O sistema valoriza a variável isSearching a false e sai da função;
Tabela 13 - Pseudo-código do ouvinte de eventos de resposta de caminhos da camada locomoção.
O último trecho de pseudo-código descreve resumidamente a rotina que decide o
destino do próximo movimento do NPC
# Descrição
1. Se o caminho da resposta do gestor de procura de caminho não estiver vazia
(pathFinderResponse.Path = null):
O sistema retorna a indicação para o agente não se mover;
2 Se o NPC já percorreu o caminho retornado pelo gestor de procura de caminho (pathIndex
>= pathFinderResponse.path):
2.1 Se o NPC já percorreu todos os pontos de passagem (navPointIndex >=
navPointList.Length) o sistema indica que o próximo ponto de passagem é o primeiro
elemento da lista dos pontos de passagem (movimento de patrulha):
navPointIndex = 0;
Caso contrário, o sistema indica que o próximo ponto de passagem é o elemento
seguinte da lista dos pontos de passagem:
navPointIndex += 1;
O sistema valoriza a false as variáveis isSearching e nodePathEndReached.
O sistema retorna a indicação para o agente não se mover;
3 Se a distância do NPC ao ponto de passagem for menor ou igual à distância mínima que
um agente tem de estar do nó para este ser considerado como alcançado
(reachedNavPointDistance):
3.1 Se o agente ainda não chegou ao final do caminho (nodePathEndReached = false):
nodePathEndReached = true
3.2 Se o NPC já percorreu o caminho retornado pelo gestor de procura de caminho
67
(pathIndex = pathFinderResponse. Length):
Se o NPC já percorreu todos os pontos de passagem (navPointIndex >=
navPointList) o sistema indica que o próximo ponto de passagem é o primeiro da
lista dos pontos de passagem:
navPointIndex = 0;
Caso contrário, o sistema indica que o próximo ponto de passagem é o ponto de
passagem seguinte:
navPointIndex += 1;
O sistema valoriza a false as variáveis isSearching e nodePathEndReached.
3.3 Caso contrário, o NPC chegou a uma localização do caminho retornado pelo gestor
de procura de caminho:
O sistema valoriza as variáveis:
pathIndex += 1;
nodePathEndReached = false;
O sistema retorna a indicação para o agente não se mover;
4 O sistema desloca-se para a localização pathFinderResponse.Path[pathIndex].
Tabela 14 - Pseudo-código da rotina de determinação do próximo movimento do NPC.
A frequente procura de caminho permite ao NPC lidar com ambientes de jogo
dinâmicos, com um espaço de erro definido pelo atributo refreshPathSearchRate. Este
atributo deve, assim ser, valorizado com um valor baixo quando o ambiente sofre
alterações frequentes ou no caso de o NPC’s deslocar-se a uma velocidade muito
elevada (maxSpeed).
Devido à falta de tempo, não foi possível implementar o sistema de validação de
caminhos que fazem parte dos requisitos secundários do estudo. Caso tivesse sido
implementada, esta funcionalidade iria ocorrer depois da resposta do gestor de procura
de caminhos.
Representação do ambiente
A implementação da camada de representação do ambiente dividiu-se em duas
componentes: gestor e esquema de divisão.
Gestor
68
O gestor tem como principal objetivo inicializar e gerir o esquema de divisão e
ainda disponibilizar o espaço de procura á camada de algoritmos de procura em grafo.
Apenas existe uma instância do gestor que implementa um gestor genérico. O gestor
genérico descreve um conjunto base de atributos e métodos que todas as
implementações do gestor devem suportar.
Cada implementação do gestor deve possuir a referência a um esquema de divisão
genérico, que tem por objetivo o suporte a diversos tipos de esquema de divisão,
embora atualmente o sistema suporte apenas dois tipos (baseado em grelha e baseado
em quadtree), é possível no futuro implementar outros esquemas de divisão baseados no
esquema de divisão genérico com o mínimo de alterações ao sistema. Esta referência
genérica, em tempo de execução, é atribuída a um dos tipos de esquema de divisão
suportados pelo sistema.
Este atributo tem por objetivo evitar que outras camadas manipulem diretamente o
esquema de divisão, ficando essa tarefa ao encargo do gestor. Devendo as demais
camadas, recorrer aos métodos disponibilizados pelo gestor. Atualmente o sistema
suporta os seguintes métodos:
Método Descrição
Init Inicialização do gestor de grafos de navegação e do grafo de navegação.
Insert Insere um objeto no grafo de navegação. Em cada inserção será feita a
atualização das conexões (vértices) dos nós vizinhos do nó ou nós onde o
objeto foi inserido.
InsertAtLoad Insere um objeto no grafo de navegação, sem atualização das conexões aos
nós vizinhos do nó ou nós onde o objeto foi inserido.
ConnectNeighbours Atualização das conexões dos nós vizinhos de todos os nós do grafo de
navegação.
GetNode Traduz uma localização num nó do grafo de navegação.
Tabela 15 - Métodos suportados pelo gestor da camada de representação do ambiente.
Esquema de divisão
O esquema de divisão divide, o espaço do ambiente de jogo, num grafo de
navegação. O grafo de navegação pode corresponder inteiramente ao espaço de procura
usado pela camada de algoritmos de procura em grafos ou ser necessário algum
processo que converta o grafo de navegação no espaço de procura, como acontece no
grafo de navegação baseado na quadtree que será abordado mais à frente.
69
De seguida, para melhor compreensão, são detalhadas as componentes genéricas
da camada de representação do ambiente.
O requisito do sistema de navegação, de suportar mais do que um esquema de
divisão implica, que todos os esquemas de divisão sejam uma instância de um esquema
de divisão genérico. Cada esquema de divisão deve:
gerar um espaço de procura linear, nomeadamente um array linear;
possuir um conjunto de parâmetros que, guarde a localização e o tamanho do
ambiente de jogo;
possuir um conjunto de métodos, que suporte os métodos disponibilizados
pelo gestor da camada de representação do ambiente (ver Tabela 15).
Cada esquema de divisão tem como argumento de inicialização a posição e
tamanho do ambiente de jogo, e o tamanho mínimo do nó.
O grafo de navegação e o array linear são compostos por nós, embora estes possam
ser específicos a cada tipo de esquema de divisão, estes implementam a partir de um nó
genérico. O nó genérico deve possuir:
Id;
conjunto de parâmetros que guarde a localização e o tamanho no nó;
custo de navegação no nó (obstáculos e tipo de terreno);
array linear, que contem os vizinhos do nó;
array linear, que contem os custos da conexão aos vizinhos (relação um
para um com a lista de vizinhos).
A camada de representação do ambiente suporta atualmente dois esquemas de
divisão: baseado em grelha e baseado em quadtree.
Baseado em grelha
Geração
A geração do grafo de navegação, através da divisão do ambiente de jogo pelo
esquema de divisão baseado em grelha, consiste na imposição de uma grelha sobre o
ambiente de jogo.
Com o intuito de simplificar a implementação, atualmente só estão suportados
ambientes de jogo com a figura geométrica quadrada, o mesmo se aplica ao tipo célula
que compõe a grelha.
70
Na inicialização da grelha é determinado a dimensão do espaço de procura (número
de células). Uma vez que um dos objetivos de estudo é a comparação entre os diversos
esquemas de divisão, é necessário que a aplicação de cada um dos esquemas de divisão
ao mesmo ambiente de jogo, origine o mesmo número nós que constitui o espaço de
procura. Desta forma, a dimensão do espaço de procura não pode ser simplesmente
determinada pela verificação do número de vezes que o ambiente de jogo contém a
dimensão mínima da célula indicada por parâmetro. Esta decisão de implementação é
justificada pela forma como a quadtree divide o espaço. A quadtree divide o ambiente
de jogo em 4 regiões recursivamente, é possível assim, que a dimensão dos nós gerados
na profundidade máxima da quadtree, não correspondam ao tamanho mínimo da célula
indicado resultando num espaço de procura mais pequeno.
Por exemplo, um ambiente de jogo com o tamanho de lado igual a 20 unidades e
tamanho mínimo de lado da célula 2 unidades, o esquema de divisão baseado em grelha
gera um espaço de procura de 100 nós, enquanto o esquema de divisão baseado em
quadtree gera um espaço de procura máximo de 16 nós. Isto acontece uma vez que a
quadtree, segundo o exemplo, apresenta uma profundidade máxima de 2 com cada
célula a apresentar um tamanho mínimo de 2,5 unidades.
Para o esquema de divisão baseado em grelha, gerar um espaço de procura igual
ao esquema de divisão baseado em quadtree, é necessário que o tamanho das células da
grelha seja igual ao tamanho das células da quadtree na sua profundidade máxima. Para
isso, foi implementado um algoritmo semelhante à quadtree. Neste algoritmo o tamanho
mínimo indicado é usado como referência para determinar o tamanho mínimo da célula
suportado pela quadtree. Desta forma, vamos determinar a profundidade máxima como
se estivéssemos a tratar de uma quadtree, através da fórmula:
Equação 3 - Profundidade máxima em quadtree.
mínimo
ambienteLogmaxerofundidad
T
Tp
2_
Equação 2 – Tamanho do espaço de procura em grelhas.
Tespaço _ procura =Tambiente
Tmínimo
æ
èç
ö
ø÷
2
71
Através da profundidade máxima é possível calcular o tamanho mínimo da
célula com a fórmula:
Posteriormente ao cálculo do tamanho mínimo da célula é possível determinar o
espaço de procura através da fórmula indicada na Equação 4 substituindo o tamanho
mínimo da célula indicada pelo tamanho mínimo da célula determinada pelo algoritmo
usado na quadtree.
Limiar
Ao ser adicionado um objeto à grelha, qualquer célula que intersecte o objeto é
considerada como ocupada, não sendo possível ao agente caminhar sobre esta.
Espaço de procura
O grafo de navegação gerado pelo esquema de divisão baseado em grelha
corresponde diretamente ao espaço de procura. A grelha imposta ao ambiente de jogo é
armazenada através da abstração de um array linear. Em comparação com a abstração
de um array multidimensional, esta abordagem permite baixar o consumo de memória e
ainda acelerar o processo de procura.
Indexação
O esquema de divisão baseado em grelha ao ser imposto no ambiente de jogo vai
dividir o ambiente em nós, a cada nó é atribuído um id de forma incremental por linha, a
Ilustração 26 exemplifica a atribuição de Id’s:
6 7 8
3 4 5
0 1 2
Ilustração 26- Exemplo de abstração multidimensional da grelha e atribuição de Id's para cada
célula.
Equação 4 – Tamanho mínimo da célula em quadtree.
2_ maxerofundidad
ambientemínimo
p
TT
72
A abstração em grelha usada na Ilustração 26, na realidade não existe, uma vez
que a nossa implementação, armazena e manipula o grafo de navegação de forma linear.
A abstração em grelha visível na Ilustração 26 na realidade Ilustração 27.
0 1 2 3 4 5 6 7 8
Ilustração 27 - Exemplo de abstração linear da grelha e atribuição de Id's para cada célula.
É possível manipular através do Id a abstração linear da grelha como se
estivéssemos a lidar com a abstração multidimensional da grelha, recorrendo para isso a
um conjunto de funções que serão descritas abaixo:
Equação 5 – Id em grelha.
olunaolunasninhad CCLI
Equação 7 - Obtenção da coluna através da coordenada x.
ltura
olunasnXoordenadaoluna
A
CCC
_
nColunas
IdinhaL
Equação 8 - Obtenção da linha através do Id.
olunasndoluna CIC %Equação 6 - Obtenção da coluna através do Id.
73
Vizinhos
A determinação de vizinhos é um processo simples, para cada nó o sistema
percorre os nós existentes na linha e coluna anterior e posterior onde o nó se encontra e
é guardada a referência de cada vizinho num array linear. A Ilustração 28 mostra para
o nó identificado pela linha i e coluna j (i, j), as coordenadas por linha e coluna de cada
um dos seus vizinhos. A Ilustração 29 mostra a distribuição num array linear dos
vizinhos mostrados na Ilustração 28.
Ao mesmo tempo que este processo decorre, para cada vizinho encontrado é
determinado o custo da ligação (custo de navegação) com base na posição do vizinho
face ao nó. O custo de navegação no sentido diagonal superior ao custo de deslocação
no sentido vertical ou horizontal.
O número de elementos em cada array pode diferir de nó para nó, caso o nó se
localize numa das fronteiras do ambiente de jogo. Desta forma um nó pode ter no
máximo 8 vizinhos e no mínimo 3 vizinhos. Esta abordagem permite diminuir o
consumo de memória e evitar iterações desnecessárias durante a procura de caminho
entre dois pontos.
Coluna
j - 1 j j + 1
Linha
i + 1 0 7 6
i 1 (i , j) 5
i - 1 2 3 4
Ilustração 28 - Determinação de vizinhos do nó (i, j).
(i+1, j-1) (i, j-1) (i-1, j-1) (i-1, j) (i-1, j-1) (i, j+1) (i+1, j+1) (i+1, j)
0 1 2 3 4 5 6 7
Ilustração 29 - Disposição dos vizinhos do nó (i, j) num array linear.
ura
inhasnZoordenadainha
L
LCL
arg
_
Equação 9 - Obtenção da linha através da coordenada z.
74
Quantização/Localização
Para determinar o nó que contém uma determinada localização, é necessário
determinar o Id do nó, para isso o sistema recorre às funções descritas em baixo.
Primeiro vamos determinar a coluna e a linha que essa localização corresponde e com
essa informação é determinado o Id do nó.
Foi estabelecido que cada nó é representado pelo seu ponto médio, a determinação
da localização de um determinado nó, pode ser determinada através da consulta do
atributo do nó center, ou através das seguintes funções:
Baseado em quadtree
Geração
O grafo de navegação gerado pelo esquema de divisão baseado na quadtree
consiste na subdivisão recursiva do espaço em quatro regiões ou quadrantes. A
implementação da quadtree é semelhante a tantas outras implementações, para além de
implementar o esquema de divisão genérico, é constituída por:
uma referência ao nó raiz;
um limiar;
uma profundidade máxima.
Cada nó para além de implementar o nó genérico, é composto por:
uma referência (apontador) para o nó pai, no caso do nó raiz, esta referência
assume o valor null;
2
minmin)(_
TTCC xolunaxoordenada
Equação 10 – Obtenção da coordenada x.
2
minmin)(_
TTLC xinhazoordenada
Equação 11 - Obtenção da coordenada z.
75
quatro referências, uma para cada um dos nós filhos (quadrantes: Sudoeste
(SO - SW), Sudeste (SE) e Nordeste (NE) e Noroeste (NO ou NW), no caso
de não haver nós filhos esta referência assume o valor null (ver Ilustração 9).
O contexto de aplicação da quadtree e o requisito do sistema de suportar
diversos tipos de algoritmos de procura, implicou a proceder a algumas alterações que
são abordados nos seguintes subcapítulos:
Profundidade máxima
Na maior partes das implementações da quadtree, antes da geração desta é passado
por parâmetro a profundidade máxima da quadtree, isto é, o número máximo de vezes
que a quadtree pode dividir o espaço ambiente de jogo. O requisito de automatismo do
nosso sistema faz com que a profundidade máxima seja determinada durante a geração
da quadtree, através da função descrita na Equação 3 usando como referencia o tamanho
mínimo que uma célula pode apresentar.
Limiar e subdivisão
Cada quadtree possui um limiar, que determina quando um determinado nó
(quadrante) deve ser subdividido. Por norma, este limiar é determinado por um número
máximo de objetos que um nó pode conter. Na maioria das vezes quando esse limiar é
alcançado, o quadrante só é subdividido se houver um nó filho que contenha totalmente
o objeto adicionado, caso contrário a quadtree não procede a mais subdivisões. Este tipo
de implementação não é indicado para ser aplicada aos jogos de vídeo. Uma vez que é
necessário uma representação ambiente o mais fiel possível. Na implementação
efetuada quando um nó contém ou intersecta um objeto adicionado à quadtree, este nó é
subdivido até ser alcançada a profundidade máxima, sendo os nós intersetados pelo
objeto, assinalados como ocupados. É possível assim, identificar corretamente a zona
ocupada e o espaço livre em que o agente se pode deslocar.
Espaço de procura e indexação
A geração de um espaço de procura linear, imposta pelos requisitos do sistema,
pode ser visto como um problema de representação, nomeadamente a representação
linear da quadtree. Uma quadtree linear tem como principal característica, o
armazenamento apenas dos nós folha. Isto permite diminuir consideravelmente o
espaço, de procura uma vez que os nós não-folha representam o mesmo espaço que os
seus nós-filho, podendo assim ser ignorados.
Durante a geração da quadtree é inicializado um array linear, com o objetivo de
armazenar a referência para os nós folha e de representar o espaço de procura. O
tamanho deste array é igual ao número total possível de nós-folha (quando todos os
76
nós-folha da quadtree se encontram profundidade máxima), pode ser determinado pela
seguinte função:
.
Geralmente, a quadtree não necessita de ser indexada, uma vez que esta pode ser
manipulada e iterada através das referências ao nó pai e aos nós filhos existentes em
cada nó. Contudo, a definição da profundidade máxima no início da geração da
quadtree, o requisito de representar o espaço de procura de forma linear e o requisito de
processamento rápido, abriram o caminho para a implementação da indexação dos nós
da quadtree. Desta forma, cada nó da quadtree possui um Id que o identifica.
Apesar da implementação da indexação dos nós da quadtree poder ser feita de
diversas formas, optou-se por uma solução que permitisse:
mapear dados multidimensionais em dados unidimensionais;
pesquisa de nós em tempo constante e não dependente do número de elementos
existentes na quadtree;
referenciar elementos através da linha e coluna em que se encontram (representação
em grelha);
referenciar diretamente de um nó através do seu id;
determinar vizinhos de forma semelhante à determinação de vizinhos no esquema de
divisão baseado em grelha.
Esta solução recorre àquilo que a Ciência da Computação e Análise Matemática
chama de ordem-Z, ordem Morton, número de Morton ou sequência de Morton que
mapear dados multidimensionais em dados unidimensionais preservando a localização
de cada elemento. O número de Morton de um elemento (Id) numa estrutura
multidimensional pode ser simplesmente calculado através da intercalação da
representação binária das suas coordenadas (z - linha e x - coluna). O processo inverso
também é possível uma vez que os bits ímpares da representação binária do Id
correspondem à coordenada x e os bits pares correspondem à coordenada z (ver
Ilustração 30).
max_Pr_ 4
ofundidadeprocuraoespacoT
Equação 12 - Determinação do espaço de procura numa Quadtree.
77
Embora o número de Morton responda ao problema de indexação, existe ainda o
problema associado à atribuição do Id a cada um dos nós da quadtree no momento da
sua geração. Este problema acontece uma vez que a quadtree é inicializada apenas com
o nó raiz, e somente no pior caso se assemelha a uma grelha. Não sendo desta forma
possível, obter de forma direta o número da linha e coluna de um determinado nó.
A atribuição de um Id (Id(n)) durante a geração de um nó (n) recorre a um conjunto
de informações do nó-pai (n-1) e ao código de orientação ( código de orientação( n )). O
código de orientação representa o quadrante que o nó ocupa em relação ao nó-pai. Esta
relação pode ser verificada através da Tabela 16:
Quadrantes Código de orientação Código binário
SO 0 00
SE 1 01
NE 2 10
NO 3 11
Tabela 16 - Quadrantes e código de orientação.
Ao nó raiz é atribuído o Id 0 e o quadrante SO, sendo os Id’s dos restantes nós
determinados através da seguinte função:
Ilustração 30 – Conversão do número Morton (Id) na coordenada x e z
78
Sempre que um nó é gerado este, é adicionado ao espaço de procura na posição
correspondente ao seu Id. Através da função da Equação 12 e da Tabela 16 podemos
verificar que o id do filho correspondente ao quadrante SO é sempre igual ao Id do pai.
Desta forma, a referência do nó-pai no espaço de procura é substituída pela referência
do Id do nó filho, obtendo-se desta forma a representação de uma quadtree linear.
Vizinhos
A determinação dos nós vizinhos para cada nó na quadtree é um processo
semelhante ao processo de determinação de vizinhos, descrito para o esquema de
divisão baseado em grelha, contudo existe algumas diferenças.
O sistema parte do princípio que todos os nós-folhas se encontram na profundidade
máxima. Desta forma, é necessário determinar o número de linhas e o número de
colunas que o nó ocupa. Com base nessa informação, o sistema vai percorrer a linha e
coluna anterior e posterior com o objetivo de determinar os nós vizinhos. Para cada nó
correspondente a uma determinada linha e coluna, o sistema verifica se o nó existe, uma
vez que o nó pode não estar dividido até à sua profundidade máxima. No caso de este
não existir, então o sistema vai determinar o nó-pai desse nó vizinho, e assim
sucessivamente, até encontrar o nó que ocupa essa posição. O nó determinado é então
adicionado ao array de vizinhos e adicionada uma entrada ao array que contêm o custo
da conexão a cada um dos vizinhos. Tal como acontece na implementação da grelha, o
número de vizinhos pode diferir de nós para nós e o custo de navegação variar de
acordo com a orientação do vizinho ao nó, sendo o custo de navegação na diagonal
superior ao custo de deslocação vertical ou horizontal.
Quantização/Localização
A determinação de um nó que contém uma determinada localização é feita pela
determinação do número de Morton através das coordenadas indicadas. Depois do
número Morton ser determinado, é verificado se o nó existe, caso não exista o sistema
vai determinar o nó-pai desse nó e assim sucessivamente até encontrar o nó que contêm
essa localização.
)(_)(Prmax_Pr
)1()( 4 norienodigonodundidadeofundidade
ndnd CII
Equação 13 - Determinação de Id de um nó da quadtree.
79
Tal como a implementação da grelha, a representação do nó numa posição do
ambiente de jogo é igual ao ponto médio desse nó. A determinação da localização de
um determinado nó, pode ser feita através do atributo do nó center.
Algoritmos de procura em grafos
Á semelhança da camada de representação do ambiente, a implementação da
camada de algoritmos de procura em grafo divide-se em duas componentes: gestor e
algoritmos de procura em grafo.
Gestor
O gestor tem como objetivo principal inicializar e gerir uma ou mais instâncias do
algoritmo de procura em grafos. O gestor recebe pedidos de resolução de caminho da
camada de locomoção e reencaminha-os.
O gestor possui os seguintes atributos:
Propriedade Descrição
pathFinderThreadPool Referência a um Thread pool que contem threads que executam
instâncias do algoritmo de procura em grafos.
nPathFinders Número de instâncias de algoritmos de procura existentes na thread
pool.
nRequests Número atual de pedidos a ser tratados.
Tabela 17 - Lista de atributos do gestor da camada de algoritmos de procura em grafos.
O atributo pathFinderThreadPool referencia uma thread pool. A thread pool
apresenta como principais características ser configurável e extensível a outras
implementações.
É possível configurar o número mínimo e máximo de thread’s suportados pela
thread pool. A thread pool quando é inicializada, inicializa o número mínimo de
thread’s definido, este número pode aumentar até ao número máximo definido, a thread
pool determina a necessidade de aumentar o número de threads, caso existam pedidos
em espera.
É possível ainda configurar o modo como o número de threads é aplicado entre:
global e por processador. No modo global, o número de threads é atribuído ao sistema
como um todo enquanto no modo por processador cada processador do sistema possui
um número mínimo e máximo de threads.
80
A thread pool possui uma lista genérica de elementos genéricos, sendo a lista
extensível a diversas tipos de estrutura de dados e a diversos tipos de elemento. Na
implementação atual do sistema de navegação esta lista corresponde a uma fila de
tarefas com prioridades, em que cada tarefa corresponde a um pedido de resolução de
caminho e está associado a uma prioridade. Esta estrutura de dados irá ordenar os seus
elementos pela ordem de chegada e pelo valor da prioridade. Embora atualmente o
sistema não suporte inteiramente NPC’s de diferentes tipos, esta funcionalidade foi
desenvolvida para suportar essa funcionalidade.
Os métodos suportados atualmente pelo gestor de algoritmos de procura em grafos
são:
Método Descrição
Init Inicialização do gestor de algoritmos de procura em grafos.
FindPath Recebe um pedido de resolução de caminho e adiciona-o à lista de
tarefas a ser consumida pelas threads da thread pool.
Tabela 18 - Lista de métodos do gestor da camada de algoritmos de procura em grafos.
O método Init tem por objetivo inicializar o gestor de algoritmos de procura de
grafos. Esta inicialização inclui a inicialização da thread pool.
O método FindPath é o método chamado quando a camada de locomoção pretende
determinar um caminho entre dois pontos. Este método apresenta um comportamento
assíncrono, uma vez que a camada de locomoção de um NPC ao chamar este método
não fica bloqueado à espera de uma resposta. O gestor reencaminha o pedido para a fila
de tarefas da thread pool onde irá aguardar até ser processado por uma instância do
algoritmo de procura em grafo.
O comportamento assíncrono entre o pedido e a resposta de resolução de caminho e
a existência de várias instâncias do algoritmo de procura em grafo visam o suporte a
múltiplos agentes.
Tipos de algoritmos de procura em grafos
Cada thread da threadpool executa uma instância do algoritmo de procura em
grafos. De forma a permitir o suporte a diversos tipos de algoritmos de procura, cada
implementação deve obrigatoriamente estender o algoritmo de procura em grafos
genérico.
O algoritmo de procura em grafos genérico apresenta como principais atributos:
81
Propriedade Descrição
navigationGraphManager Referência ao gestor da camada de representação do ambiente.
nIterations Número de iterações realizadas pelo pathfinder no processamento de
um pedido de resolução de caminho.
goal Nó de destino.
response Estrutura de resposta a ser enviada à camada de locomoção do NPC
responsável pelo pedido de resolução de caminho (ver Tabela 22).
Tabela 19 - Lista de atributos do algoritmo de procura em grafos genérico.
A referência ao gestor da camada de representação do ambiente tem por objetivo
disponibilizar o espaço de procura utilizado pelo algoritmo de procura e por outro lado
responder a pedidos de localização/quantização de pontos/nós.
O algoritmo de procura em grafos genérico disponibiliza ainda um conjunto de
métodos que as diversas implementações devem implementar ou usar:
Método Descrição
Init Inicializa a instância do algoritmo de procura em grafo.
FindPath Preparação a instância do algoritmo de procura em grafo para uma nova procura
de caminho entre dois pontos.
DoIteration Proceder uma iteração do algoritmo de procura em grafos.
GetResponse Retorna a resposta à camada de locomoção do NPC responsável pelo pedido de
resolução de caminho.
Tabela 20 - Lista de métodos do algoritmo de procura em grafos genérico.
O método DoIteration procede a uma iteração do algoritmo de procura, desta
forma, cada implementação do algoritmo de procura deve estar preparado para ser
executado por iteração, invés de calcular o caminho de uma vez só. Este método é
chamado repetidamente pela thread até o resultado da iteração ser diferente de não
acabado (NOTFINISHED). Esta implementação tem por objetivo suportar o
processamento intercalado de pedidos de resolução de caminho, procurando suportar a
aplicação de técnicas como o timeslice. Contudo, esta funcionalidade ainda não se
encontra inteiramente suportada pelo sistema.
82
O método FindPath recebe um pedido de procura de caminho e prepara o
algoritmo para uma nova procura de caminho. O pedido consiste numa estrutura
composta por:
Propriedade Descrição
id Identificador do pedido.
priority Prioridade do pedido.
start Ponto 3D que representa a localização do ponto inicial do caminho.
goal Ponto 3D que representa a localização do ponto final do caminho.
onPathFinderResponse Referencia ao delegate que contem a referência para um método da
camada locomoção do NPC responsável pelo pedido de procura de
caminho.
Tabela 21 - Lista de atributos da estrutura de pedido de resolução de caminho.
Quando o algoritmo de procura termina o processamento de um pedido, o sistema
utiliza o atributo onPathFinderResponse para fazer o callback ao NPC responsável pelo
pedido. O callback é feito através da chamada ao método descrito na Tabela 13
passando como atributo a estrutura de resposta ao pedido.
A estrutura de resposta composta pelos seguintes atributos:
Propriedade Descrição
id Identificador da resposta.
path Array de pontos 3D que representa a solução de caminho entre os dois pontos
indicados pela estrutura de pedido de resolução de caminho.
searchResult Resultado da procura de caminho
Tabela 22 - Lista de atributos da estrutura de resposta de resolução de caminho.
O resultado da procura de caminho pode variar entre 2 valores: encontrado
(FOUND) e não encontrado (NOTFOUND).
Quer a estrutura de pedido, quer a estrutura de resposta podem ser estendidos com
objetivo de aumentar o número de funcionalidades ou possibilitar diferentes tipos de
implementações.
83
Atualmente o sistema de navegação suporta dois tipos de algoritmos de procura em
grafo: A* e o Fringe Search. Para cada um destes algoritmos descrevemos as suas
principais características e o pseudo-codigo relativos aos dois métodos principais da sua
implementação: FindPath e DoIteration.
A*
A implementação do algoritmo de procura em grafo A* recorre a três estruturas de
dados distintas:
o conjunto de nós abertos (open) é armazenado numa fila de prioridades. Esta
estrutura é responsável por dispor os seus elementos segundo a sua prioridade. Desta
forma, o caminho com o menor custo possui a maior prioridade, e é o primeiro da
fila a ser selecionado;
para armazenar o conjunto de nós fechados (closed) foi usado uma HashSet. Esta
estrutura de dados consiste numa coleção de elementos únicos não ordenados, que
recorre a uma implementação hash para a identificação dos seus elementos. Esta
estrutura foi selecionada uma vez que disponibiliza um conjunto de operações de
complexidade O(1). Dentro das operações disponibilizadas, interessa-nos a operação
de pertença, a Hashset permitir determinar de forma fácil e rápida se um
determinado elemento faz parte do conjunto;
a terceira e última estrutura, destina-se a armazenar caminhos (path) entre dois nós.
A implementação desta estrutura tem como características ser imutável, uma vez
que depois de ser adicionado um elemento a esta estrutura, este não pode ser
modificado. Esta característica confere ainda à estrutura a característica de ser
threadsafe. Esta estrutura tem como tributos uma lista de nós anteriores
(previousSteps), o custo total do caminho, e o ultimo nó adicionado (lasStep). A fila
de nós abertos irá guardar diversas instâncias desta estrutura.
Método FindPath:
# Descrição
1. O sistema valoriza as variáveis:
Destino Origem
closed {}
open open.enqueue(0, new path
84
(navGraphManager.GetNode(request.Start)))
path {}
Tabela 23 - Pseudo-código do método FindPath para o algoritmo de procura em grafos A*
Método DoIteration:
# Descrição
1. O sistema obtém o caminho com o custo mais baixo:
path = open.Dequeue();
2. Se o conjunto de nós fechados contém o nó do último passo (if closed contains
path.lastStep):
O método devolve NOTFINISHED.
3. Se o nó no último passo, for igual ao nó de destino (if path.lastStep == destination):
O método devolve FINISHED.
4 O sistema adiciona o último passo ao conjunto de nós fechados:
closed.add(path.lastStep)
5. O sistema percorre todos os nós vizinhos do último passo (foreach n in
path.lastStep.neighbours):
5.1 Se n for possível de caminhar:
newpath = path.AddStep(n, g(n))
q.enqueue(newpath.TotalCost(g(n)) + h(n), newpath)
6 Se não existir mais nó na lista aberta (open.Count = 0):
O método devolve NOTFOUND.
Tabela 24 - Pseudo-código do método DoIteration para o algoritmo de procura em grafos A*
O custo do movimento de n (g(n)) é determinado pela soma do custo do caminho
do nó path.lastStep, o custo de caminhar em n e o custo do caminho entre o nó
path.lastStep e o nó n.
O custo estimado do nó n ao nó destino (h(n)), é calculado através do método
Manhattan. Este método destaca-se pela sua rapidez, contudo, não garante o caminho
mais curto possível, apresentando apenas uma grande probabilidade disso.
85
Fringe Search
A implementação do algoritmo de procura em grafo Fringe Search recorre a duas
estruturas de dados distintas:
a estrutura “Fringe” que funciona como uma lista duplamente ligada, onde é guarda
a informação do nó atual (currentNode) e o nó à cabeça (headNode);
“Cache” array de elementos, em que cada elemento é composto pelo valor g e o nó
pai.
Método FindPath:
# Descrição
1. O sistema inicializa as variáveis auxiliares:
Variável Inicialização
Cache C[] new Cache[navGraphManager.searchSpace.Length]
Fringe ringe Limpa a lista “agora” e “depois”:
new Fringe[navGraphManager.searchSpace.Length]
2. O sistema valoriza as variáveis auxiliares:
Destino Origem
C C.AddCache(navGraphManager.GetNode(request.Start).Id, 0, NULL)
Fringe Adiciona o nó raiz à lista now:
Fringe.insertNode(navGraphManager.GetNode(request.Start))
fLimit Valoriza o limiar com o valor do h do nó inicial
h(request.Start)
fMin MaxPossibleValue
Tabela 25 - Pseudo-código do método FindPath para o algoritmo de procura em grafos Fringe
Search*
Equação 14 – Obtenção de h(n).
etXurrentYetXurrentXn TCabsTCabsh argarg)( ((10
86
Método DoIteration:
# Descrição
1. O sistema valoriza as variáveis:
Destino Origem
Node Fringe.CurrentNode
2. Se node == null:
Se Fringe.Head == Null
O método devolve NOTFOUND.
Caso contrário:
fLimit = fMin;
O método devolve NOTFINISHED.
Caso contrário verifica se o nó goal foi encontrado (node == goal):
O método devolve FOUND.
3. O sistema obtém o elemento da cache:
Destino Origem
cacheElement GetFromCache(node)
4. O sistema determina o valor de f:
fValue = g(cacheElement) + h(nodeId, goal);
5. Se fValue > fLimit:
Se fValue < fMin
fMin = fValue;
O sistema obtém o próximo elemento da lista Fringe (Fringe.Next())
fLimit = fMin;
O método devolve NOTFINISHED.
6. O sistema percorre todos os nós vizinhos do nodeId (foreach n in node.neighbours):
6.1 Se n for possível de caminhar:
87
6.2 O sistema determina o g do vizinho:
g(n) = g(cacheElement) + n.Cost + node.NeighboursConectionCost(n);
6.3 O sistema verifica se n há existe em cache (GetFromCache(n) != null):
Se g(n) >= g(GetFromCache(n)
fLimit = fMin;
O método devolve NOTFINISHED.
6.4 O sistema adiciona o nó n ao Fringe
Fringe.insertNode(n)
6.5 O sistema adiciona o nó n à cache:
C.AddCache(n, g(n), node)
7 O sistema atualiza a estrutura Fringe:
Remove o elemento corrente (fringe.RemoveCurrentNode())
Atualiza o próximo nó (fringe.NextNode())
8 fLimit = fMin;
Tabela 26 - Pseudo-código do método DoIteration para o algoritmo de procura em grafos Fringe
Search*
4.3.2 Ferramenta de prova de conceito
A aplicação de prova de conceito surgiu da necessidade de se ter um modelo
prático, que pudesse provar o conceito e a arquitetura estabelecida. Desta forma, foi
implementado um projeto em Unity 3D, que através de técnicas de geração processual
de conteúdo geram um ambiente de jogo de vídeo, em que os diversos agentes recorrem
ao sistema de navegação desenvolvido. O desenvolvimento deste protótipo funcional
permitiu, como ferramenta, provar a viabilidade da solução, dos conceitos e as
tecnologias envolvidas na elaboração do projeto.
A ferramenta desenvolvida suporta a construção automática e a dinâmica de
cenários inteiros, em troca da definição de alguns parâmetros. Com vista a este fim e
para simplificar a sua implementação, toda a arquitetura da ferramenta assenta na
técnica de programação de inversão de controlo. Foi usada uma biblioteca third-party
desenvolvida por Sebastiano Mandalà especificamente para o Unity 3D, uma vez que as
demais ferramentas para este fim são incompatíveis. Esta técnica possibilita um baixo
nível de acoplamento entre os diferentes módulos do sistema. As dependências entre os
módulos não são definidas programaticamente, mas sim através da configuração de um
container, o qual é responsável por “injetar” em cada componente as suas dependências.
88
Desta forma, os objetos não são criados pelo utilizador, mas sim pelo container de
forma lazy (quando necessário). Este aspeto é bastante importante pois permite adiar a
criação de objetos até estes serem realmente necessários, minimizando o consumo de
memória. Para a criação de objetos o container recorre a fábricas (factories) que são
responsáveis pela criação de um tipo de objeto específico.
Esta abordagem possibilita que apenas seja necessário adicionar um objeto a cada
cenário do Unity 3D, o container. Todos os outros objetos são criados através do
container.
O tipo de objetos suportados atualmente, são:
camada de representação do ambiente;
camada de algoritmos de procura em grafos;
conjunto entidades (entities).
A camada de representação do ambiente no inspetor corresponde ao GameObject
do gerente que irá conter como dependência uma instância do grafo de navegação.
À semelhança da camada de representação do ambiente, a camada de algoritmos de
procura em grafos no inspetor é representada pelo gerente e irá conter como
dependência uma instância por cada thread a executar o algoritmo de procura em
grafos.
Todas as entidades são extensões de uma entidade genérica. Cada tipo de entidade
é composta por características únicas e/ou características herdadas de outras entidades e
dispõe de um gestor que recorre a fábricas para gerar as suas instâncias. Recorrendo ao
paradigma da programação orientada a objetos é possível criar diversos tipos de
entidades inteiramente novas ou adicionar comportamentos de entidades já existentes.
No inspetor cada tipo de entidade é representada pelo gestor que contêm as suas
instâncias. A ferramenta atual suporta as seguintes tipos de entidades:
camera: dispositivo que permite ao jogador ver o ambiente de jogo;
terrain: Terreno que suportar os diversos objetos do ambiente de jogo. Em cada
cenário só existe um e este é gerado inteiramente através de técnicas de geração
processual;
navPoint: esfera que assina-la uma localização chave no ambiente de jogo;
mob: NPC com a capacidade de se movimentar pelo ambiente de jogo. O Mob é
composto pela camada de locomoção e um conjunto de NavPoint’s;
obstacle: volume quadrado que represente um obstáculo que é evitado pelo NPC.
89
No início de cada execução o container cria os objetos e as diversas entidades com
base em configurações e na informação especificada em ficheiros XML ou informação
gerada em tempo de execução pelos geradores. Em cada execução é criado inteiramente
um ambiente de jogo de raiz.
4.3.3 Ferramenta de avaliação
A ferramenta de avaliação foi desenvolvida com o objetivo de avaliar de forma
fiável o desempenho e consumo de memória do sistema de navegação desenvolvido.
Como requisito desta ferramenta, deve possibilitar a execução de testes automáticos
(sem intervenção do ser humano) recebendo como argumento de entrada um ficheiro de
configuração e retornando como output o resultado dos testes efetuados. Apesar da
ferramenta de prova de conceito permitir observar o consumo de memória e o tempo de
resposta do sistema, não se trata de uma avaliação fiável. Por outro lado, a componente
gráfica que lhe está associada é “desnecessária” para a recolha de dados, estando esta
associada a um grande consumo de recursos o que influência os resultados obtidos e
dificulta a rapidez e replicação dos testes.
Tal como acontece na ferramenta de prova de conceito, a execução da
ferramenta de avaliação baseia-se em ficheiros de configuração no formato XML. O
ficheiro de entrada contêm diversas entradas, cada entrada representa uma situação de
Ilustração 31 - Simulação de 600 NPC’s com esquema de divisão baseado em Grelha e algoritmo de
procura A*.
Ilustração 32 - Simulação de 2 NPC’s com o esquema de divisão baseado em quadtree e algoritmo
de procura Fringe Search.
90
teste. Uma entrada é composta por diversos parâmetros que correspondem a um ficheiro
XML.
Parâmetros Descrição Valores possíveis
Id Identificação da simulação. -
Esquema de
divisão
Esquema de divisão a ser aplicado ao ambiente de
jogo.
Baseado em grelha ou
em quadtree
Algoritmo de
procura em grafos
Algoritmo de procura em grafos usado para a
resolução de caminhos
A* ou Fringe Search
Dimensão do
terreno
Tamanho do terreno onde será aplicado o esquema
de divisão.
Pequena, média ou
grande
Procedimentos Lista de procedimentos a aplicar ao ambiente de
jogo especificado nos parâmetros anteriores.
-
Número de
repetições
Número de vezes que os procedimentos serão
repetidos
-
Tabela 27 - Parâmetros que compõe uma entrada do ficheiro XML.
A divisão de cada simulação em parâmetros promove a modularização e a
reutilização dos ficheiros XML.
Os ficheiros de procedimentos são constituídos por diversas entradas, cada entrada
corresponde a uma operação que é executada de forma linear sendo registado o tempo
de processamento e memória utilizada na sua execução. Atualmente as operações
suportadas são:
Operação Descrição
InitNavigationGraph Inicialização do grafo de navegação.
Inicialização do algoritmo de procura.
AddObstacleAtLoad Adição de vários obstáculos durante a inicialização do grafo de navegação
e no final atualização do grafo de navegação.
AddObstacle Adição de um obstáculo e atualização do grafo de navegação.
PrintSearchSpace Obtém a dimensão do espaço de procura.
ToNode Quantização, ocorre a conversão de uma localização do ambiente de jogo
num nó do grafo de navegação.
ToPoint Localização, ocorre a conversão de um nó em uma localização do ambiente
91
de jogo.
ConnectNeighbours Procede à conexão de vizinhos.
FindePath Determina o caminho entre dois pontos.
FinishTest Finaliza o teste.
Tabela 28 - Operações suportadas pela ferramenta de avaliação.
Cada ficheiro de procedimento deve possuir no mínimo três procedimentos:
InitNavigationGraph, InitNavigationGraph e FinishTest. Para cada procedimento de
uma simulação executado é criado um ficheiro de output com o Id da simulação e o
processamento.
Comparando a implementação da ferramenta de prova de conceito e a ferramenta
de avaliação existem três grandes diferenças:
não é usada a técnica de programação de inversão de controlo uma vez que a
biblioteca usada na ferramenta de prova de conceito é específica para o Unity 3D e o
ambiente de execução da ferramenta de avaliação é inteiramente em C#;
os objetos e entidades assim como a sua descrição em XML diferem entre
ferramentas. Esta opção tem por objetivo poupar memória uma vez que na
ferramenta de avaliação não é necessário tantos atributos para descrever os objetos e
entidades;
a criação dos objetos não recorre a fábricas.
Embora estas diferenças tenham obrigado a uma nova implementação da camada
“business” do jogo de vídeo, devido à arquitetura do sistema de navegação ser centrada
em objetos tratou-se de uma tarefa relativamente simples.
A nível de funcionamento destacam-se duas diferenças entre as duas ferramentas:
na ferramenta de avaliação não existe uma camada locomoção, os pedidos
realizados à camada de procura em grafos são feitos de forma linear à medida que os
procedimentos vão sendo executados
existem dois modos de execução. O primeiro modo de execução consiste no uso de
apenas uma instância do algoritmo de procura em grafos, existindo apenas a thread
principal da ferramenta. O gestor não recorre à threadpool para lançar novas
instâncias, sendo as chamadas ao método responsável pela procura de caminho
síncronas, lineares e bloqueantes. O segundo modo de execução é semelhante à
ferramenta de prova de conceito, em que o gestor recorre à threadpool para
92
armazenar e consumir pedidos através de uma ou mais threads. A existência de dois
modos de execução tem por objetivo permitir avaliar melhor a arquitetura
desenvolvida.
A avaliação do tempo de processamento de cada operação é feita através do
biblioteca do C# System.Diagnostics que disponibiliza um conjunto de métodos
(nomeadamente o Stopwatch) que permitem medir de forma precisa o tempo decorrido.
Desta forma, é obtido o tempo antes da chamada à função e depois da chamada à
função, sendo o último tempo subtraído pelo primeiro tempo.
Para a avaliação da memória usada na execução do método, é obtida a memória
total do sistema antes da chamada à função e depois da chamada à função. Sendo a
quantidade de memória avaliada depois da chamada à função subtraída à quantidade de
memória avaliada antes da chamada à função. Antes da obtenção da memória total do
sistema é chamado o método Thread.MemoryBarrier uma vez que a máquina usada em
testes dispõe de um sistema multiprocessador e a chamada a este método sincroniza o
acesso à memória, fazendo com que o processador não faça reordenamento de
instruções.
4.4 Sumário
Neste capítulo é descrito o trabalho técnico realizado para alcançar os objetivos
propostos.
Na primeira secção é feita a análise do problema com vista aos objetivos traçados
no capítulo 1.2 e à pesquisa bibliogafia feita no Capítulo 2.
Depois da conceptualização dos problemas que este estudo procura resolver, na
secção seguinte é descrito o desenho da solução com base nos requisitos e problemas
identificados anteriormente.
A secção final tem por objetivo especificar a implementação do desenho da
solução, nesta secção é detalhado a implementação do sistema de navegação e das duas
ferramentas criadas para a explorar.
93
Capítulo 5
Resultados
Neste capítulo são indicados os resultados da avaliação da arquitetura descrita no
capítulo 4.2.1 através da ferramenta de avaliação descrita no capítulo 4.3.3 segundo os
métodos abordados no Capítulo 3.
A recolha da amostra foi efetuada no seguinte ambiente:
Hardware Especificação
Processador Intel Core 2 Duo P8600 @ 2.40GHz
Memória ram 4.00 GB
Disco rígido 5.400 RPM
Sistema operativo Windows 8 Pro
Tabela 29 - Especificação de ambiente de testes.
Para a recolha de dados no modo de execução com threadpool, a ferramenta de
avaliação foi configurada com o número máximo de 10 threads a serem para aplicadas
no modo global.
No geral, a recolha da amostra consistiu na avaliação do tempo de
processamento e memória alocada de conjunto de operações efetuadas sobre a
arquitetura descrita.
94
5.1 Apresentação de resultados
5.1.1 Inicialização da camada de representação do
ambiente
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0823 0,0285 6,8530 0,0402 158,7661 0,1265
Fringe Search 0,0825 0,0285 7,3136 0,0398 158,5532 0,1293
Povoado
A* 0,0823 0,0290 6,9181 0,0404 158,8104 0,2900
Fringe Search 0,0833 0,0283 7,0222 0,0402 158,6607 0,2929
Muito
Povoado
A* 0,0825 0,0289 7,1381 0,0395 159,1450 0,2886
Fringe Search 0,0827 0,0295 7,2173 0,0393 158,6877 0,2857
Tabela 30 - Resultados do tempo de processamento na inicialização da camada de representação do
ambiente.
(ms) Ambiente Pequeno Ambiente médio Ambiente grande
Grelha 0,0826 7,0771 158,7705
Quadtree 0,0288 0,0399 0,2355
Tabela 31 - Média do tempo de processamento na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente.
Os resultados mostram que:
o esquema de divisão baseado em grelha despende mais tempo de processamento na
inicialização da camada de representação do ambiente, quando comparado com o
esquema de divisão baseado em quadtree;
existe uma relação direta entre o tempo de processamento e a dimensão do ambiente
de jogo. Esta relação é mais expressiva no esquema de divisão baseado em grelha
(ver Ilustração 33).
95
Ambiente
pequeno Ambiente médio Ambiente grande
(B) Grelha Quadtree Grelha Grelha Quadtree Grelha
Pouco
Povoado
A* 12976,5 1007,7 876712,3 33240,9 14123176 524760,4
Fringe Search 12972,8 1008,0 876712,6 33240 14123176 524761,2
Povoado
A* 12989,5 960,3 876712 33240,3 14123176 524760,9
Fringe Search 12980,3 988,5 876712 33262,7 14123176 524760,6
Muito
Povoado
A* 12984,4 959,7 876712,3 33241,3 14123176 524760,3
Fringe Search 12982,5 959,6 876712,3 33240,7 14123176 524760,3
Tabela 32 - Resultados do consumo de memória na inicialização da camada de representação do
ambiente.
(B) Ambiente Pequeno Ambiente médio Ambiente grande
Grelha 12981 876712,3 14123176
Quadtree 980,6 33244,3 524760,6
Tabela 33 - Média do consumo de memória na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente.
Os resultados da alocação de memória na inicialização da camada de representação
do ambiente mostram que:
o esquema de divisão baseado em grelha apresenta um consumo superior de
memória quando comparado com a representação baseada em quadtree;
Ilustração 33 - Média do tempo de processamento na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente.
96
existe uma relação direta entre a memória consumida e a dimensão do ambiente de
jogo. Esta relação é mais expressiva para o esquema de divisão baseado em grelha
(ver Ilustração 34).
Modo de execução com threadpool
Tipo de recurso Ambiente pequeno Ambiente médio Ambiente grande
Grelha Tempo Proc. (ms) 0,0910 10,2835 241,5552
Memória (B) 13319,8 871158,5 14132659,2
Quadtree Tempo Proc. (ms) 0,0350 0,0455 0,1230
Memória (B) 948,6 33264,0 524786,3
Tabela 34 - Resumo dos resultados da inicialização da camada de representação do ambiente no
modo de execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
Os dados de execução com threadpool reafirmam as observações dos dados
execução sem threadpool. Quanto à comparação os dois tipos de execução observa-se
que:
a execução com threadpool no geral é ligeiramente mais demorada com a exceção
da esquema de divisão do ambiente de jogo baseada na quadtree para o ambiente de
jogo de maior dimensão;
a execução com threadpool apresenta um maior consumo de memória.
Ilustração 34 - Gráfico do consumo de memória na inicialização da camada de representação do
ambiente: Esquema de divisão Vs. Dimensão do ambiente.
97
Não são apresentados dados referentes ao algoritmo de procura em grafos uma vez
que esta camada não se encontra inicializada na altura em que esta operação é
executada.
5.1.2 Inicialização da camada de procura de
caminhos
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0032 0,0045 0,0059 0,0045 0,0078 0,0053
Fringe Search 0,0023 0,0029 0,0037 0,0030 0,0053 0,0044
Povoado
A* 0,0032 0,0041 0,0062 0,0047 0,0091 0,0054
Fringe Search 0,0023 0,0028 0,0039 0,0034 0,0053 0,0037
Muito
Povoado
A* 0,0032 0,0039 0,0056 0,0046 0,0091 0,0060
Fringe Search 0,0023 0,0032 0,0037 0,0031 0,0052 0,0038
Tabela 35 - Resultados do tempo de processamento na inicialização da camada de procura de
caminhos.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
A* 0,0037 0,0052 0,0071
Fringe
Search 0,0026 0,0034 0,0046
Tabela 36 - Média do tempo de processamento na inicialização camada de procura de caminhos:
Algoritmo de procura em grafos Vs. Dimensão do ambiente.
Através da análise dos resultados do tempo de processamento despendido na
inicialização da camada de procura de caminhos verificamos que.
o algoritmo A* consome mais tempo de processamento quando comparado com o
algoritmo Fringe Search.
existe uma relação direta entre o tempo de processamento e a dimensão do ambiente
de jogo. Esta relação é mais expressiva quando estamos a lidar com o algoritmo A*
(ver Ilustração 35).
98
Ambiente pequeno Ambiente médio Ambiente grande
(B) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 216,0 240,0 216,0 240,0 216,0 240,0
Fringe Search 160,0 184,0 160,0 184,0 160,0 184,0
Povoado
A* 216,0 240,0 216,0 240,0 216,0 240,0
Fringe Search 160,0 184,0 160,0 184,0 160,0 184,0
Muito
Povoado
A* 216,0 240,0 216,0 240,0 216,0 240,0
Fringe Search 160,0 184,0 160,0 184,0 160,0 184,0
Tabela 37 - Resultados do consumo de memória na inicialização da camada de procura de
caminhos.
(B) Grelha Quadtree
A* 216.0 240.0
Fringe Search 160.0 184.0
Tabela 38 - Média os resultados do consumo de memória na inicialização da camada de procura de
caminhos.
A análise dos dados do consumo de memória na inicialização da camada de
procura de caminhos mostra que:
o algoritmo de procura A* necessita de alocar mais memória do que o algoritmo
Fringe Search.
Existe uma relação entre o tipo de esquema de divisão do ambiente e o algoritmo de
procura, com o esquema de divisão do ambiente a necessitar de menos memória que
a quadtree.
Ilustração 35 - Gráfico do tempo de processamento na inicialização da camada do algoritmo de
procura em grafos: Algoritmo de procura em grafos Vs. Dimensão do ambiente.
99
Não são mostrados resultados relativamente à diferenciação da dimensão do
ambiente uma vez que não foram registadas quais quer diferenças.
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0092 0,0082 0,0099 0,0093 0,0150 0,0107
Fringe Search 0,0080 0,0077 0,0098 0,0098 0,0160 0,0108
Povoado
A* 0,0091 0,0084 0,0111 0,0095 0,0150 0,0113
Fringe Search 0,0090 0,0081 0,0099 0,0107 0,0144 0,0108
Muito
Povoado
A* 0,0097 0,0083 0,0100 0,0095 0,0150 0,0113
Fringe Search 0,0094 0,0081 0,0098 0,0094 0,0145 0,0111
Tabela 39 - Resultados do tempo de processamento na inicialização da camada de procura de
caminhos no modo de execução com threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
A* 0,0088 0,0099 0,0130
Fringe Search 0,0079 0,0099 0,0129
Tabela 40- Média do tempo de processamento na inicialização da camada de procura de caminhos
no modo de execução com threadpool: Algoritmo de procura vs. dimensão do ambiente de jogo.
Os resultados do tempo de processamento na inicialização da camada de procura de
caminhos são semelhantes ao modo de execução sem threadpool (ver Ilustração 36).
Contudo no modo de execução com threadpool observa-se uma diferença de valores
menor entre os dois algoritmos.
Quando comparado os dois modos de execução verificamos que o modo de
execução com threadpool demora mais tempo na inicialização da camada de algoritmo
de procura.
100
Ambiente pequeno Ambiente médio Ambiente grande
(B) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 325,1 407,9 331,1 408,0 425,3 408,0
Fringe Search 395,9 408,0 351,5 408,0 418,6 408,0
Povoado
A* 325,1 408,0 336,1 408,0 325,1 408,0
Fringe Search 411,8 401,9 330,8 408,0 429,5 408,0
Muito
Povoado
A* 425,1 407,4 335,1 408,0 325,1 408,0
Fringe Search 398,4 408,0 430,1 408,0 425,1 408,3
Tabela 41 - Resultados do consumo de memória na inicialização da camada de procura de
caminhos no modo de execução com threadpool.
(B) Grelha Quadtree
A* 350,3 407,9
Fringe Search 399,1 407,4
Tabela 42 – Média dos resultados do consumo de memória na inicialização da camada de procura
de caminhos no modo de execução com threadpool.
No que diz respeito à memória consumida na inicialização da camada do
algoritmo de procura, à semelhança dos resultados da execução sem threadpool
verificou-se a mesma relação entre o tipo de esquema de divisão do ambiente e o
Ilustração 36 - Gráfico do tempo de processamento na inicialização da camada do algoritmo de
procura em grafos no modo de execução com threadpool: Algoritmo de procura em grafos Vs.
Dimensão do ambiente.
101
algoritmo de procura. Contudo, não foi verificado que o algoritmo A* necessite de mais
memória em comparação com o algoritmo Fringe Search.
Quando comparamos os dois modos de execução verificamos que o modo de
execução com threadpool no geral está associado a um maior consumo de memória.
5.1.3 Adição de objetos antes do início do jogo
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0802 1,8767 6,8802 158,0598 150,9461 2533,0915
Fringe Search 0,0817 1,8771 7,5691 150,5527 151,2722 2525,0418
Povoado
A* 0,0850 1,9777 7,6098 162,8541 164,1789 2713,5759
Fringe Search 0,0831 1,9914 7,1021 164,7457 163,9507 2728,3264
Muito
Povoado
A* 0,1129 2,1517 7,1981 169,9471 160,3751 2799,2295
Fringe Search 0,0872 2,1477 8,3126 167,1792 157,9600 2795,6864
Tabela 43 - Resultados do tempo de processamento na adição de objetos antes do início do jogo.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0883 7,4453 158,1138
Quadtree 2,0037 162,2231 2682,4919
Tabela 44 - Média do consumo do tempo de processamento na adição de objetos antes do início do
jogo: Esquema de divisão Vs. Dimensão do ambiente.
(ms) Pouco povoado Povoado Muito povoado
Grelha 52,8049 57,1683 55,6743
Quadtree 895,0832 962,2452 989,3903
Tabela 45 - Média do tempo de processamento na adição de objetos antes do início do jogo:
Esquema de divisão Vs. Densidade de objetos.
A análise do tempo de processamento despendido na adição de objetos antes do
início do jogo mostra que:
102
o esquema de divisão do ambiente de jogo baseado em quadtree necessita de mais
tempo para completar a tarefa de adição de objetos.
existe uma relação direta entre o tempo de processamento e a dimensão do ambiente
de jogo. Esta relação é mais expressiva para o esquema de divisão baseado em
quadtree (ver Ilustração 37).
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0935 1,8961 10,4389 272,5728 225,6396 4158,6945
Fringe Search 0,0907 1,8932 9,7634 256,0591 344,5340 4266,2258
Povoado
A* 0,0962 2,0067 10,6019 260,5249 190,6228 4890,3458
Fringe Search 0,0956 2,0235 10,1114 256,6111 220,7723 4369,5282
Muito
Povoado
A* 0,0995 2,1810 11,3993 272,4382 240,5406 4454,7437
Fringe Search 0,0992 2,2203 10,6207 281,7327 236,7920 4904,1754
Tabela 46 - Resultados do tempo de processamento na adição de objetos antes do início do jogo no
modo de execução com threadpool.
Ilustração 37 – Gráfico da média do consumo do tempo de processamento na adição de objetos antes
da execução do jogo: Esquema de divisão Vs. Dimensão do ambiente.
103
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0883 7,4453 158,1138
Quadtree 2,0037 162,2231 2682,4919
Tabela 47 - Média do tempo de processamento na adição de objetos antes do início do jogo no modo
de execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
(ms) Pouco povoado Povoado Muito povoado
Grelha 52,8049 57,1683 55,6743
Quadtree 895,0832 962,2452 989,3903
Tabela 48- Média do tempo de processamento na adição de objetos antes do início do jogo no modo
de execução com threadpool: Esquema de divisão Vs. Densidade de objetos.
A execução com threadpool confirma as observações efetuadas com base nos
resultados da execução sem threadpool (ver Ilustração 38). Contudo, verifica-se
também tempos bastante superiores especialmente à medida que o ambiente de jogo
aumenta de dimensão.
Ilustração 38 - Gráfico da média do consumo do tempo de processamento na adição de objetos antes
da execução do jogo no modo de execução com threadpool: Esquema de divisão Vs. Dimensão do
ambiente.
104
5.1.4 Tamanho do espaço de pesquisa
A Tabela 49 mostra o máximo de nós possíveis que cada esquema de divisão
pode gerar e o número de objetos a adicionados em cada tipo de ambiente por densidade
de objetos (para mais informação consultar capítulo 3.2.1 ).
(Nº nós) Máximo de
nós
Pouco povoado
(25%)
Povoado
(30%)
Muito povoado
(35%)
Ambiente pequeno 64 16 19 22
Ambiente Médio 1024 256 307 358
Ambiente grande 65536 16384 19660 22937
Tabela 49 - Número máximo de nós por dimensão de ambiente e por densidade de objetos
Ambiente pequeno Ambiente médio Ambiente grande
(Nº nós) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco Povoado 64 46 4096 3127 65536 49894
Povoado 64 52 4096 3352 65536 53722
Muito Povoado 64 64 4096 3535 65536 56596
Tabela 50 - Resultados do tamanho do espaço de pesquisa.
(Nº nós) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 64 4096 65536
Quadtree 54 3338 53404
Tabela 51 – Média dos resultados do tamanho do espaço de pesquisa: Esquema de divisão Vs.
Dimensão do ambiente.
No que diz respeito ao espaço de pesquisa podemos verificar que:
o esquema de divisão baseado em grelha gera um número de nós superior ao
número de nós da representação do ambiente baseada em quadtree. O número de nós
da grelha corresponde a todas as células que a compõem.
Como de esperar existe uma relação entre o número de nós e a dimensão do
ambiente de jogo (ver Ilustração 39).
105
5.1.5 Quantização
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0020 0,0087 0,0028 0,0110 0,0050 0,0054
Fringe Search 0,0020 0,0093 0,0027 0,0104 0,0052 0,0073
Povoado
A* 0,0022 0,0085 0,0031 0,0038 0,0066 0,0057
Fringe Search 0,0019 0,0083 0,0028 0,0041 0,0050 0,0059
Muito
Povoado
A* 0,0019 0,0021 0,0024 0,0043 0,0064 0,0071
Fringe Search 0,0020 0,0026 0,0023 0,0035 0,0052 0,0056
Tabela 52 - Resultados do tempo de processamento na quantização.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0020 0,0027 0,0056
Quadtree 0,0066 0,0062 0,0062
Tabela 53 – Média dos resultados do tempo de processamento na quantização: Esquema de divisão
Vs. Dimensão do ambiente.
Ilustração 39 - Gráfico da média do tamanho do espaço de procura: Esquema de divisão Vs.
Dimensão do ambiente.
106
(ms) Pouco povoado Povoado Muito povoado
Grelha 52,8049 57,1683 55,6743
Quadtree 895,0832 962,2452 989,3903
Tabela 54 - Média dos resultados do tempo de processamento na quantização: Esquema de divisão
Vs. Densidade de objetos.
Os resultados recolhidos mostram que:
o esquema de divisão baseado em quadtree despende mais tempo na realização da
operação de quantização do que a grelha;
verifica-se uma relação direta, entre o esquema de divisão baseado em grelha e a
dimensão do ambiente. No esquema de divisão baseado em quadtree, esta relação é
inversa, com o tempo de processamento a diminuir com o aumento da dimensão do
ambiente de jogo (ver Ilustração 40).
a comparação do esquema de divisão baseado em grelha com a densidade de
objetos, apresenta valores sensivelmente contantes. No esquema de divisão baseado
em quadtree, observa-se uma relação inversa, com o tempo de processamento a
diminuir com o aumento da densidade de objetos (ver Ilustração 41).
Ilustração 40 - Gráfico da média do tempo de processamento na localização: Esquema de divisão
Vs. Dimensão do ambiente.
107
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0043 0,0152 0,0049 0,0173 0,0064 0,0067
Fringe Search 0,0038 0,0143 0,0048 0,0176 0,0079 0,0066
Povoado
A* 0,0043 0,0147 0,0062 0,0057 0,0065 0,0070
Fringe Search 0,0043 0,0150 0,0049 0,0068 0,0064 0,0069
Muito
Povoado
A* 0,0046 0,0047 0,0051 0,0057 0,0064 0,0070
Fringe Search 0,0049 0,0046 0,0050 0,0056 0,0065 0,0068
Tabela 55 - Resultados do tempo de processamento na quantização no modo de execução
threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0044 0,0052 0,0067
Quadtree 0,0114 0,0098 0,0068
Tabela 56 – Média dos resultados do tempo de processamento na quantização no modo de execução
com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
Ilustração 41 - Gráfico da média do tempo de processamento na localização: Esquema de divisão
Vs. Densidade de objetos.
108
(ms) Pouco povoado Povoado Muito povoado
Grelha 0,0054 0,0054 0,0054
Quadtree 0,0130 0,0093 0,0057
Tabela 57 - Média dos resultados do tempo de processamento na quantização no modo de execução
com threadpool: Esquema de divisão Vs. Densidade de objetos.
Os resultados recolhidos mostram que:
o esquema de divisão baseado em quadtree demora mais tempo na realização da
operação de localização do que o esquema de divisão baseado em grelha;
observa-se uma relação direta entre o esquema de divisão baseado em grelha e a
dimensão do ambiente. Em contraste, verifica-se uma relação inversa entre o
esquema de divisão baseado em quadtree e a dimensão do ambiente (ver Ilustração
42).
o esquema de divisão baseado em grelha quando comparado com a densidade de
objetos apresenta valores sensivelmente contantes. No esquema de divisão baseado
em quadtree observa-se uma relação inversa, com o tempo de processamento a
diminuir com o aumento da densidade de objetos (ver Ilustração 43).
A comparação entre os dois modos de execução mostra que o modo de execução
com threadpool apresenta resultados superiores.
Ilustração 42 - Gráfico da média do tempo de processamento na quantização no modo de execução
com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
109
5.1.6 Localização
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0022 0,0029 0,0037 0,0034 0,0045 0,0049
Fringe Search 0,0021 0,0027 0,0031 0,0031 0,0046 0,0064
Povoado
A* 0,0025 0,0026 0,0038 0,0042 0,0062 0,0079
Fringe Search 0,0022 0,0024 0,0031 0,0044 0,0045 0,0079
Muito
Povoado
A* 0,0022 0,0025 0,0030 0,0044 0,0062 0,0090
Fringe Search 0,0022 0,0029 0,0030 0,0033 0,0047 0,0078
Tabela 58 - Resultados do tempo de processamento na localização.
Ilustração 43 - Gráfico da média do tempo de processamento na quantização no modo de execução
com threadpool: Esquema de divisão Vs. Densidade de objetos.
110
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0022 0,0033 0,0051
Quadtree 0,0027 0,0038 0,0073
Tabela 59 – Média dos resultados do tempo de processamento na localização: Esquema de divisão
Vs. Dimensão do ambiente.
Os resultados obtidos do tempo de processamento na localização mostram:
O esquema de divisão baseado em quadtree despende mais tempo na realização da
operação de localização do que a grelha;
Existe uma relação entre o esquema de divisão e a dimensão do ambiente (ver
Ilustração 44).
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0041 0,0042 0,0047 0,0078 0,0092 0,0081
Fringe Search 0,0035 0,0039 0,0045 0,0082 0,0107 0,0071
Povoado
A* 0,0040 0,0042 0,0059 0,0081 0,0091 0,0093
Fringe Search 0,0040 0,0041 0,0046 0,0093 0,0092 0,0092
Muito A* 0,0045 0,0043 0,0047 0,0080 0,0093 0,0089
Ilustração 44 - Gráfico da média do tempo de processamento na localização: Esquema de divisão
Vs. Dimensão do ambiente.
111
Povoado Fringe Search 0,0047 0,0042 0,0046 0,0077 0,0090 0,0080
Tabela 60 - Resultados do tempo de processamento na localização no modo de execução com
threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0041 0,0048 0,0094
Quadtree 0,0042 0,0082 0,0085
Tabela 61 - Média dos resultados do tempo de processamento na localização no modo de execução
com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
No modo de execução com threadpool é verificada a relação entre o esquema de
divisão e a dimensão do ambiente as observações, tal como acontece no modo de
execução sem threadpool (ver Ilustração 45).
Quando comparados os dois tipos de execução verifica-se que o modo de execução
com threadpool apresenta um tempo de execução superior.
5.1.7 Procura de caminho
Antes da apresentação dos resultados do tempo de execução da operação de
procura de caminho inerente a cada modo de execução, iremos caracterizar a procura de
caminho realizada em cada situação de teste.
Ilustração 45 - Gráfico da média do tempo de processamento na localização no modo de execução
com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
112
Ambiente
pequeno Ambiente médio Ambiente grande
(Nº nós) Grelha Quadtree Grelha Grelha Quadtree Grelha
Pouco
Povoado
A* 8,0 4,0 89,0 71,0 317,0 257,0
Fringe Search 38,0 16,0 372,0 367,0 1281,0 1246,0
Povoado
A* 10,0 560,0 75,0 64,0 440,0 408,0
Fringe Search 26,0 29,0 362,0 374,0 1256,0 1327,0
Muito
Povoado
A* 9,0 9,0 152,0 95,0 526,0 286,0
Fringe Search 20,0 20,0 365,0 406,0 1340,0 1339,0
Tabela 62 - Nº nós visitados na procura de caminho.
(Nº nós) Ambiente Pequeno Ambiente médio Ambiente grande
Grelha 18,5 235,8 860,0
Quadtree 106,3 229,5 810,5
Tabela 63 - Média dos resultados do nº de nos visitados na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente.
(Nº nós) Ambiente Pequeno Ambiente médio Ambiente grande
A* 100,0 91,0 372,3
Fringe Search 27,0 374,3 1298,2
Tabela 64 - Média dos resultados do nº de nos visitados na procura de caminho: Algoritmo de
procura Vs. Dimensão do ambiente.
No que diz respeito às diferentes dimensões do ambiente de jogo, a análise da
Tabela 63 mostra que o esquema de divisão baseado em grelha apresenta um maior
número de nós visitados (ver Ilustração 46). A análise da Tabela 64 indica que o
responsável pela maioria das visitas é o algoritmo Fringe Search. Estas duas
observações mostram como exceção o ambiente de dimensão pequena (ver Ilustração
47).
113
(Nº nós) Pouco povoado Povoado Muito povoado
A* 124,3 259,5 179,5
Fringe Search 553,3 562,3 581,7
Tabela 65 - Média dos resultados do nº de nos visitados na procura de caminho: Algoritmo de
procura Vs. Densidade de objetos.
Ilustração 46 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho:
Esquema de divisão Vs. Dimensão do ambiente.
Ilustração 47 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho:
Algoritmo de procura Vs. Dimensão do ambiente.
114
No que diz respeito à densidade de objetos a análise da Tabela 65 mostra que:
O algoritmo que visita mais nós é o Fringe Search.
Verifica-se uma relação direta entre o nº de nós visitados pelo algoritmo de procura
Fringe Search e a densidade de objetos (ver Ilustração 48).
(Nº nós) Grelha Quadtree
A* 180,7 194,9
Fringe Search 562,2 569,3
Tabela 66 - Média dos resultados: Esquema de divisão vs. Algoritmo de procura
A Tabela 66 ignora a densidade de objetos e as diferentes dimensões do
ambiente de jogo. É possível verificar que o algoritmo Fringe Search apresenta um
elevado número de nós expandidos. No que diz respeito ao esquema de divisão, pode
verificar-se que a representação em quadtree está associada a um maior número de nós
visitados.
Ambiente
pequeno Ambiente médio Ambiente grande
(Nº nós) Grelha Quadtree Grelha Grelha Quadtree Grelha
Pouco
Povoado
A* 51 27 621 531 2430 2048
Fringe Search 49 19 669 640 2234 2238
Povoado A* 64 3840 569 506 2739 2555
Ilustração 48 - Gráfico da média dos resultados do nº de nos visitados na procura de caminho:
Algoritmo de procura Vs. Densidade de objetos.
115
Fringe Search 40 34 618 627 2144 2236
Muito
Povoado
A* 56 56 780 631 3025 2331
Fringe Search 32 32 618 631 2131 2149
Tabela 67 - Nº nós expandidos na procura de caminho.
(Nº nós) Ambiente Pequeno Ambiente médio Ambiente grande
Grelha 48,7 645,8 2450,5
Quadtree 668,0 594,3 2259,5
Tabela 68 - Média dos resultados do nº de nós expandidos na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente.
(Nº nós) Ambiente Pequeno Ambiente médio Ambiente grande
A* 682,3 606,3 2521,3
Fringe Search 34,0 633,8 2188,7
Tabela 69 - Média dos resultados do nº de nós expandidos na procura de caminho: Algoritmo de
procura Vs. Dimensão do ambiente.
Com base na dimensão do ambiente é possível verificar que o esquema baseado
em grelha esta associado a um maior número de nós expandidos (ver Ilustração 49). No
que diz respeito ao algoritmo de procura verifica-se que o algoritmo A* é responsável
pela maioria dos nós expandidos (ver Ilustração 50).
116
Ambiente pequeno Ambiente médio Ambiente grande
Quadtree Grelha Grelha Quadtree Grelha Grelha
Pouco
Povoado
A* Custo 112 48 1168 972 4632 3760
Tamanho 8 4 81 68 315 255
Fringe
Search
Custo 201 101 3016 2882 10117 10124
Tamanho 16 8 217 207 732 725
Povoado A* Custo 120 5760 1104 936 4592 4020
Ilustração 49 – Gráfico da média dos resultados do nº de nós expandidos na procura de caminho:
Esquema de divisão Vs. Dimensão do ambiente.
Ilustração 50 - Média dos resultados do nº de nós expandidos na procura de caminho: Algoritmo de
procura Vs. Dimensão do ambiente.
117
Tamanho 9 480 75 63 309 276
Fringe
Search
Custo 246 112 2993 3005 10137 10101
Tamanho 19 9 216 216 728 728
Muito
Povoado
A* Custo 120 120 1256 1064 4744 3936
Tamanho 9 87 74 323 270
Fringe
Search
Custo 200 200 2998 2879 10093 10046
Tamanho 17 17 219 210 732 723
Tabela 70 – Custo e tamanho do caminho na procura de caminho.
Para referência a Tabela 70 mostra os resultados do custo e tamanho do caminho
associados à procura de caminho.
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0992 0,0468 2,7979 1,7753 18,2011 14,0959
Fringe Search 0,0444 0,0222 0,5954 0,6169 11,4111 15,7379
Povoado
A* 0,1078 0,0696 1,9745 1,5999 23,3095 23,9534
Fringe Search 0,0344 0,0347 0,5857 0,6162 11,9188 16,6199
Muito
Povoado
A* 0,0971 0,0975 4,5987 2,4958 26,4892 14,5364
Fringe Search 0,0271 0,0279 0,5947 0,6627 12,0561 17,4047
Tabela 71 - Resultados do tempo de processamento na procura de caminho.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0683 1,8578 17,2310
Quadtree 0,0498 1,2944 17,0580
Tabela 72 – Média dos resultados do tempo de processamento na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente.
(ms) Pouco povoado Povoado Muito povoado
Grelha 5,5249 6,3218 7,3105
Quadtree 5,3825 7,1489 5,8708
Tabela 73 - Média dos resultados do tempo de procura de caminho: Esquema de divisão Vs.
Densidade de objetos.
118
A análise dos dados recolhidos mostram que:
o esquema de divisão baseado em grelha demora mais tempo na realização da
procura de caminho do que o esquema de divisão baseado em quadtree;
verifica-se uma relação direta entre o esquema de divisão baseado e a dimensão do
ambiente (ver Ilustração 51);
observa-se uma relação direta entre o esquema de divisão baseado na grelha e a
densidade de objetos (ver Ilustração 52).
Ilustração 51- Gráfico da média do tempo de processamento na procura de caminho no modo de
execução: Esquema de divisão Vs. Dimensão do ambiente.
119
(ms) Ambiente pequeno Ambiente médio Ambiente grande
A* 0,0863 2,5404 20,0976
Fringe Search 0,0333 0,6119 14,1914
Tabela 74 – Média dos resultados do tempo de processamento na procura de caminho: Algoritmo
de procura Vs. Dimensão do ambiente.
(ms) Pouco povoado Povoado Muito povoado
A* 6,1694 8,5025 8,0525
Fringe Search 4,7380 4,9683 5,1289
Tabela 75 - Média dos resultados do tempo de procura de caminho: Algoritmo de procura Vs.
Densidade de objetos.
A análise dos dados do algoritmo de procura que:
o algoritmo de procura A* demora mais tempo a resolver o caminho quando
comparado com o algoritmo de procura Fringe Search.
verifica-se uma relação direta entre os algoritmo de procura e a dimensão do
ambiente (ver Ilustração 54);
verifica-se uma relação direta entre os algoritmo de procura e a densidade de objetos
(ver Ilustração 53);
Ilustração 52 - Gráfico da média do tempo de processamento na procura de caminho: Esquema de
divisão Vs. Densidade de objetos.
120
Ilustração 54 – Gráfico da média dos resultados do tempo de processamento na procura de caminho:
Algoritmo de procura Vs. Dimensão do ambiente.
Ilustração 53 – Gráfico da média dos resultados do tempo de procura de caminho: Algoritmo de
procura Vs. Densidade de objetos.
121
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0.7671 0.0432 7.1283 3.3398 217.1986 115.0754
Fringe Search 0.3926 0.0259 7.7789 0.9639 260.2318 141.4198
Povoado
A* 0.5430 0.1748 17.8604 4.9524 449.7212 372.0360
Fringe Search 0.0589 0.1411 13.4733 10.2921 404.6305 310.4867
Muito
Povoado
A* 0.9584 0.6397 31.3672 14.1955 646.3444 518.9940
Fringe Search 0.8921 0.1801 22.9686 12.8670 609.8572 497.0122
Tabela 76 - Resultados do tempo de processamento na procura de caminho no modo de execução
threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0.6020 16.7628 431.3306
Quadtree 0.2008 7.7685 325.8374
Tabela 77 – Média dos resultados do tempo de processamento na procura de caminho: Esquema de
divisão Vs. Dimensão do ambiente no modo de execução threadpool.
(ms) Pouco povoado Povoado Muito povoado
Grelha 82.2496 147.7145 218.7313
Quadtree 43.4780 116.3472 173.9814
Tabela 78 - Média dos resultados do tempo de procura de caminho: Esquema de divisão Vs.
Densidade de objetos no modo de execução com threadpool.
A análise dos dados recolhidos com base no esquema de divisão mostra resultados
semelhantes aos obtidos no modo de execução sem threadpool. Contudo quando se
compara os dois modos, verifica-se que o modo de execução com threadpool consome
um tempo de processamento superior (ver Ilustração 51 e Ilustração 52).
122
(ms) Ambiente pequeno Ambiente médio Ambiente grande
A* 0.5210 13.1406 386.5616
Fringe Search 0.2092 11.3906 370.6064
Tabela 79 – Média dos resultados do tempo de processamento na procura de caminho no modo de
execução com threadpool: Algoritmo de procura Vs. Dimensão do ambiente.
Ilustração 55 - Gráfico da média dos resultados do tempo de processamento na procura de
caminho: Esquema de divisão Vs. Dimensão do ambiente no modo de execução com threadpool.
Ilustração 56 - Gráfico da média dos resultados do tempo de procura de caminho: Esquema de
divisão Vs. Densidade de objetos no modo de execução com threadpool.
123
(ms) Pouco povoado Povoado Muito povoado
A* 57.2587 140.8813 202.0832
Fringe Search 68.4688 123.1804 190.6295
Tabela 80 - Média dos resultados do tempo de procura de caminho no modo de execução com
threadpool: Algoritmo de procura Vs. Densidade de objetos.
Os resultados obtidos relativamente ao algoritmo de procura mostram
novamente similaridade com os dos obtidos no modo de execução sem threadpool,
sendo também verificado um maior consumo de tempo de processamento (ver
Ilustração 54 e ver Ilustração 53);
Ilustração 57 - Gráfio da média dos resultados do tempo de processamento na procura de caminho
no modo de execução com threadpool: Algoritmo de procura Vs. Dimensão do ambiente.
124
5.1.8 Conexão de vizinhos
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0649 1,8315 6,1815 146,7390 128,1095 2380,3570
Fringe Search 0,0686 1,8331 6,2359 150,5527 135,5613 2442,1794
Povoado
A* 0,0658 1,9225 6,0823 150,8234 126,9979 2436,7918
Fringe Search 0,0692 1,9340 6,1892 148,2640 125,0039 2491,8742
Muito
Povoado
A* 0,0662 2,0838 6,2390 157,3369 132,6878 2490,3111
Fringe Search 0,0684 2,3332 6,2172 150,6001 137,2191 2542,0801
Tabela 81 - Resultados do tempo de processamento na conexão de vizinhos.
Ilustração 58 - Gráfico da média dos resultados do tempo de procura de caminho no modo de
execução com threadpool: Algoritmo de procura Vs. Densidade de objetos.
125
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0672 6,1908 130,9299
Quadtree 1,9897 150,7193 2463,9323
Tabela 82 - Média dos resultados na conexão de vizinhos: Esquema de divisão Vs. Dimensão do
ambiente.
Os dados recolhidos indicam que:
O esquema de divisão baseado em quadtree demora mais tempo na determina dos
vizinhos quando comparado com o esquema de divisão baseado em grelha;
Verifica-se uma relação direta entre o esquema de divisão e a dimensão do ambiente
(ver Ilustração 59).
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0743 1,8460 16,0038 282,3993 216,5745 4250,7287
Fringe Search 0,0732 1,8436 13,9961 247,4384 332,4596 4243,9365
Povoado
A* 0,0738 1,9751 13,7657 282,8601 174,7220 4537,8333
Fringe Search 0,0742 1,9458 15,1245 242,9283 214,9347 4217,8934
Ilustração 59 - Gráfico da média do tempo de processamento da conexão de vizinhos: Esquema de
divisão Vs. Dimensão do ambiente.
126
Muito
Povoado
A* 0,0728 2,1356 22,7980 272,2811 226,6443 4406,2555
Fringe Search 0,0737 2,1160 11,1273 293,0865 248,3991 4387,9968
Tabela 83 - Resultados do tempo de processamento na conexão de vizinhos no modo de execução
com threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0737 15,4692 235,6224
Quadtree 1,9770 270,1656 4340,7740
Tabela 84 – Média de resultados do tempo de processamento na conexão de vizinhos no modo de
execução com threadpool.
Os resultados recolhidos mostram a mesmas observações do modo de execução
sem threadpool (ver Ilustração 60). A comparação entre os dois modos de execução
mostra que o modo de execução com threadpool apresenta tempo de processamento
superior.
Ilustração 60 - Gráfico da média do tempo de processamento da conexão de vizinhos no modo de
execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
127
5.1.9 Adição de objeto
Modo de execução sem threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0051 1,8230 0,0090 144,3576 0,0113 2427,8789
Fringe Search 0,0054 1,8256 0,0085 144,5888 0,0114 2433,0068
Povoado
A* 0,0051 1,8987 0,0091 148,4475 0,0130 2491,5081
Fringe Search 0,0048 1,9053 0,0084 147,9232 0,0113 2499,2016
Muito
Povoado
A* 0,0050 2,0099 0,0079 151,8049 0,0130 2537,5944
Fringe Search 0,0049 2,0341 0,0084 157,0554 0,0113 2555,2386
Tabela 85 - Resultados do tempo de processamento de adição de objeto.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0051 0,0086 0,0119
Quadtree 1,9161 149,0296 2490,7380
Tabela 86 - Média dos resultados de adição de objeto: Esquema de divisão Vs. Dimensão do
ambiente.
(ms) Pouco povoado Povoado Muito povoado
Grelha 46,0370 44,0681 47,0829
Quadtree 853,9154 871,9350 890,7909
Tabela 87 - Média dos resultados do tempo adição de objeto: Esquema de divisão Vs. Densidade de
objetos.
A análise dos resultados mostra que:
o esquema de divisão baseado em quadtree demora mais tempo na adição de um
objeto quando comparado com o esquema de divisão baseado em grelha;
verifica-se uma relação direta entre o esquema de divisão e a dimensão do ambiente.
128
observa-se uma relação direta entre o esquema de divisão baseado na quadtree e a
densidade de objetos.
Modo de execução com threadpool
Ambiente pequeno Ambiente médio Ambiente grande
(ms) Grelha Quadtree Grelha Quadtree Grelha Quadtree
Pouco
Povoado
A* 0,0108 1,9114 0,0113 282,0036 0,0165 4196,8917
Fringe Search 0,0103 1,9064 0,0110 245,2843 0,0178 4276,5933
Povoado
A* 0,0107 2,0030 0,0124 286,6588 0,0173 4741,2733
Fringe Search 0,0101 1,9838 0,0111 250,8083 0,0167 4192,5921
Muito
Povoado
A* 0,0101 2,1161 0,0113 280,1132 0,0172 4367,6116
Fringe Search 0,0099 2,1066 0,0112 286,2601 0,0165 4450,9673
Tabela 88 - Resultados do tempo de processamento de adição de objeto no modo de execução com
threadpool.
(ms) Ambiente pequeno Ambiente médio Ambiente grande
Grelha 0,0737 15,4692 235,6224
Quadtree 1,9770 270,1656 4340,7740
Tabela 89 – Média dos resultados do tempo de processamento de adição de objeto no modo de
execução com threadpool: Esquema de divisão Vs. Dimensão do ambiente.
Os resultados recolhidos mostram a mesmas observações do modo de execução
sem threadpool. A comparação entre os dois modos de execução mostra que o modo de
execução com threadpool apresenta tempo de processamento superior.
5.2 Sumário
Neste capítulo são disponibilizados os resultados obtidos através da ferramenta
de avaliação. De forma a obter-se dados do funcionamento da aplicação no geral, foram
recolhidos dados de diferentes operações, cada operação foi subdividida pelo modo de
execução que os originou os dados.
129
A observação dos dados mostra que o esquema de divisão do ambiente baseado
quadtree apenas é inferior à grelha na conexão de vizinhos. Infelizmente esta operação
tem um grande enfase nos ambientes dinâmicos.
Os dados inerentes ao algoritmo Fringe Search mostram no geral um menor
tempo quando comparado com os dados do algoritmo A*
No que diz respeito à comparação entre os modos de execução verificamos que
o modo de execução com threadpool está associado a um maior tempo de
processamento e maior alocação de memória.
130
Capítulo 6
Discussão de resultados e conclusão
6.1 Discussão de resultados
A apresentação de resultados dá lugar nesta secção, à sua discussão, com vista aos
objetivos e hipóteses de investigação traçados.
Na operação de inicialização da camada de representação, ambas as representações
apresentam bons resultados, no que diz respeito ao consumo de memória e tempo de
processamento. Existe contudo, uma clara vantagem nos resultados obtidos, do esquema
divisão baseado em quadtree. A diferença de valores pode ser justificada pela
implementação desta operação em cada um dos esquemas de divisão do ambiente.
Uma vez que nenhum objeto foi anteriormente adicionado ao ambiente de jogo, a
operação de inicialização da quadtree consiste apenas na inicialização do nó raiz (root
node) e na alocação de memória de um array com o tamanho igual ao número máximo
possível de nós.
No caso da grelha, não existe relação entre o número de objetos adicionados ao
ambiente de jogo e o número de nós, uma vez que, na operação de inicialização, é
sempre necessário inicializar todas as células (nós) que constituem a grelha. Isto
constitui uma desvantagem relativamente à memória alocada e tempo de processamento
despendido quando comparado com a quadtree, principalmente se tivermos presente que
para cada, nó é necessário determinar os nós vizinhos.
Outro aspeto a ter em conta, é a dimensão do ambiente, que à medida que vai
aumentando de tamanho, aumenta também o tempo de processamento e a alocação de
memória. É de realçar que este aumento na quadtree é mínimo, quando comparado com
a grelha. O facto da representação do ambiente baseado em grelha ser mais sensível ao
aumento da dimensão do ambiente, pode ser justificado pelo número de nós
inicializados aumentar com o aumento da dimensão do ambiente.
131
Para esta operação verifica-se que a primeira, segunda e quarta hipótese de
investigação são inteiramente válidas, sendo que a terceira hipótese apenas é válida para
a representação do ambiente baseado em grelha.
No geral, os resultados verificados na operação de inicialização da camada de
procura de caminhos são bons, com o algoritmo A* a mostrar um maior tempo de
processamento e maior alocação de memória, quando comparado com o algoritmo
Fringe Search. Esta diferença, pode ser explicada pelas estruturas usadas por cada um
dos algoritmos de procura em grafos, sendo as estruturas do algoritmo A* mais
complexas e necessitarem de uma maior quantidade de recursos para a sua inicialização.
Quando analisados os dados com base na dimensão do ambiente, verificamos que
existe um impacto direto no tempo de execução, sendo que a alocação de memoria se
mantem constante.
Para esta operação, verifica-se que a sétima hipótese de investigação colocada é
válida.
A operação de adição de objetos antes do início do jogo mostra, que o esquema de
divisão baseado em quadtree despende muito mais tempo de processamento e de
memória, para a realização desta operação. Esta diferença pode ser explicada pela
implementação da atualização de cada uma das estruturas. Na representação do
ambiente de jogo baseada em grelha, não existe a necessidade de determinar os vizinhos
para cada um dos nós, havendo apenas a necessidade de calcular o limiar de
navegabilidade das células afetadas. O mesmo não acontece na representação do
ambiente de jogo baseada em quadtree, em que é necessário determinar para cada nó, os
vizinhos e o limiar de navegabilidade associado a cada um deles.
É possível ainda verificar, um aumento de recursos computacionais consumidos à
medida que a dimensão do ambiente de jogo aumenta. É possível verificar a mesma
relação no que diz respeito à densidade de objetos no ambiente de jogo, contudo a
observação verificada é de grandeza inferior. As diferenças encontradas, poderão ser
explicadas, pela implementação desta operação. Uma vez que a operação ocorre antes
do início do jogo, é necessário que apenas ocorra a atualização do grafo de navegação
uma única vez, não observando-se assim uma grande diferença nos valores com base no
número de objetos.
A primeira, terceira e quarta hipótese de investigação, com base nesta operação,
são validadas pelos dados obtidos. Contudo, a segunda hipótese de investigação não é,
132
uma vez que a quadtree apresenta um tempo de processamento bastante superior quando
comparada com grelha.
A operação de verificação do espaço de pesquisa, mostrar o número de nós gerados
por cada representação do ambiente, com base na dimensão do ambiente e a densidade
de objetos do ambiente de jogo. Podemos observar, que o esquema de divisão baseado
em grelha, possui sempre o máximo de número de nós possível apresentando assim, um
maior número de nós quando comparado com a quadtree. Os resultados apresentados
pela quadtree, mostram uma relação entre o número de nós e a dimensão do ambiente, e
o número de nós e a densidade de objetos.
Com base na interpretação dos resultados desta operação e partindo do pressuposto
que quanto maior o número de nós, maior o espaço de memória ocupado, a terceira
hipótese de investigação pode ser considerada como válida para os dois esquemas de
divisão do ambiente. Contudo, a quarta hipótese de investigação é apenas válida para a
quadtree.
A operação de quantização, é mais rápida no esquema de divisão baseado em
grelha, do que na quadtree. Esta diferença de valores pode ser explicada pela
implementação de cada uma destas estruturas.
Na grelha, a operação de quantização, é feita apenas através do cálculo de uma
função. A relação verificada entre o tempo de processamento e a dimensão do ambiente
pode ser explicada, com o aumento da grandeza dos id’s dos nós. Desta forma, à medida
que a grandeza dos id’s aumenta, aumenta também o tempo de processamento do
cálculo da função.
A operação de quantização na quadtree é também feita através do cálculo de uma
função, contudo é ainda necessário, verificar o nó responsável por esse id, o que pode
resultar numa procura na árvore da quadtree. Esta implementação pode ainda explicar a
relação inversa verificada do tempo de processamento e a dimensão do ambiente, e
ainda a densidade de objetos. Uma vez que, é possível que quanto maior o número de
nós na quadtree, menor é a procura na árvore da quadtree.
A primeira e quarta hipótese de investigação são válidas. Contudo, a segunda
hipótese não pode ser considerada como válida, uma vez que a grelha apresenta um
tempo de processamento inferior à quadtree. Relativamente à terceira hipótese esta é
válida apenas para a grelha.
133
A operação de localização apresenta um tempo de processamento menor para o
esquema de divisão baseado em grelha, quando comparado com a quadtree. Ambas as
operações são obtidas através do cálculo de funções, podemos então verificar, que a
função de localização da quadtree despende mais tempo de processamento na operação
de localização. É de realçar, que ambas as funções de cálculo da localização são
sensíveis à dimensão do ambiente. Esta relação poderá ser justificada, pelo aumenta da
grandeza do id nos ambientes de maior dimensão.
Relativamente às hipóteses de investigação realizadas, podemos assumir como
válidas a primeira e segunda hipótese. Contudo não é possível validar a segunda e
quarta hipótese de investigação.
Os resultados da operação de procura de caminho confirmam os dados dos autores
do algoritmo Fringe Search (Björnsson et al., 2005) . Este algoritmo, visita um maior
número de nós, expande um menor número de nós e é mais rápido quando comparado
com o algoritmo A*. Estes resultados confirmam também a sétima e oitava hipótese de
investigação.
No que diz respeito à nona e décima hipótese de investigação, ambas as hipóteses
são válidas uma vez que se verifica que ambos os algoritmos são sensíveis à dimensão
do ambiente e densidade de objetos no ambiente de jogo.
Quando comparamos o tempo de processamento despendido na procura de
caminho com o esquema de divisão, observa-se que o esquema baseado em gelha
apresenta um tempo de processamento maior na resolução de caminhos. Os resultados
obtidos podem ser explicados, pelo maior número de nós associados à representação do
ambiente baseado em grelha. Os resultados obtidos validam a décima primeira hipótese
de investigação.
A operação de conexão de vizinhos e operação de adição de objetos mostra que, o
esquema de divisão baseado em grelha, despende menos tempo a desempenhar estas
duas operações quando comparado com quadtree. Contudo, a diferença de valores é
bastante significativa e tende a ser mais díspar à medida que o número de nós aumenta,
quer pela dimensão do ambiente e quer pela densidade de objetos no ambiente de jogo.
Os dados recolhidos poderão ser justificados de forma similar à operação de adição
de objetos antes do início do jogo. Embora o processo de subdivisão da quadtree possa
estar ligado a um aumento do tempo de processamento, a comparação dos valores da
operação de conexão de vizinhos com a operação de adição de objeto (que envolve a
134
conexão de vizinhos), mostra que o maior consumo de tempo está associado à própria
conexão de vizinhos.
No que diz respeito às hipóteses de investigação traçadas, a primeira e sexta
hipótese são válidas para a grelha, contudo é apenas válida para a quadtree no caso de
ambientes de estáticos ou ambientes dinâmicos de pequena e média dimensão e com
uma densidade de objetos pequena ou média. A terceira e quarta hipótese de
investigação podem ser consideradas como válidas, contudo a segunda não.
No geral, é possível observar que o algoritmo Fringe Search possa de facto ser
considerado como uma boa alternativa ao algoritmo A*. Este algoritmo apresenta
melhores resultados de inicialização e de procura de caminho, quando comparado com o
A*.
No que diz respeito à representação do ambiente, verificamos que a quadtree possui
inúmeras vantagens, incluindo um tempo de processamento mais baixo na procura de
caminhos. Contudo, os resultados da operação de conexão de vizinhos fazem com que
esta estrutura não seja a melhor escolha em ambientes dinâmicos de grande dimensão.
Relativamente ao suporte de múltiplos agentes (hipótese de investigação 5),
verificamos que ambas as representações do ambiente e ambos os tipos de algoritmos de
procura podem ser usados. Contudo a hipótese de recorrer a uma threadpool para lidar
com os diversos pedidos de resolução de caminho, com vista à redução do tempo de
processamento, não se verifica. Os resultados obtidos a partir do modo de execução com
threadpool, mostra não haver nenhuma vantagem nesta abordagem, uma vez que os
resultados encontrados sem exceção mostram um tempo de processamento e consumo
de memória maior.
6.2 Conclusão
Neste trabalho, apresentamos um conjunto de técnicas que visam o suporte às
técnicas PCG, com o objetivo de concluir o processo de apoio ao movimento NPCs
sobre um cenário desconhecido. Este objetivo incluiu, não apenas a geração de mapas
de navegação em tempo de execução, mas também a identificação de caminhos no
mapa, e o controlo da locomoção de um NPC nesse caminho. Esta locomoção
controlada pretende lidar com eventos dinâmicos e inesperados que invalidem o
caminho escolhido, e solicitem que o sistema conceba novas soluções alternativas.
Acreditamos que as técnicas abordadas são fundamentais no processo de
construção e implantação de NPCs com vista ao aumento da longevidade e variedade
135
dos jogos de vídeo. Por outro lado, que os dados válidos recolhidos das diferentes
técnicas abordadas possam ser usados em outras investigações.
É da nossa opinião, que é impossível encontrar uma solução geral eficiente para
todas as situações. Contudo, esperamos que a solução desenvolvida possibilite melhorar
e facilitar a tarefa do designer, libertando-o da tarefa de fixar manualmente no cenário
de jogo todos os caminhos possíveis de navegação.
As abordagens futuras devem abordar este problema com soluções hibridas que
permitam por exemplo adaptar as técnicas utilizadas para o tamanho do ambiente de
jogo.
No que diz respeito aos objetivos iniciais traçados, todos os objetivos principais
foram alcançados, nomeadamente o desenvolvimento de uma solução que suportasse
múltiplos agentes, diversas dimensões de ambiente de jogo e suporte à deteção de
obstáculos estáticos e dinâmicos. Contudo, não foi possível alcançar nenhum dos
objetivos secundários devido à falta de tempo. Esta impossibilidade pode ser justificada
por dois fatores. O primeiro fator está associado a um planeamento inicial demasiado
otimista da solução problemática em questão. O segundo fator deve-se ao facto de um
dos autores do projeto ser trabalhador estudante, o que teve algum impacto no tempo
disponível no desenvolvimento do projeto e no cumprimento dos prazos.
6.3 Limitações
O presente estudo padece das seguintes limitações:
A implementação do cálculo do número de Morton, está limitado ao valor 65.536, o
que implica uma profundidade máxima da quadtree de 8 que equivale a 65.536 nós
folha;
Para simplificação de desenvolvimento, o processo de indexação da grelha está
limitado a números inteiros;
Apesar da implementação do algoritmo Fringe Search, ter sido baseado na
implementação do autor verificou-se diferenças no tamanho e custo do caminho
calculado quando comparado com o algoritmo A*.
Para a avaliação da memória, foi avaliada a memória antes e depois de cada
operação, não tendo sido realizadas medições intermédias. Este procedimento pode
ter contribuir para o enviesamento do estudo.
136
6.4 Trabalho futuro
Delineamos algumas possibilidades de trabalho futuro:
comparar os resultados obtidos da grelha, com outras topologias de abstração de
grelha.
invés de calcular o número de Morton, recorrer a matrizes pré-computadas com
vista à diminuição do tempo de processamento;
desenvolvimento de uma estrutura de dados hibrida entre grelha e quadtree, que
altere com base no número de nós à semelhança da estrutura de dados hybrid
dictonary na tecnologia .net. Procurando assim obter-se o melhor de dois mundos;
explorar mais eficientes de determinação de vizinhos na quadtree.
137
Bibliografia
Anguelov, B. (2011). Video Game Pathfinding and Improvements to Discrete Search on Grid-based
Maps. Pretoria. Retrieved from http://upetd.up.ac.za/thesis/submitted/etd-03022012-
094023/unrestricted/dissertation.pdf
Björnsson, Y., Enzenberger, M., Holte, R., & Schaeffer, J. (2005). Fringe Search Beating A* at
Pathfinding on Game Maps. In IEEE Symposium on Computational Intelligence and Games (pp.
125–132). IEEE. Retrieved from http://webdocs.cs.ualberta.ca/~holte/Publications/fringe.pdf
Borovikov, I. (2011). Navigation Graph Generation. gamedev.net: Artificial Intelligence, 1–17. Retrieved
from http://www.gamedev.net/page/resources/_/technical/artificial-intelligence/navigation-graph-
generation-r2805
Botea, A., Martin, M., Schaeffer, J., & Tg, C. (2004). Near Optimal Hierarchical Path-Finding. Journal of
Game Development, 1, 7–28.
Buckland, M. (2004). Programming Game AI by Example. Texas: Wordware Publishing Inc.,U.S.
Harabor, D. (2011). Graph Pruning and Symmetry Breaking On Grid Maps. In IJCAI’11 Proceedings of
the Twenty-Second international joint conference on Artificial Intelligence - Volume Volume Three
(pp. 2816–2817). Retrieved from
https://www.aaai.org/ocs/index.php/IJCAI/IJCAI11/paper/view/3236
Harabor, D., & Botea, A. (2008). Hierarchical path planning for multi-size agents in heterogeneous
environments. In 2008 IEEE Symposium On Computational Intelligence and Games (pp. 258–265).
IEEE. doi:10.1109/CIG.2008.5035648
Hirt, J., Gauggel, D., Hensler, J., Blaich, M., & Bittel, O. (2011). Using Quadtrees for Realtime
Pathfinding in Indoor Environments. In Research and Education in Robotics - EUROBOT 2010
Communications in Computer and Information Science Volume 156 (pp. 77–78). doi:10.1007/978-
3-642-27272-1_6
Kishimoto, A., & Artificial, K. (2004). Inteligência Artificial em Jogos Eletrônicos. Retrieved from
http://www.programadoresdejogos.com/trab_academicos/andre_kishimoto.pdf
Koefoed-hansen, A. (2012). Representations for Path Finding in Planar Environments. Aarhus
Universitet.
Kring, A., Champandard, A. J., & Samarin, N. (2010). DHPA * and SHPA *: Efficient Hierarchical
Pathfinding in Dynamic and Static Game Worlds. In Conference on Artificial Intelligence and
Interactive Digital Entertainment (AIIDE’10) (pp. 39–44).
138
Millington, I., & Funge, J. (2009). Artifical Intelligence For Games (2o ed.). Burlington: Morgan
Kaufmann Publishers.
Netto, M., Machado, S., Marcos, R., Pedro, R., & Nunes, L. (2006). Um estudo comparativo de
ferramentas para a criação de jogos educacionais baseados em realidade virtual. Instituto
Politécnico de Bragança.
Pedro, R., & Nunes, L. (2009). Motores para Desenvolvimento de Jogos Digitais. Instituto Politécnico de
Bragança.
Spronck, P., Ponsen, M., Sprinkhuizen-Kuyper, I., & Postma, E. (2006). Adaptive game AI with dynamic
scripting. Machine Learning, 63(3), 217–248. doi:10.1007/s10994-006-6205-6
Tozour, P. (2008). Why Waypoints Aren’t for Pathfinding. Retrieved from http://www.ai-
blog.net/archives/000152.html
Yahja, A., Stentz, A., Singh, S., & Brumitt, B. L. (1998). Framed-quadtree path planning for mobile
robots operating in sparse environments. In Proceedings. 1998 IEEE International Conference on
Robotics and Automation (Cat. No.98CH36146) (Vol. 1, pp. 650–655). IEEE.
doi:10.1109/ROBOT.1998.677046