estudo da aplicabilidade da opm para desenvolvimento de...
TRANSCRIPT
UNIVERSIDADE TECNOLÓGICA FEDERAL DO PARANÁ
DEPARTAMENTO ACADÊMICO DE INFORMÁTICA
CURSO DE BACHARELADO EM SISTEMAS DA INFORMAÇÃO
RODRIGO LUIZ KOVALSKI
Estudo da Aplicabilidade da OPM para Desenvolvimento de
Jogos Digitais
TRABALHO DE CONCLUSÃO DE CURSO
CURITIBA
2019
RODRIGO LUIZ KOVALSKI
Estudo da Aplicabilidade da OPM para Desenvolvimento de
Jogos Digitais
Trabalho de Conclusão de Curso de graduação,
apresentado à disciplina de Trabalho de Diplomação,
do Curso Superior de Bacharelado em Sistemas da
Informação do Departamento Acadêmico de
Informática - DAINF - da Universidade Tecnológica
Federal do Paraná - UTFPR, como requisito parcial
para obtenção do título de Bacharel em Sistemas da
Informação.
Orientador: Prof. Paulo Cézar Stadzisz
DAINF - Departamento Acadêmico de
Informática - UTFPR
CURITIBA
2019
Ministério da Educação UNIVERSIDADE TECNOLÓGICA FEDERAL DO PARANÁ
Câmpus Curitiba
Diretoria de Graduação e Educação Profissional Departamento Acadêmico de Informática
Coordenação do Curso de Bacharelado em Sistemas de Informação
TERMO DE APROVAÇÃO
ESTUDO DA APLICABILIDADE DA OPM PARA DESENVOLVIMENTO DE JOGOS DIGITAIS
por
Rodrigo Luiz Kovalski
Este Trabalho de Conclusão de Curso foi apresentado no dia 29 de novembro de 2019 como
requisito parcial à obtenção do grau de Bacharel em Sistemas de Informação na Universidade
Tecnológica Federal do Paraná - UTFPR - Câmpus Curitiba. O(a)(s) aluno(a)(s) foi(ram) arguido(a)(s)
pelos membros da Banca de Avaliação abaixo assinados. Após deliberação a Banca de Avaliação
considerou o trabalho ________________________________________.
________________________________
Paulo Cézar Stadzisz
(Presidente - UTFPR/Curitiba)
________________________________
Mariângela de Oliveira Gomes Setti
(Avaliador(a) 1 - <Instituição>)
________________________________
Rita Cristina Galarraga Berardi
(Avaliador 2(a) - Instituição)
________________________________
Profa. Leyza Baldo Dorini
(Professora Responsável pelo TCC – UTFPR/Curitiba)
_____________________________
Prof. Marcelo Mikosz Gonçalves
(Coordenadordo curso de Bacharelado em
Sistemas de Informação – UTFPR/Curitiba)
―A Folha de Aprovação assinada encontra-se na Coordenação do Curso.‖
À minha família, por sua capacidade de acreditar em mim е investir em
mim, a todos os professores do curso, em especial ao professor Paulo
Cézar Stadzisz, pela paciência na orientação е todo o apoio que
tornaram possível а conclusão desta monografia, aos amigos е colegas,
pelo incentivo е pela parceria e a todos aqueles que de alguma forma
estiveram е estão próximos de mim, fazendo esta vida valer cada vez
mais а pena.
RESUMO
KOVALSKI, Rodrigo Luiz. Estudo da Aplicabilidade da OPM para Desenvolvimento de Jogos
Digitais. x f. TCC (Curso de Bacharelado em Sistema da Informação), Universidade
Tecnológica Federal do Paraná. Curitiba, 2019
Assim como qualquer software, os jogos digitais também podem ser desenvolvidos com
auxílio de métodos para modelagem de sistemas. Buscar aplicar novas técnicas é essencial
para o desenvolvimento de software, uma vez que o mercado de jogos digitais está em
grande crescimento. Novas abordagens podem proporcionar agilidade no desenvolvimento e
melhoria da qualidade do software. Há diversos estudos sobre modelagens para o
desenvolvimento de jogos, mostrando um grande interesse da comunidade em aplicar estes
métodos. A Metodologia Objeto-Processo (OPM), desenvolvida por Dori (1995), é uma nova
abordagem para concepção de sistemas que preconiza combinar a abordagem clássica de
modelagem orientada a processos com técnicas de modelagem orientada a objetos. Foram
desenvolvidos dois jogos digitais. O primeiro foi modelado com UML e OPM para estudar a
aplicação e fazer uma comparação entre as duas modelagens. O segundo jogo foi
desenvolvido com a OPM, com objetivo de investigar a aplicação em um software mais
complexo. A OPM se mostrou apropriada para a modelagem de jogos digitais. Em
comparação com a UML, a OPM demonstrou ser uma alternativa favorável. Foram propostas
nove orientações para auxiliar a modelagem OPM em um jogo digital.
Palavras-chave: Metodologia Objeto-Processo, jogos digitais, modelagem conceitual.
LISTA DE FIGURAS
Figura 1 - Conceitos básicos da OPM ....................................................................................... 17
Figura 2 - Características dos objetos e processos ................................................................... 18
Figura 3 - Relações Estruturais da OPM ................................................................................... 18
Figura 4 - Relações Processuais da OPM ................................................................................. 19
Figura 5 - Exemplo de interface do programa OPCAT .............................................................. 20
Figura 6 - Metamodelo OPM de nível superior de Tomada de Decisão (OPD) ......................... 21
Figura 7 - OPD do processo de tomada de decisão em zoom .................................................. 22
Figura 8 – Exemplo de interface da game engine Unity3D ........................................................ 23
Figura 9 - Tela inicial do "Square Overflow" .............................................................................. 25
Figura 10 - Exemplo de novo nível do jogo "Square Overflow".................................................. 26
Figura 11 - Exemplo de execução de um nível do jogo "Square Overflow" ............................... 27
Figura 12 – Tela contento o botão ―Próximo nível― do jogo "Square Overflow" ......................... 27
Figura 13 - Tela ―Fim de Jogo‖ do jogo "Square Overflow" ........................................................ 28
Figura 14 - Diagrama de Casos de Uso ―Square Overflow‖. ...................................................... 30
Figura 15 - Diagrama de Classes ―Square Overflow‖ ................................................................ 32
Figura 16 - Diagrama de Sequência ―Iniciar uma nova partida‖ do jogo ―Square Overflow". ..... 33
Figura 17 - Diagrama de Sequência ―NextLevel‖ do jogo ―Square Overflow" ............................ 34
Figura 18 - Diagrama de Sequência ―Selecionar quadrados‖ do jogo ―Square Overflow". ........ 35
Figura 19 - Diagrama de Sequência ―countPoint‖ do jogo ―Square Overflow" ........................... 35
Figura 20 - Diagrama de Sequência ―countError‖ do jogo ―Square Overflow" ........................... 36
Figura 21 - Diagrama de Sequência ―Avançar nível‖ do jogo ―Square Overflow". ..................... 36
Figura 22 - Diagrama de Sequência ―Sair do jogo‖ do jogo ―Square Overflow‖ ......................... 37
Figura 23 - Diagrama de Sequência ―Ouvir música‖ do jogo ―Square Overflow‖ ....................... 38
Figura 24 – Diagrama de Comunicação ―Iniciar nova partida‖ do jogo ―Square Overflow‖ ........ 39
Figura 25 - Diagrama de Comunicação ―Selecionar quadrados‖ do jogo ―Square Overflow‖ .... 40
Figura 26 - Diagrama de Comunicação ―Avançar nível‖ do jogo ―Square Overflow‖ ................. 40
Figura 27 - Diagrama de Comunicação ―Sair do jogo‖ do jogo ―Square Overflow‖ .................... 41
Figura 28 - Diagrama de Comunicação ―Ouvir música‖ do jogo ―Square Overflow‖ .................. 41
Figura 29 - Diagrama de Estado ―PlayButton‖ do jogo ―Square Overflow‖ ................................. 42
Figura 30 - Diagrama de Estado ―SquareButton‖ do jogo ―Square Overflow‖ ............................ 43
Figura 31 - Diagrama de Estado ―NextLevelButton‖ do jogo ―Square Overflow‖ ........................ 43
Figura 32 - Diagrama de Estado ―GameManager‖ do jogo ―Square Overflow‖ .......................... 44
Figura 33 - Diagrama de Estado ―ExitGameButton‖ do jogo ―Square Overflow‖ ........................ 45
Figura 34 - Diagramas de Estado dos elementos da tela do jogo ―Square Overflow‖ ............... 46
Figura 35 - Diagramas de Estado dos elementos da tela do jogo ―Square Overflow‖ ............... 46
Figura 36 – Diagrama principal do jogo ―Square Overflow‖ ....................................................... 47
Figura 37 - Diagrama ―Iniciando nova partida in-zoomed‖ do jogo ―Square Overflow‖ .............. 48
Figura 38 - Diagrama ―Gerenciando nível in-zoomed‖ do jogo ―Square Overflow‖. ................... 50
Figura 39 - Diagrama ―Inicializando quadrado in-zoomed‖ do jogo ―Square Overflow‖.............. 51
Figura 40 - Diagrama ―Atualizando tela in-zoomed‖ do jogo ―Square Overflow‖. ....................... 52
Figura 41 - Diagrama ―Selecionando quadrados in-zoomed‖ do jogo ―Square Overflow‖. ......... 53
Figura 42 - Diagrama ―Contando pontos in-zoomed‖ do jogo ―Square Overflow‖ ...................... 55
Figura 43 - Diagrama ―Contando erros in-zoomed‖ do jogo ―Square Overflow‖ ......................... 56
Figura 44 - Diagrama ―Avançando nível in-zoomed‖ do jogo ―Square Overflow‖ ....................... 57
Figura 45 - Diagrama ―Saindo do jogo in-zoomed‖ do jogo ―Square Overflow‖ ......................... 58
Figura 46 - Tela inicial do jogo "Blinky" ...................................................................................... 65
Figura 47 - Tela de Tutorial do jogo ―Blinky‖ .............................................................................. 65
Figura 48 - Tela de exemplo do jogo ―Blinky‖ mostrando um coelho seguindo o ―Blinky‖ .......... 66
Figura 49 - Tela de exemplo do jogo ―Blinky‖ mostrando o Mágico encontrando o "Blinky" ...... 67
Figura 50 – Tela de exemplo do jogo ―Blinky‖ mostrando a porta de reaparecimento ............... 67
Figura 51 – Diagrama principal do jogo ―Blinky" ........................................................................ 70
Figura 52 - Diagrama ―Iniciando partida" do jogo ―Blinky" .......................................................... 72
Figura 53 - Diagrama ―Movimentando Blinky" do jogo ―Blinky" .................................................. 73
Figura 54 - Diagrama ―Pulando" do jogo ―Blinky" ....................................................................... 73
Figura 55 - Diagrama ―Movimentando na horizontal" do jogo ―Blinky" ....................................... 74
Figura 56 - Diagrama ―Pegando coelho" do jogo ―Blinky" .......................................................... 75
Figura 57 - Diagrama ―Salvando coelho" do jogo ―Blinky" ......................................................... 76
Figura 58 - Diagrama ―Pegando caixa" do jogo ―Blinky" ............................................................ 77
Figura 59 - Diagrama ―Arremessando caixa" do jogo ―Blinky" ................................................... 78
Figura 60 - Diagrama ―Matando Mágico" do jogo ―Blinky" ......................................................... 79
Figura 61 - Diagrama ―Morrendo" do jogo ―Blinky" ..................................................................... 80
Figura 62 - Diagrama ―Movimentando Mágico in-zoomed" do jogo ―Blinky" .............................. 81
Figura 63 - Diagrama ―Matando Blinky" do jogo ―Blinky‖ ........................................................... 82
Figura 64 - Hierarquia dos diagramas do jogo "Blinky" .............................................................. 84
Figura 65 – Diagrama ―Criando cenário‖ .................................................................................... 86
Figura 66 – Diagrama ―Estados do Baú‖ .................................................................................... 87
Figura 67 – Diagrama ―Movimentando personagem para frente‖ .............................................. 88
Figura 68 – Diagrama ―Comprando item‖ .................................................................................. 90
Figura 69 – Diagrama de um modelo funcional de jogo digital genérico .................................... 91
LISTA DE TABELAS E QUADROS
Tabela 1 - Requisitos funcionais e não funcionais do jogo ―Square Overflow‖ ...................... 29
Tabela 2 - Quantidade de diagramas produzidos para o jogo ―Square Overflow‖ ................. 60
LISTA DE ABREVIATURAS E SIGLAS
CASE - Computer-Aided Software Engineering
GWP - Game Waterfall process
GUP - Game Unified Process
OPD - Object-Process Diagram
OPL - Object-Process Language
OPM - Object Process Methodology
OPCAT - Object-Process CASE Tool
UML - Unified Modeling Language
UTFPR – Universidade Tecnológica Federal do Paraná
XGD - eXtreme Game Development
SUMÁRIO
1. INTRODUÇÃO ............................................................................................................ 11
1.1. Contexto do trabalho ................................................................................................... 11
1.2. Objetivos do Trabalho ................................................................................................. 12
1.2.1. Objetivo Geral ............................................................................................................. 12
1.2.2. Objetivos Específicos .................................................................................................. 13
1.2.3. Estrutura do Trabalho .................................................................................................. 13
2. FUNDAMENTAÇÃO TEÓRICA .................................................................................. 14
2.1. Metodologias utilizadas em desenvolvimento de jogos ............................................... 14
2.2. Metodologia Objeto-Processo ..................................................................................... 16
3. APLICAÇÃO DA UML E DA OPM EM UM JOGO DIGITAL ...................................... 25
3.1. Descrição do jogo ―Square Overflow‖ .......................................................................... 25
3.2. Requisitos do software ―Square Overflow‖ .................................................................. 28
3.3. Modelagem UML do jogo ―Square Overflow‖ .............................................................. 29
3.4. Modelagem OPM do jogo ―Square Overflow‖ .............................................................. 47
3.5. Programação do jogo ―Square Overflow‖ .................................................................... 58
3.6. Discussão sobre o jogo ―Square Overflow‖ ................................................................. 59
3.7. Discussão sobre a aplicação a UML e a OPM em um jogo digital .............................. 60
4. INVESTIGAÇÃO DA APLICAÇÃO DA UML E DA OPM EM JOGOS DIGITAIS ....... 62
5. SEGUNDA APLICAÇÃO DA OPM EM UM JOGO DIGITAL ..................................... 64
5.1. Descrição do jogo ―Blinky‖ ........................................................................................... 64
5.2. Requisitos do jogo ―Blinky‖ .......................................................................................... 68
5.3. Modelagem OPM do jogo ―Blinky‖ ............................................................................... 70
5.4. Programação do jogo ―Blinky‖ ..................................................................................... 83
5.5. Discussão sobre o jogo ―Blinky‖ .................................................................................. 83
6. PROPOSTA DE ORIENTAÇÕES SOBRE A OPM EM JOGOS DIGITAIS ................ 85
7. CONCLUSÃO E CONSIDERAÇÕES FINAIS ............................................................. 93
8. REFERÊNCIAS ........................................................................................................... 95
9. APÊNDICE A – CÓDIGOS DOS SCRIPTS DO JOGO ―SQUARE OVERFLOW‖ ... 101
10. APÊNDICE B – CÓDIGOS DOS SCRIPTS DO JOGO ―BLINKY‖ ........................... 105
11
1. INTRODUÇÃO
1.1. Contexto do trabalho
O mercado de jogos digitais evoluiu significativamente desde as suas origens nos
salões de diversões do final dos anos 70 e início dos 80, particularmente graças à
Internet, às experiências online com vários jogadores e aos jogos móveis e sociais. As
diversas maneiras pelas quais os videogames estão sendo utilizados vêm atraindo grande
variedade de consumidores. Por exemplo, o mercado norte-americano espera alcançar
um crescimento de 3,6% ao ano a partir de agosto de 2015, totalizando 20,3 bilhões até
2020, superando o esperado crescimento em outros produtos de entretenimento, como
TV, cinema e música. Evidências recentes mostram que, em torno de metade dos adultos
norte-americanos se envolvem com videogames de alguma forma (Kaimann, D., Stroh‐
Maraun, N., e Cox, J, 2018).
Uma grande evolução nas tecnologias e processos de desenvolvimento de jogos
ocorreu desde seus primeiros dias. O crescimento das exigências dos consumidores, as
complexidades técnicas e estéticas, bem como as fontes investidas no desenvolvimento
de jogos digitais, sensibilizaram para a importância do uso de conceitos de Engenharia de
Software e de linguagens de alto nível para o desenvolvimento de jogos (Furtado, 2012).
O que começou como uma indústria artesanal tornou-se uma indústria que as grandes
operações corporativas dominam atualmente (Flynt, 2005).
A produção de jogos geralmente envolve alguns dos mais complexos esforços de
desenvolvimento de software. Pode não ser possível realizar tais esforços sem
planejamento extensivo. Além disso, é um problema sustentar esses esforços sem
atenção aos processos de desenvolvimento (Flynt, 2005).
A distinção entre jogos e outras categorias de software é que, nos jogos, os grupos
de desenvolvimento consistem em pessoas com diferentes áreas de especialização. A
equipe de desenvolvimento de jogos pode ser formada por:
● Roteirista: responsável por escrever o script do jogo e o papel conceitual do jogo;
● Game Designer: responsável por converter o conceito em documento de projeto, que
será o guia para o desenvolvimento do projeto;
● Programadores: podem-se envolver programadores com diversas áreas, habilidades
e conhecimentos, tais como programadores de Engine e de gráficos, programadores de
12
inteligência artificial e programadores de frameworks.
● Músicos: são os responsáveis pela programação do som e efeitos sonoros;
● Artistas: podem-se ter artistas de personagens, modeladores 3D e os artistas de
texturas;
● Testadores: são os responsáveis por encontrar bugs e fazer sugestões para
mudanças na jogabilidade, gráficos e da história.
Equipes com integrantes contendo papéis diversificados, como os descritos na lista,
não costumam estar necessariamente relacionados à complexidade do projeto em si, pois
é comum no desenvolvimento dos jogos digitais que as equipes possuam perfis
direcionados para funções específicas. (Ampatzoglou e Chatzigeorgiou, 2007).
Assim como qualquer software, os jogos digitais também podem ser desenvolvidos
com auxílio de metodologias para modelagem de sistemas (Demachy 2003, Tenzer e
Stevens 2007, Tenzer 2004, Barros 2007, Furtado 2012, Ampatzoglou e Chatzigeorgiou
2007, Bethke 2003, Flynt 2005, Lima 2013, Alves e Santos 2015). Buscar aplicar novas
técnicas é essencial para desenvolvimento de software, uma vez que o mercado de jogos
digitais está em pleno crescimento e novas abordagens podem proporcionar agilidade no
desenvolvimento e melhoria da qualidade do software (Furtado, 2012).
O uso de modelagem de software, como por exemplo, a UML, é uma prática
sugerida na literatura e consagrada em algumas metodologias de desenvolvimento de
software que não é comumente aplicada a empresas de jogos. O não uso da UML se dá
principalmente pela abordagem ágil usada em vários projetos e pela própria deficiência no
modelo UML, quando utilizado para a modelagem de jogos (Barros, 2007).
Assim, o desenvolvimento de software de jogos digitais ainda carece de métodos de
modelagem compatíveis com as necessidades deste tipo de software. Uma vez que a
UML não demonstrou ser uma opção notória para os desenvolvedores de jogos, outras
opções, como a OPM, poderiam ser exploradas para este fim.
1.2. Objetivos do Trabalho
1.2.1. Objetivo Geral
O objetivo geral deste trabalho é investigar e propor a aplicabilidade da Metodologia
Objeto-Processo (OPM) como forma de substituir a linguagem UML, que seria a
linguagem de referência no desenvolvimento tradicional de jogos digitais. A intenção com
13
este estudo é investigar como a aplicação da OPM se comporta em um projeto de jogo
digital.
1.2.2. Objetivos Específicos
Os objetivos específicos deste trabalho, associados ao objetivo geral, são:
● Correlacionar as características e alternativas de modelagem da OPM no
desenvolvimento de jogos digitais com outras abordagens de modelagem, notadamente a
UML;
● Investigar a aplicabilidade da UML e da OPM no contexto de jogos digitais;
● Propor um conjunto de orientações para uso geral da OPM na modelagem de
software de jogos digitais.
1.2.3. Estrutura do Trabalho
Primeiramente, no capítulo 2 este documento irá abordar as metodologias que são
atualmente referenciadas em desenvolvimento de jogos e a descrição da Metodologia
Objeto-Processo. O capítulo 3 aborda a aplicação de um jogo digital a partir da UML e a
OPM. O capítulo 4 se refere a uma breve investigação da aplicação da UML e da OPM
em jogos digitais. O capítulo 5 trata-se do desenvolvimento de outro jogo, mais complexo,
utilizando a OPM. O capítulo 6 se refere a uma proposta de orientações de modelagem de
jogos digitais utilizando a OPM. Por último, no capítulo 7, são feitas as considerações
finais e conclusão do projeto.
14
2. FUNDAMENTAÇÃO TEÓRICA
Para fundamentar o trabalho foi realizada uma pesquisa sobre as metodologias
utilizadas para desenvolvimento de jogos e sobre a Metodologia Objeto-Processo,
descritos neste capítulo.
2.1. Metodologias utilizadas em desenvolvimento de jogos
Historicamente, a indústria de jogos digitais, desde seu início, enfrentou desafios e
cenários únicos, assim tornando o desenvolvimento de jogos um domínio peculiar
comparado ao software em geral. As primeiras produções de jogos ignoravam
importantes conceitos de engenharia de software e objetivos de projeto, como reutilização
e modularidade. Por vários anos a forma de desenvolver jogos foi caracterizada pela falta
de um processo organizado (Furtado, 2012).
As empresas do ramo de jogos eletrônicos enfrentam dificuldades em desenvolver
jogos com alta tecnologia. Os principais motivos são a evolução rápida da tecnologia e o
destaque que essa indústria vem ganhando nos últimos anos (Fabichak, 2009). O
crescimento das demandas dos consumidores, a complexidade técnica e estética, bem
como os recursos investidos no desenvolvimento de jogos digitais, foram os principais
fatores que levaram a refletir sobre como é importante o uso de conceitos de Engenharia
de Software e linguagens de alto nível para o desenvolvimento de jogos (Furtado, 2012).
A tecnologia está em constante transformação e, deste modo, é preciso analisar as
transformações e desenvolver projetos que atendam a todos os requisitos em um curto
prazo de tempo. O risco de se construir um jogo ruim, não aceito e não comercial,
causaria prejuízos. A fim de minimizar esses impactos, surgem necessidades de se
utilizar metodologias para o desenvolvimento de jogos. Essas metodologias, por força das
adaptações, também devem sofrer alterações para se ajustarem às demandas e às
tecnologias presentes (Hamada, 2015).
Atualmente, existem diversas metodologias adaptadas para desenvolvimento de
jogos, algumas delas descritas detalhadamente por Flynt (2005), em seu livro ―Software
Engineering for Game Developers‖. Algumas delas metodologias são: o Modelo GWP
(Game Waterfall Process), Modelo XGD (eXtreme Game Development) e Modelo GUP
(Game Unified Process).
15
O modelo GWP é uma versão similar à versão tradicional de desenvolvimento de
sistemas com o processo Cascata. O nome Cascata se dá pela característica que as
fases seguem um único sentido. Este modelo, por ser pouco flexível, pode acumular
vários erros durante o processo de desenvolvimento.
O Modelo XGD é um modelo adaptado do Extreme Programming (XP), que é um
modelo ágil desenvolvido para programadores. O XGD realiza algumas adaptações para
funcionar com os demais papéis da equipe de desenvolvimento de jogos (Demachy,
2017).
O modelo GUP é baseado na junção dos modelos Extreme Programming e Rational
Unified Process (RUP). O modelo mescla iterações curtas do XP e iterações longas do
RUP de forma mais adequada para cada papel na produção (Flood, 2013).
O Scrum e o Game Scrum são citados pelo autor Carvalho (2013). O Scrum é um
processo ágil, iterativo e incremental que foca na aceitação das mudanças que podem
ocorrer, principalmente em contextos pouco definidos. O Game Scrum é uma adaptação
do ciclo de vida do desenvolvimento clássico de jogos para um contexto ágil.
Para ilustrar melhor o contexto do mercado de jogos, os dados da pesquisa
brasileira ―1o Censo da indústria brasileira de jogos digitais‖ indicaram que a maioria das
empresas prefere utilizar métodos ágeis, sendo o Scrum (60%) o mais utilizado. Alguns
métodos tradicionais (Cascata 4,5% e Project Management Body of Knowledge 11,3%)
também foram citados. A porcentagem de respondentes que declararam não utilizar
nenhuma metodologia foi de 25,6%. Outras metodologias citadas na pesquisa foram
Agile, Desenvolvimento Ágil, Design Card Game (DCG), Feature Driven Development
(FDD), Design Centrado no ser Humano (HCD) e Mapas Mentais. Algumas empresas
também citaram que utilizam ferramentas modificadas do Scrum (BNDES, 2014).
Diversos autores de artigos e livros sobre a área de Engenharia de Software para
desenvolvimento de jogos citam o uso da UML (Unified Modeling Language) como
ferramenta útil para auxiliar o desenvolvimento do projeto de jogos (Demachy 2003,
Tenzer e Stevens 2007, Tenzer 2004, Barros 2007, Furtado 2012, Ampatzoglou e
Chatzigeorgiou 2007, Bethke 2003, Flynt 2005, Lima 2013, Alves e Santos 2015).
A UML (Unified Modelling Language - Linguagem de Modelagem Unificada) surgiu
da união de linguagens anteriores para análise e projeto de sistemas orientados a objetos
e, em 1997, passou a ser aceita e reconhecida como um padrão potencial de notação
para modelagem de múltiplas perspectivas de sistemas de informações pela OMG
("Object Management Group") (Costa, 2001).
16
A UML define um conjunto básico de diagramas e notações que permitem
representar as múltiplas perspectivas do sistema sobre análise e desenvolvimento. Dentre
os diagramas podem ser citados: Diagramas de Casos de Uso, Diagramas de Classes,
Diagramas de Interações (Sequência ou Colaboração), Diagramas de Atividades e
Diagramas de Estado e Transição (Costa, 2001).
A utilização da UML para o design de jogos melhora a comunicação entre os
designers de jogos e programadores e pode ser útil também para lidar com artistas e na
gestão (Demachy, 2003). A UML é uma prática sugerida na literatura e consagrada em
algumas metodologias de desenvolvimento de software, mas não é comumente aplicada
em empresas de jogos. O não uso da UML se dá, principalmente, pela característica ágil
de vários desses projetos e pela própria deficiência no modelo, quando utilizado para a
modelagem de jogos (Barros, 2007). Os autores Reinhartz-Berger, Iris e Dori (2014), em
um comparativo da UML com a OPM, apontam detalhadamente a deficiência da UML. No
contexto de jogos, a UML demanda muito tempo e seus diagramas podem não estar
consistentes.
Como foi citada, nos parágrafos anteriores, a modelagem UML é recomendada em
desenvolvimento de jogos, com as devidas considerações. No próximo capítulo será
descrita a Modelagem Objeto Processo e como ela pode ser utilizada em substituição da
modelagem UML. Assim, justifica-se a OPM como uma opção em desenvolvimento de
jogos digitais.
2.2. Metodologia Objeto-Processo
Um projeto arquitetônico de software ideal deve produzir um modelo de software que
aperfeiçoa os requisitos funcionais e não funcionais, frequentemente conflitantes, de
problemas do mundo real. A grande escala e a complexidade de projetos de software
modernos resultam em desafios extremamente difíceis para designers de arquitetura de
software (Lui e Glunch 2004). A linguagem de modelagem utilizada fornece a base para
especificar o sistema desejado. Se essa linguagem não for muito técnica, ela pode facilitar
a comunicação entre desenvolvedores de sistemas e clientes corporativos e fornece uma
base para uma documentação de alta qualidade (Sturm, Dori e Sheohory, 2010). O
modelo conceitual descreve a funcionalidade do sistema a ser desenvolvido, define os
limites do sistema, sua relação com o ambiente e sua arquitetura de alto nível. Ele auxilia
17
a compor a base para a compreensão do nível do sistema pelas diferentes partes
interessadas, tais como gerentes de engenharia de sistemas, gerentes de projeto,
arquitetos e equipes multidisciplinares que realizam o projeto (Perelman, 2011).
A Metodologia Objeto-Processo é uma nova abordagem à modelagem de sistemas
que preconiza combinar a abordagem clássica de modelagem orientada a processos com
técnicas de modelagem orientada a objetos. A OPM se aplica à modelagem de qualquer
tipo de sistema (físico ou lógico) não orientado a software unicamente. Ao longo dos anos,
a OPM evoluiu para uma metodologia de ciclo de vida completo. Sua abordagem de
modelagem única é a principal característica que atrai pesquisadores e desenvolvedores.
O ponto forte da OPM reside no fato de que apenas um tipo de diagrama é usado para
modelar a estrutura, função e comportamento do sistema. Essa abordagem de modelo
único evita os problemas associados à multiplicidade do modelo, entretanto o modelo que
é produzido pode ser mais complexo e difícil de entender (Ramsin e Paige, 2008).
OPM é um método de modelagem integrado que unifica a função do sistema,
estrutura e comportamento dentro de um quadro de referência. Os blocos de construção
do OPM são objetos, processos, estados e links estruturais e comportamentais que são
ilustrados na Figura 1 (Reinhartz-Berger et al. 2002, Dori 2010, Mordecai e Dori 2014).
Fonte: Traduzido de Mordecai e Dori (2014).
Na OPM, um objeto é uma coisa que existe, ou pode existir, ―fisicamente‖ ou
―informaticamente‖. Os objetos podem conter estados, de tal forma que em cada ponto no
tempo, o objeto está em um de seus estados ou em transição entre estados durante a
execução de um processo. Um processo é uma ―coisa‖ (termo utilizado pela OPM) que
transforma um objeto criando-o ou consumindo-o ou alterando seu estado.
Figura 1 - Conceitos básicos da OPM
18
Figura 2 - Características dos objetos e processos
Fonte: autoria própria.
Os objetos e processos têm características específicas quanto a sua essência, que é
física (com sombreado) ou informática (sem sombreado). Os objetos e processos contêm
um tipo de ―afiliação‖ que pode ser ambiental (contorno contínuo) ou sistêmica (contorno
tracejado). A representação para cada caso está representada na Figura 2.
Os processos e objetos podem compreender outros processos e objetos. Os estados
podem caracterizar objetos. As relações entre estes elementos são expressas por várias
ligações. As ligações estruturais, mostradas na Figura 3, suportam a descrição dos
aspectos do modelo estático.
Figura 3 - Relações Estruturais da OPM
Fonte: Traduzido de Mordecai e Dori (2014).
O triângulo do topo da imagem, que possui um triângulo menor dentro dele, exibe os
objetos e processos que estão relacionados como características daquele objeto. Um
exemplo seria um atributo ―Cor azul‖ de um objeto ―Bola‖, sendo que, removendo-o ou
trocando-o, o objeto ―Bola‖ ainda continua existindo. O triângulo sem preenchimento
19
ilustra os processos/objetos especializados de um processo/objeto generalizado. Um
exemplo seria um objeto ―Bola de futebol‖ que, além de ser também um objeto ―Bola‖,
pode possuir outras características. O triângulo todo preenchido demonstra os objetos
que são componentes ou partes de outro objeto. Um exemplo seria um objeto ―Motor‖ que
é parte de um objeto ―Carro‖, onde sua existência é necessária para que um objeto
―Carro‖ esteja completo.
As ligações processuais, mostradas na Figura 4, suportam as relações processuais,
dinâmicas e de causalidades (Mordecai e Dori 2014). O processo, quando não decorre de
outro processo, ocorre apenas na presença de um objeto específico e este podendo ser
em estados específicos. Processo como saída pode criar um objeto, alterar o estado de
um objeto ou chamar outro processo.
Os processos transformam objetos criando-os, consumindo-os ou alterando seus
estados. A representação simultânea de estrutura e comportamento no mesmo tipo de
diagrama é equilibrada, criando sinergia em que cada aspecto ajuda a compreender o
outro (Lui e Glunch 2004, Dori 2010).
Figura 4 - Relações Processuais da OPM
Fonte: traduzido de Mordecai e Dori (2014).
As visualizações integradas da OPM combinam as características estruturais,
funcionais e comportamentais em um modelo. Nesta integração, a responsabilidade e os
papéis de todas as entidades são claramente especificados e autodocumentados (Lui e
20
Glunch 2004). O desdobramento define relações estruturais entre o objeto ou processo
principal e objetos e processos de nível inferior. Para processos, pode-se emergir ou
imergir os detalhes. Essa característica é chamada in-zooming e permite definir uma
ordem de execução cronológica parcial dos subprocessos incluídos (Perelman, 2011). A
OPM é adequada tanto para a análise, quanto para a concepção do sistema, permitindo
uma transição suave entre estas fases (Peleg e Dori, 1999).
Além da OPM, Dori também desenvolveu a Object-Process CASE (Computer-Aided
Software Engineering) Tool (OPCAT), ferramenta que suporta os Object-Process
Diagrams (OPD) e uma representação textual equivalente, denominada Object-Process
Language (OPL). Tanto o OPD quanto a OPL fazem parte da metodologia (Lui e Glunch
2004, Dori 2010).
Fonte: Dori et al (2010).
A interface gráfica e textual combinada do OPCAT foi projetada para tirar vantagem
das habilidades de linguagem natural e intuição gráfica. Um usuário do OPCAT pode
esboçar sua ideia no OPD e depois verificar se as especificações textuais da OPL
correspondem à sua intenção (Lui e Glunch 2004). A tradução de um OPD definido para o
script OPL correspondente e vice-versa é feito automaticamente, de modo que o designer
Figura 5 - Exemplo de interface do programa OPCAT
21
pode trabalhar de forma intercambiável na versão gráfica ou textual da especificação
(Reinhartz-Berger et al. 2002). O recurso de zoom permite aos projetistas escolher o nível
de granularidade e compreender os designs OPM, de abstrações de alto nível até
apresentações detalhadas de mais baixo nível (Lui e Glunch 2004).
Para a modelagem OPM dos jogos foi utilizada a ferramenta OPCAT versão 4.0
(OPCAT Systems, 2011). A escolha da OPCAT deve-se ao fato de que é uma ferramenta
gratuita e foi criada justamente com o propósito de auxiliar a modelagem Objeto-
Processo. A Figura 5 ilustra um exemplo de interface do programa OPCAT. O quadro
nomeado ―SD‖ contém o Diagrama Objeto-Processo e abaixo dele temos outro quadro,
com a Linguagem Objeto-Processo, que descreve o diagrama. A Linguagem Objeto-
Processo é gerada automaticamente conforme é construído o diagrama.
A metodologia Objeto-Processo, descrita por Dori (2002), foi aplicada em várias
propostas, como modelagem de Enterprise Resource Planning (Soffer et al, 2005),
sistema em tempo real (Peleg e Dori, 1999), transações de cartões de crédito (Dori,
2001), como ferramenta de modelagem de negócios (Dori, 2000) e especificação de
algoritmos (Wenyin e Dori, 1999).
Figura 6 - Metamodelo OPM de nível superior de Tomada de Decisão (OPD)
Fonte: traduzido de Mordecai e Dori (2014).
Como forma de exemplo, o trabalho ―Conceptual Modeling of System-Based
Decision-Making‖ de Mordecai, Yaniv e Dori (2014), descreve uma aplicação da OPM. A
Figura 6 descreve um metamodelo OPM de nível superior de tomada de decisão (OPD) e
a Figura 7 descreve OPD do processo de ―Tomar Decisão‖ em zoom. Comparando as
22
figuras 6 e 7 podemos ver como o zooming funciona na maneira de exibição do processo.
Na Figura 6 o processo ―Tomada de Decisão‖ está abstraído (zoom-out) e na Figura 7 o
mesmo processo está ampliado (zoom-in), mostrando de forma mais detalhada que o
processo consiste de subprocessos e o relacionamento entre eles.
Na Figura 6, interpreta-se que o processo de ―Tomar Decisão‖ é um método do
―Agente Decisor‖, um ―Conjunto de Decisores‖ controla o processo de ―Tomar Decisão‖ e
isso só ocorre com a presença de um ―Modelo de Decisão‖ e de um conjunto de
―Variáveis de Estados‖. O processo de ―Tomar Decisão‖ afeta o ―Conjunto de Variáveis de
Decisão‖.
A Figura 7 apresenta o detalhamento do processo ―Tomar Decisão‖, que embora
possua maior especificação da interação dos objetos e processos, as informações da
Figura 6 permanecem representadas. Na Figura 7 têm-se vários subprocessos, que estão
representados um abaixo do outro. Essa representação é uma característica da
modelagem OPM na qual a representação vertical, indica que os processos situados no
topo ocorrem primeiro e em seguida os situados logo abaixo. Já os processos lado a lado
ocorrem simultaneamente.
Figura 7 - OPD do processo de tomada de decisão em zoom
Fonte: traduzido de Mordecai e Dori (2014)
23
Os modelos de interação entre os elementos que compõem os diagramas da OPM
(13 no total) são em menor número do que os da UML. A UML tem 14 tipos de diagramas
e cada um destes tem um conjunto ligeiramente diferente de interações. Como o OPM só
tem um tipo de diagrama, a concisão dos padrões de interação ajuda a simplificar o
esforço de modelagem (Lui e Glunch 2004). No artigo ―Object-Process Methodology
(OPM) vs. UML: A Code Generation Perspective‖ os autores Reinhartz-Berger, Iris e Dori
(2014) concluíram que os problemas de consistência na UML e sua representação
distribuída do comportamento do sistema são refletidos no código, resultando em código
parcial que é principalmente orientado à estrutura. Os modelos OPM, por outro lado,
capturam os aspectos estáticos e dinâmicos de um sistema em uma única visão coerente,
permitindo a geração de uma lógica de aplicativo potencialmente completa em vez de
apenas um código esqueleto.
Figura 8 – Exemplo de interface da game engine Unity3D
Fonte: autoria própria.
De acordo com a proposta de Barros (2007), a criação do jogo é fase que envolve a
produção do jogo, em que é feito o desenvolvimento do código-fonte, e da arte
audiovisual do jogo. A construção do jogo foi feita a partir do Diagrama Objeto-Processo
como base para desenvolvimento do sistema na camada de código de jogo. Para auxiliar
na elaboração dos códigos foi utilizado o Game Engine Unity3D (Unity Technologies,
2009), versão 5.6.0f3, dando um nível maior de abstração para o desenvolvimento. A
24
game engine é uma camada de software que disponibiliza recursos de mais alto nível a
serem empregados pelo ―código do jogo‖, facilitando seu desenvolvimento.
As Game Engines tornaram-se o estado da arte no desenvolvimento de muitos
títulos de jogos comerciais. Ao fornecer mais abstração, encapsulamento do
conhecimento e uma base de desenvolvimento de jogos reutilizáveis, eles permitiram que
a indústria de jogos alcançasse um nível de produtividade incomparável (Furtado, 2012).
A Game Engine Unity 3D é um sistema orientado por Game Objects (Objetos de jogo),
que abstrai diversas funções através de associação de componentes (scripts pré-
definidos).
Este capítulo apresentou o contexto do desenvolvimento de jogos digitais e
descreveu as principais características da modelagem OPM. Também foram citados
estudos que foram realizados sobre a análise entre as modelagens UML e OPM. Com
base neste estudo, as modelagens foram aplicadas e analisadas no desenvolvimento de
um jogo digital, que é descrito nos próximo capítulo.
25
3. APLICAÇÃO DA UML E DA OPM EM UM JOGO DIGITAL
Este capítulo descreve o processo de desenvolvimento de um jogo digital aplicando
a UML e a OPM. Para isso, foi desenvolvido um jogo digital, de autoria própria, as partir
dos diagramas UML e OPM. Tanto a modelagem UML como a OPM, de autoria própria,
foram feitas por um estudante com experiência de nível acadêmico. Entretanto, a
qualidade das modelagens segue o desenvolvimento mais próximo possível que a
literatura recomenda. A elaboração do jogo foi feita em quatro etapas: a definição dos
requisitos do jogo, a modelagem dos requisitos em UML, a modelagem dos requisitos em
OPM e a programação do jogo.
3.1. Descrição do jogo ―Square Overflow‖
O jogo proposto para este estudo deste capítulo foi denominado ―Square Overflow‖.
Trata-se de um jogo que desafia o jogador identificar um padrão de luzes por meio da sua
capacidade de reconhecimento visual. Foi optado por fazer esse jogo porque seu
mecanismo é simples e tem pequeno porte, facilitando a correlação entre os diagramas
da UML e da OPM.
Figura 9 - Tela inicial do "Square Overflow"
Fonte: autoria própria.
26
A Figura 9 refere-se à tela inicial do jogo, que contém a opção de iniciar o jogo e sair
do jogo. Assim que o jogador aciona o botão ―Jogar‖, uma nova partida é iniciada. O
jogador pode também a qualquer momento acionar o botão ―Sair‖ para fechar o jogo.
Ao inicializar uma partida, o jogador será desafiado a indicar o padrão de luzes que
é formado por um conjunto de quadrados acesos. A Figura 10 mostra um exemplo de
uma tela do jogo inicializando um novo nível. Esta tela contém os textos: ―Pontos‖,
exibindo a pontuação atual, e ―Erros‖, exibindo os erros cometidos, e um conjunto de
quadrados com os tipos: cinza (apagado) e branco (aceso). O padrão dos quadrados
acesos é exibido na tela por um período de dois segundos. Este período é reservado para
que o jogador tente memorizar o padrão. Após este período de tempo todos os quadrados
são apagados (em cor cinza). Na Figura 10, o padrão é formado pelos três quadrados
acesos.
Figura 10 - Exemplo de novo nível do jogo "Square Overflow"
Fonte: autoria própria.
A Figura 11 exibe um exemplo de tela durante a execução do jogo, que representa a
continuação da partida exibida na Figura 10. Quando o jogador seleciona um quadrado
pertencente ao padrão, este quadrado permanece aceso e é computado um ponto. Na
Figura 11, o quadrado no canto superior direito foi selecionado e permaneceu aceso, pois
foi uma seleção correta. Quando o jogador seleciona um quadrado que não pertence ao
padrão, o quadrado é removido e é adicionado um erro. Observando a Figura 11, a matriz
27
não exibe um quadrado no canto inferior esquerdo. Havia um quadrado anteriormente que
foi selecionado e, como não pertencia ao padrão, foi removido da matriz.
Figura 11 - Exemplo de execução de um nível do jogo "Square Overflow"
Fonte: autoria própria.
Figura 12 – Tela contento o botão ―Próximo nível― do jogo "Square Overflow"
Fonte: autoria própria.
28
Figura 13 - Tela ―Fim de Jogo‖ do jogo "Square Overflow"
Fonte: autoria própria.
Após cada ação do jogador, ocorre a verificação de condição de vitória, que é a
formação do padrão exibido, ou condição de derrota, que é errar além do limite permitido.
A cada vez que a vitória é alcançada, um novo nível é criado, com um número maior de
quadrados que a fase anterior e em um novo padrão. A Figura 12 mostra uma tela com o
botão ―Próximo nível‖ e o texto informativo mostrando o total de pontos. Quando ocorre
uma derrota, a partida acaba, exibindo a tela de fim de jogo, que está representada na
Figura 12. É exibido o total de pontos e o botão ―Jogar‖, que ao acioná-lo, começa uma
nova partida.
3.2. Requisitos do software ―Square Overflow‖
Os requisitos funcionais e não funcionais do software ―Square Overflow‖ são
apresentados na Tabela 1. Foi dado foco apenas aos requisitos funcionais para o
desenvolvimento e a compreensão do uso das modelagens UML e OPM.
29
Tabela 1 - Requisitos funcionais e não funcionais do jogo ―Square Overflow‖
Requisitos funcionais
RF01 O software deverá permitir a um jogador iniciar uma nova partida de jogo se uma partida não estiver em andamento.
RF02 O software deverá criar uma nova matriz de quadrados e um novo padrão de luzes quando for iniciada nova partida ou um novo nível.
RF03 O software deverá permitir ao jogador selecionar um quadrado.
RF03.1 O software deverá marcar ponto se o jogador selecionar um quadrado pertencente ao padrão.
RF03.2 O software deverá emitir som se o jogador selecionar um quadrado pertencente ao padrão.
RF03.3 O software deverá marcar erro se o jogador selecionar um quadrado fora do padrão.
RF03.4 O software deverá emitir som se o jogador selecionar um quadrado fora do padrão.
RF04 O software deverá exibir os pontos na tela.
RF05 O software deverá exibir os erros na tela.
RF06 O software deverá tocar música de fundo
RF07 O software deve permitir ao jogador avançar o nível da partida caso tenha selecionado o padrão exibido.
RF09 O software deverá permitir ao jogador sair do jogo.
Requisitos não funcionais
NRF01 O software será feito com a game engine Unity3D.
Fonte: autoria própria.
3.3. Modelagem UML do jogo ―Square Overflow‖
A modelagem UML foi desenvolvida com o auxílio da ferramenta Astah Community
versão 6.6.4 (Vision Change, 2012). A escolha da ferramenta deveu-se à simplicidade de
uso e gratuidade da versão. Para a modelagem do ―Square Overflow‖ foram escolhidos
apenas os principais diagramas que têm representatividade para esse projeto: Casos de
Uso, Classes, Comunicação, Estados e Sequência. Devido ao pequeno porte do projeto,
os diagramas de pacotes e componentes não foram modelados. Como foi escolhido o
diagrama de Estados, o diagrama de atividade não foi modelado, em razão da
redundância entre estes diagramas.
O diagrama de Casos de Uso da Figura 14 descreve quatro casos de uso, que são
as utilizações que o jogador (ator) poderá fazer do sistema. O caso de uso ―Iniciar nova
partida‖ está relacionado com o jogador poder iniciar uma nova rodada do jogo com a pré-
condição de que não tenha uma partida em andamento. O caso de uso ―Iniciar nova
30
partida‖ implica que o software, por meio do subcaso de uso ―Gerenciar nível‖, crie um
nível e, desta forma, uma nova partida é iniciada. Quando um novo nível é criado, os
textos da tela são atualizados.
Figura 14 - Diagrama de Casos de Uso ―Square Overflow‖
Fonte: autoria própria.
O caso de uso ―Selecionar quadrados‖ permite que o jogador selecione quadrados
durante o andamento de uma partida. O andamento de uma partida ocorre enquanto o
padrão de luzes não está totalmente selecionado e o total de erros não excede o limite
permitido. Quando o jogador faz seleção de um quadrado, o software checa a condição
31
de vitória ou derrota pelo subcaso de uso ―Gerenciar nível‖, atualiza as informações da
tela pelo subcaso de uso ―Atualizar as informações da tela‖ e emite um áudio pelo
subcaso de uso ―Emitir som‖.
O caso de uso ―Avançar nível‖ permite que o jogador continue a partida avançando
para o próximo nível. O jogador deverá ter resolvido o nível anterior, tendo selecionado
todo o padrão de luzes como pré-condição. O nível é incrementado pelo software por
meio do subcaso de uso ―Gerenciar nível‖, que cria o próximo nível, mais complexo, a
partir dos parâmetros do nível anterior.
O caso de uso ―Sair do jogo‖ permite que o jogador encerre o jogo a qualquer
momento da partida e o caso de uso é o ―Ouvir música‖ que consiste de tocar música de
fundo durante o jogo. Este caso de uso não depende da ação do jogador para existir.
O diagrama de Classes da Figura 15 descreve a estrutura das classes, assim como
seus atributos, operações e relações. Optou-se por utilizar nomes em inglês para as
classes. As classes contendo o sufixo ―Button‖ são botões e contendo o sufixo ‗‖UI‖ são
elementos da User Interface (interface do usuário).
Quando o software é inicializado, é exibido o botão ―Jogar‖, que representado pela
classe PlayButton. Este botão permite ao jogador inicializar uma nova partida. Ao solicitar
uma nova partida, a classe de controle GameManager realiza a parametrização das
variáveis e cria um novo nível. Ao ser selecionado, o PlayButton também acessa as
classes pertencentes a tela fazendo as seguintes alterações: as classes que exibem texto
PointsUI, ErrorUI, InfoGameUI tem seus textos inicializados e o título TitleUI é ocultado.
A criação do nível é feita pela classe GameManager, que limpa a tela destruindo
todos os quadrados e instancia uma matriz de quadrados. Os quadrados contêm a classe
SquareButton, que controla seu comportamento no jogo. Durante o andamento da partida,
a classe SquareButton recebe as seleções do jogador e informa a classe GameManager,
que atualiza os parâmetros da partida, as informações na tela (TitleUI, PointsUI, ErrorUI,
InfoGameUI) e faz a verificação de vitória ou de derrota. A seleção também emite som
que é controlado pela classe SquareButton.
32
Figura 15 - Diagrama de Classes ―Square Overflow‖
Fonte: autoria própria.
33
O botão ―Próximo nível‖ está associado à classe NextLevelButton que é responsável
por solicitar um novo nível ao GameManager. A classe GameManager ativa o botão
NextLevelButton quando um nível é concluído e o botão PlayButton quando os muitos
erros levam ao encerramento da partida. Ambos os botões se desativam após a seleção
do jogador.
O botão ―Sair‖ está associado à classe ExitGameButton que realiza o encerramento
do jogo. Este botão fica ativo durante todo o jogo. A classe MusicManager é responsável
por tocar o áudio do jogo que inicializa assim que o jogo começa.
Figura 16 - Diagrama de Sequência ―Iniciar uma nova partida‖ do jogo ―Square Overflow"
Fonte: autoria própria.
A Figura 16 mostra o diagrama de sequência do processo de inicialização de uma
nova partida. A partida começa assim que o jogador seleciona o botão ―Jogar‖ que possui
a classe PlayButton. O botão faz a solicitação de um novo nível para o GameManager,
oculta o título (TitleUI), inicializa os textos (PointsUI, ErrorsUI) e se desativa.
A Figura 17 mostra a parte do processo que ocorre ao executar a função nextLevel
que é chamada tanto no início de uma nova partida quanto na criação de um próximo
nível. Como os quadrados são instanciados em forma de matriz, há dois loops que são o
34
eixo vertical e o eixo horizontal. Na criação dos quadrados, a parametrização determina
se será parte do padrão ou não. A matriz é criada mostrando todo o padrão e, logo após
dois segundos, o padrão é ocultado pela classe SquareButton.
Figura 17 - Diagrama de Sequência ―NextLevel‖ do jogo ―Square Overflow"
Fonte: autoria própria.
A Figura 18 mostra o diagrama de sequência da seleção de um quadrado. O
processo começa quando o jogador faz uma seleção de um quadrado. Quando
selecionado, informa a classe GameManager se pertence ao padrão ou não. Isso faz com
que seja executada a função countPoint em caso de padrão ou countError em caso de
erro. Na sequência, o quadrado realiza mudança de aparência e emite um som.
A Figura 19 mostra o processo de execução da função countPoint de forma
completa. Com a seleção de um quadrado no padrão é realizada a atualização do texto
PointsUI que exibe os pontos e então é feita a verificação se todo o padrão foi
selecionado. Caso isso tenha ocorrido, a sequência continua com um loop, que destrói
todos os quadrados, com atualização dos textos ErrorsUI e InfoGameUI e é habilitado o
botão ―Próximo nível‖ (NextLevelButton).
35
Figura 18 - Diagrama de Sequência ―Selecionar quadrados‖ do jogo ―Square Overflow"
Fonte: autoria própria.
Figura 19 - Diagrama de Sequência ―countPoint‖ do jogo ―Square Overflow"
Fonte: autoria própria.
36
Figura 20 - Diagrama de Sequência ―countError‖ do jogo ―Square Overflow"
Fonte: autoria própria.
Figura 21 - Diagrama de Sequência ―Avançar nível‖ do jogo ―Square Overflow".
Fonte: autoria própria.
37
A Figura 20 exibe o processo de execução da função countError. Quando a classe
GameManager recebe uma seleção fora do padrão, atualiza o texto do erro (ErrorsUI) e
verifica se o limite de erros foi atingido. Caso o limite de erros seja atingido a classe
GameManager destrói todos os quadrados num loop, informa o fim do jogo (InfoGameUI),
exibe o título (TitleUI) e habilita o botão ―Jogar‖ (PlayButton).
A Figura 21 mostra a sequência do processo de avanço de nível. Quando o jogador
seleciona o botão ―Próximo nível‖, que tem a classe NextLevelButton, a classe
GameManager irá criar um novo nível conforme o diagrama de Sequência ―NextLevel‖. O
botão ―Próximo nível‖ limpa o texto informativo InfoGameUI e se desabilita.
A Figura 22 mostra a sequência de saída do jogo. Assim que o jogador selecionar o
botão ―Sair‖, sua classe ExitGameButton executa a função de encerramento.
Figura 22 - Diagrama de Sequência ―Sair do jogo‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 23 exibe o diagrama de sequência ―Ouvir música‖. O áudio da música
começa a tocar assim que a classe MusicManager é criada. A classe MusicManager é
instanciada pela engine Unity3D e que também, em algum momento, com o encerramento
do jogo, é destruída. A criação e destruição das classes pela Unity3D ocorrem também da
mesma forma com as demais classes, embora não esteja explicito-nos outros diagramas.
38
Figura 23 - Diagrama de Sequência ―Ouvir música‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 24 mostra o diagrama de comunicação ―Iniciar nova partida‖. Assim que o
jogador seleciona o botão ―Jogar‖, a classe PlayButton solicita a criação de um novo nível,
inicializa os textos (PointsUI, ErrorUI, InfoGameUI) e esconde o título (TitleUI) e se
desativa. Quando os quadrados são instanciados pela classe GameManager, a classe
SquareButton bloqueia a seleção do jogador e executa a função
StartCoroutine(showingFrame()) que no decorrer de dois segundos libera a seleção e
oculta o padrão.
A Figura 25 mostra o diagrama de comunicação da seleção de quadrados. Cada vez
que o jogador seleciona um quadrado, a classe SquareButton informa a classe
GameManager, emite um som e muda de aparência. A classe GameManager faz a
verificação se é um quadrado pertencente ao padrão ou não. No caso de acerto: pontua,
altera o texto de pontos na tela e se o padrão estiver completado informa o jogador e
habilita o botão ―Próximo nível‖. No caso de erro: marca erro, atualiza o texto de erro na
tela e caso tenha excedido o limite de erro na tela, informa o fim do jogo e habilita o botão
de ―Jogar‖.
39
Figura 24 – Diagrama de Comunicação ―Iniciar nova partida‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
40
Figura 25 - Diagrama de Comunicação ―Selecionar quadrados‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
Figura 26 - Diagrama de Comunicação ―Avançar nível‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 26 exibe o diagrama de comunicação sobre o processo de avançar nível.
Quando o jogador seleciona o botão ―Próximo nível‖ a classe NextLevelButton solicita à
GameManager a criação de um novo nível e o botão de ―Próximo nível‖ é desabilitado. Os
quadrados são instanciados e executam as mesmas funções da mesma forma mostrada
41
no diagrama de comunicação ―Iniciar nova partida‖.
A Figura 27 mostra o diagrama de comunicação do processo de saída do jogo.
Quando o botão ―Sair‖ é selecionado a classe ExitGameButton chama a função quitGame
que realiza o fechamento do jogo.
Figura 27 - Diagrama de Comunicação ―Sair do jogo‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 28 mostra o diagrama de comunicação ―Ouvir música‖. A função play é a
única função que o MusicManager executa durante o jogo.
Figura 28 - Diagrama de Comunicação ―Ouvir música‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 29 mostra os estados alcançáveis do botão PlayButton ao longo do
processo. O botão existe assim que o jogo é inicializado e fica aguardando que o jogador
o selecione. Quando é selecionado, os textos são inicializados, o título é ocultado e por
42
fim fica aguardando até que a condição de encerramento do jogo faça com que o
GameManager reabilite o botão.
Figura 29 - Diagrama de Estado ―PlayButton‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 30 exibe o diagrama de estado do botão ―quadrado‖ que possui a classe
SquareButton. Assim que o botão é instanciado, sua seleção se torna desabilitada e a
função interna StartCoroutine(showingFrame()) é inicializada. No decorrer de dois
segundos o padrão é escondido e a seleção do botão é habilitada. Após a ocultação do
padrão o botão fica estado de aguardando seleção. Quando o botão é selecionado, a
classe SquareButton informa o GameManager para realizar o processamento de sua
seleção, emite áudio, muda a imagem, impede que seja selecionado novamente e fica
aguardando a criação de um novo nível.
43
Figura 30 - Diagrama de Estado ―SquareButton‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
Figura 31 - Diagrama de Estado ―NextLevelButton‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
Na Figura 31 é exibido o diagrama de estado do botão ―Próximo nível‖ com a classe
44
NextLevelButton. Quando o jogo é inicializado o botão está inicialmente ocultado, pois
não existe uma partida em andamento. O estado inicial é ―Aguardando habilitação‖ e sua
habilitação irá ocorrer pela classe GameManager sempre que o jogador completar o
padrão de um nível. Quando o jogador selecionar o botão, é ocultado o texto informativo
InfoGameUI e o processo de novo nível será encaminhado para a classe GameManager e
o botão se desabilita novamente.
A Figura 32 mostra o diagrama de estado da classe GameManager. Esta classe fica
aguardando que seja solicitado um novo nível ou que o jogador selecione um quadrado.
Como na inicialização do jogo não há nenhum nível em andamento, o estado inicial é
aguardando a solicitação de um novo nível (nextLevel()), que pode ser feita pela seleção
do botão ―Jogar‖ ou ―Próximo nível‖. Após a criação de um novo nível, a classe
GameManager fica aguardando a seleção de um quadrado pelo jogador.
Figura 32 - Diagrama de Estado ―GameManager‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
Com a seleção de um quadrado no padrão, ocorre o processo mostrado no
diagrama de sequência ―countPoint‖. É realizada a atualização do texto PointsUI que
exibe os pontos e então é feita a verificação se todo o padrão foi selecionado. Caso o
45
padrão ainda esteja incompleto, o GameManager continua aguardando a próxima
seleção. Caso isso tenha ocorrido, todos os quadrados são destruídos, são atualizados os
textos ErrorsUI e InfoGameUI e é ativado o botão ―Próximo nível‖ (NextLevelButton).
Quando a classe GameManager recebe uma seleção fora do padrão, atualiza o
texto do erro (ErrorsUI) e verifica se o limite de erros foi atingido. Caso o número de erros
não tenha atingido o limite, o GameManager continua aguardando a próxima seleção.
Caso o limite de erros seja atingido a classe GameManager destrói todos os quadrados,
informa o fim do jogo (InfoGameUI), exibe o título (TitleUI) e habilita o botão ―Jogar‖
(PlayButton).
A Figura 33 descreve os estados do botão ―Sair‖ que contém a classe
ExitGameButton. O botão fica habilitado desde a inicialização do jogo e fica aguardando a
seleção do jogador para executar o fim do jogo.
A Figura 34 exibe os dois únicos estados que os elementos da tela possuem, o título
―TitleUI‖, uma imagem que pode ser exibida ou ocultada e os demais textos que mudam o
conteúdo escrito.
Figura 33 - Diagrama de Estado ―ExitGameButton‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
46
Figura 34 - Diagramas de Estado dos elementos da tela do jogo ―Square Overflow‖
Fonte: autoria própria.
Figura 35 - Diagramas de Estado dos elementos da tela do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 35 mostra os estados possíveis da classe MusicManager. A classe inicia a
reprodução da música e permanece neste estado até que o jogo seja encerrado pelo
jogador.
Com a realização da modelagem dos diagramas UML, foram gerados, no total, vinte
e dois diagramas, sendo um de caso de uso, um de classe, sete de sequência, cinco de
comunicação e nove de estados.
47
3.4. Modelagem OPM do jogo ―Square Overflow‖
Para a realização da modelagem OPM optou-se por iniciar o diagrama a partir das
utilizações do jogo. Desta forma, o diagrama OPM da Figura 36 ilustra os cinco processos
correspondentes às cinco utilizações do jogo que são: ―Tocando música‖, ―Iniciando nova
partida‖, ―Selecionado quadrados‖, ―Avançando nível‖ e ―Saindo do jogo‖. Optou-se por
escrever os nomes dos processos no gerúndio, uma vez que a tradução dos diagramas
OPM do inglês para o português comporta mais de uma interpretação. Como existem
várias relações no diagrama principal, foi utilizado o recurso de cores para facilitar sua
visualização.
Figura 36 – Diagrama principal do jogo ―Square Overflow‖
Fonte: autoria própria.
O jogador (pessoa) está representado como ―objeto físico‖ (sombreado). Os objetos
dos botões utilizados pelo jogador, que são ―PlayButton‖, ―SquareButton‖,
―NextLevelButton‖ e ―ExitGameButton‖, estão representadas como ―objetos informáticos‖
48
(sem sombreado) pois são ―botões virtuais‖ acessados pelo cursor do mouse. Como o
processo ―Tocando música‖ é simples, todo o funcionamento já está sendo exibido no
diagrama principal, que inicializa o componente ―AudioSource‖ pelo estado ―play‖,
enquanto os demais estão generalizados. Os componentes dos objetos e os
subprocessos aparecem conforme é feito o ―in-zooming‖.
Figura 37 - Diagrama ―Iniciando nova partida in-zoomed‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
49
O diagrama da Figura 37 representa o ―in-zooming‖ aplicado ao processo ―Iniciando
nova partida‖. O primeiro subprocesso é o ―Selecionando botão‖, que envolve o evento
(representado pela letra ―e‖) que é disparado quando o jogador realiza sua seleção. Existe
também uma condição (representado pela letra ―c‖) que determina que para isto ocorrer,
um objeto precisa estar em um estado específico para um processo acontecer. No caso
do processo ―Selecionando botão‖, uma das condições para a sua execução é que o
objeto ―PlayButton‖ precisa estar em seu o estado inicial (borda grossa) ―Aguardando
seleção‖. Este processo ocorre de maneira similar com os outros botões do sistema. Os
demais subprocessos só ocorrem com a execução do anterior (acima), conforme a
cronologia esperada.
Quando o botão ―PlayButton‖ muda de estado para selecionado, são executados os
subprocessos ―Gerenciando nível‖ e ―Atualizando tela‖ que estão generalizados e o
subprocesso ―Desativando‖. O subprocesso ―Desativando‖ faz a desativação pela
alteração do parâmetro ―active‖ do ―GameObject‖, que é um objeto componente do botão.
A Figura 38 mostra a ampliação do subprocesso ―Gerenciando nível‖ que possui o
subprocesso ―Criando novo nível‖ que é chamado tanto pelo ―NextLevelButton‖ quanto por
―PlayButton‖. O arco entre dois ou mais pontos de objetos apontando para o mesmo
processo significa que uma relação ou outra é o suficiente para realizar a execução do
processo. O objeto GameManager que representa a classe GameManager instancia os
quadrados quando é solicitada a criação de um novo nível. O processo de instanciar
quadrados é invocado novamente até que seus parâmetros ―Eixo X‖ e ―Eixo Y‖ alcancem
um determinado valor limite. O processo ―Inicializando quadrado‖ está fora do processo
―Gerenciando nível‖ e ocorre de maneira independente, pois sua inicialização está
associada somente ao estado inicial do objeto.
A Figura 39 mostra o processo de inicialização de um quadrado de forma mais
detalhada. O andamento dos processos segue a ordem vertical, na qual um quadrado
com o parâmetro ―Pattern‖ igual a ―true‖ faz a ocultação da imagem além dos demais
processos. O objeto ―Temporizador‖ é uma forma de representação de que um período de
passou e seus estados mudam com o decorrer do tempo. Os objetos ―Button‖, ―Pattern‖ e
―Image‖ são componentes pertencentes ao objeto ―SquareButton‖ que contém parâmetros
equivalentes aos das classes em UML.
50
Figura 38 - Diagrama ―Gerenciando nível in-zoomed‖ do jogo ―Square Overflow‖.
Fonte: autoria própria.
51
Figura 39 - Diagrama ―Inicializando quadrado in-zoomed‖ do jogo ―Square Overflow‖.
Fonte: autoria própria.
52
Figura 40 - Diagrama ―Atualizando tela in-zoomed‖ do jogo ―Square Overflow‖.
Fonte: autoria própria.
A Figura 40 mostra o diagrama do subprocesso ―Atualizando tela‖ com zoom. Este
processo é executado tanto pelo ―PlayButton‖ como o ―NextLevelButton‖. O processo
desencadeia a ocultação do título e a atualização dos textos. Entretanto, ao iniciar uma
partida, o texto informativo ―InfoGameUI‖ se encontra vazio, por isso só há necessidade
do processo ―Setando o texto InfoGameUI‖ ocorrer na presença do ―NextLevelButton‖.
53
Figura 41 - Diagrama ―Selecionando quadrados in-zoomed‖ do jogo ―Square Overflow‖.
Fonte: autoria própria.
54
A Figura 41 contém o diagrama ―in-zoomed‖ do processo ―Selecionando quadrados‖.
Assim como os demais botões, este processo é inicializado pelo jogador quando ele faz
uma seleção. Se um quadrado possui o parâmetro ―Pattern‖ como valor ―true‖, então ele
pertence ao padrão de luzes e quando ele é selecionado o subprocesso ―Contando
pontos‖ é chamado. Caso um quadrado tenha o parâmetro ―Pattern‖ com o valor ―false‖,
então ele não pertence ao padrão de luzes e se for selecionado o subprocesso ―Contando
erros‖ será inicializado. Após a execução desses subprocessos, o som, que está pré-
definido para o botão, é tocado e então sua imagem muda. A imagem muda, de acordo
com a presença ou não do padrão, para que o jogador tenha o retorno visual da ação. Por
fim, a opção de seleção do botão é desativada para evitar uma nova seleção.
O diagrama ―Contando pontos in-zoomed‖ da Figura 42 mostra o processo similar ao
do diagrama de sequência UML ―CountPoints‖. A seleção sempre faz a atualização dos
pontos ―PointsUI‖ e, caso atinja a condição de selecionar todo o padrão (numberOfPatters
<= currentHits), outros subprocessos são desencadeados pelo objeto GameManager. O
processo de preparar um novo nível é desencadeado, desta forma os quadrados são
destruídos para a criação de novos, o texto de erro é atualizado, o texto de total de pontos
―InfoGameUI‖ é exibido e o botão ―NextLevelButton‖ é ativado para que o jogador solicite
o próximo nível.
A Figura 43 mostra o diagrama ―Contando erros‖ em zoom. Quando o quadrado que
está fora do padrão é selecionado, o processo contabiliza um erro e seu total atualizado é
exibido na tela. Ao atingir o limite de erros permitidos (limitErrors <= currentErrors), o
―GameManager‖ realiza a limpeza da tela destruindo os quadrados, informa o final do jogo
pelo texto informativo ―InfoGameUI‖, exibe o titulo e habilita o botão ―PlayButton‖ para que
o jogador possa começar uma nova partida.
A Figura 44 se refere ao diagrama ―Avançando nível‖ em zoom que representa uma
das cinco ações do diagrama principal. Quando o jogador executa uma seleção, os
subprocessos ―Gerenciando nível‖ e ―Atualizando tela‖ são chamados e, por fim, o botão é
desativado. Os diagramas da Figura 37 - ―Iniciando nova partida‖ in-zoomed e da Figura
44 – ―Avançando nível‖ in-zoomed são parecidos e utilizam os mesmos subprocessos. Os
subprocessos ―Gerenciando nível‖ e ―Atualizando tela‖ estão representados na Figura 38
e 40 respectivamente. Isto é possível por que se trata do mesmo objeto ―GameManager‖
que está envolvido na execução dessas operações.
55
Figura 42 - Diagrama ―Contando pontos in-zoomed‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
56
Figura 43 - Diagrama ―Contando erros in-zoomed‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
57
Figura 44 - Diagrama ―Avançando nível in-zoomed‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
A Figura 45 mostra de forma detalhada o processo envolvido com o botão
―ExitGameButton‖. Assim que o jogador realiza a seleção, a função de encerramento do
jogo é acionada.
58
Figura 45 - Diagrama ―Saindo do jogo in-zoomed‖ do jogo ―Square Overflow‖
Fonte: autoria própria.
O desenvolvimento da modelagem OPM gerou dez diagramas no total. O diagrama
OPM ―Ações do jogador‖ tem a estrutura similar ao diagrama de caso de uso, os
processos seguem fluxo similar ao dos diagramas de sequência e os estados dos
diagramas de estados UML estão presentes na execução dos processos e nos estados
dos objetos.
3.5. Programação do jogo ―Square Overflow‖
A programação do jogo foi feita utilizando objetos do tipo GameObject, compostos
por componentes pré-definidos do Unity3D, incluindo o componente Scripts realizado em
linguagem C#. Para este projeto foram utilizados elementos da interface do usuário, que
são botões, textos e imagens fixados na câmera. Os quadrados gerados pelo gerenciador
de nível, são botões, possuindo a ação OnClick(). Esta ação, que é da própria engine
Unity3D, realiza a chamada de uma ou mais funções no programa quando o botão é
59
clicado. Conforme já foi citado nas modelagens, a inicialização do jogo é feita pelo botão
chamado ―Jogar‖, que permite ao jogador inicializar o jogo (OnClick()).
Foram gerados dois scripts: um para o SquareButton que cuida da inicialização do
botão e outro para o GameManager que faz todo o controle do jogo. Os códigos
comentados dos Scripts desenvolvidos para o jogo ―Square Overflow‖ estão no
APÊNDICE A – Códigos dos scripts do jogo ―Square Overflow‖.
O executável com a versão final do jogo ―Square Overflow‖ está disponível online
para download (Kovalski, 2019a).
3.6. Discussão sobre o jogo ―Square Overflow‖
O jogo ―Square Overflow‖ consistiu de cinco utilizações: ―Iniciar nova partida‖,
―Selecionar quadrados‖, ―Avançar nível‖, ―Sair do jogo‖ e ―Ouvir música‖. O
desenvolvimento dos diagramas UML foi feita de tal forma que, diagramas com muitas
informações e diagramas com partes similares entre si, ficassem separados em novos
diagramas. Desta forma, a quantidade de diagramas aumentou, porém a carga de
informações dos diagramas foi reduzida. Assim foi possível evidenciar melhor as visões
sobre o sistema, facilitando sua compreensão. A quantidade de diagramas gerados em
UML desta maneira foi vinte e cinco.
Para a aplicação da OPM, foram desenvolvidos dez diagramas. O diagrama de alto
nível mostra todas as utilizações do programa, enquanto, os demais, mostram uma visão
detalhada para cada utilização. Com a capacidade de representação do OPM, foi possível
representar o comportamento, a estrutura e a funcionalidade no mesmo diagrama. Os
diagramas OPM foram aprofundados em níveis de detalhes até possuir as mesmas
informações que foram apresentadas na UML.
O tempo necessário para a modelagem de cada diagrama levou em média quatro
horas tanto para a UML quanto para a OPM. Porém, como o número total de diagramas
OPM foi menor que a UML, a OPM teve tempo total menor desenvolvimento. Entretanto,
deve-se levar em consideração que, como foi feita a modelagem UML anteriormente, o
entendimento sobre como os requisitos vão compor o sistema, já estavam, de alguma
forma, definidos. As modelagens dos diagramas UML demandaram uma reflexão de como
60
iriam ser as dinâmicas e a estrutura do software. Por isso, durante a etapa de modelagem
da UML, foram realizadas revisões sobre a consistência entre os diagramas, necessitando
realizar ajustes nos diagramas já criados, para manter a coerência das visões sobre o
sistema. A Tabela 2 mostra a quantidade de diagramas produzidos para o software
―Square Overflow‖.
Tabela 2 – Quantidade de diagramas produzidos para o jogo ―Square Overflow‖
UML OPM
Caso de uso Classe Sequência Comunicação Estados Objeto-Processo
1 1 8 5 10 10
Total 25 10
Fonte: autoria própria.
3.7. Discussão sobre a aplicação a UML e a OPM em um jogo digital
A OPM, de modo geral, demonstrou ser mais fácil de modelar que a UML. Tendo
apenas um tipo de diagrama, a forma de navegar por camadas de detalhamento, ajuda a
separar cada elemento de acordo com seu papel em cada processo. Em contra partida, a
UML tem um conjunto de símbolos e formas de representações diferentes para cada
diagrama. Então, a cada vez que um novo tipo diagrama é feito, é necessário se adaptar
a uma nova notação.
Com relação à facilidade de compreensão, a ferramenta de modelagem OPCAT
gera automaticamente o texto OPL, que é correspondente às informações representadas
no diagrama OPD. Durante a modelagem, o modelador tem o texto como um apoio para
conferir os diagramas e o significado das relações. Para o manuseio dos diagramas, um
observador também poderá escolher entre ver o diagrama ou ler o texto, conforme
parecer melhor compreensível.
A OPM permite mostrar as relações de participação e condições para os processos
de forma simples e, se for necessário, também permite detalhar essas relações de forma
mais explícita. Por outro lado, a criação com a UML exige um nível maior de
detalhamento, como por exemplo, no diagrama de classes têm-se as variáveis, funções e
seus argumentos bem definidos.
Pode-se concluir que a OPM é apropriada para a modelagem de jogos digitais. Em
61
comparação com a UML, a modelagem com a OPM demonstrou ser uma opção favorável.
Como a OPM como possui um apenas tipo de diagrama e seu total de símbolos menor
que a UML e gera um texto equivalente, a quantidade de informações que um modelador
precisa lidar é menor, ajudando na compreensão e manutenção dos diagramas.
Com os diagramas gerados e analisados, o próximo capítulo apresenta uma
investigação da percepção de três profissionais da área de jogos, com relação aos
diagramas UML e OPM gerados para o desenvolvimento de um jogo digital.
62
4. INVESTIGAÇÃO DA APLICAÇÃO DA UML E DA OPM EM JOGOS
DIGITAIS
Para complementar as impressões retiradas dos diagramas UML e OPM em jogos
digitais, foi realizada uma investigação sobre os modelos gerados por meio de um
questionário com três profissionais da área de desenvolvimento de jogos digitais. O
questionário foi composto por duas perguntas: ―1 – Já conhecia alguma das modelagens
apresentadas?‖ e ―2 – Qual das modelagens apresentadas demonstrou maior facilidade
de compreensão?‖. Os três entrevistados possuem pós-graduação em desenvolvimento
de jogos digitais e experiência no desenvolvimento de jogos, sendo dois programadores,
denominados ―entrevistados A e B‖, e um modelador de objetos tridimensionais,
denominado ―entrevistado C‖. Para realizar a investigação, foi previamente realizado um
breve treinamento sobre as duas abordagens e então foram apresentados os diagramas
UML e OPM do jogo ―Square Overflow‖.
Com a apresentação das modelagens e a realização do questionário, foram obtidos
os resultados. Com relação à UML, os ―entrevistados A e B‖ já a conhecia, porém não
haviam visto sua aplicação em um jogo digital. Já o ―entrevistado C‖ não conhecia a
modelagem. Com relação à OPM, nenhum dos três entrevistados a conhecia.
Para a segunda pergunta, o ―entrevistado A‖ respondeu de seguinte maneira: ―A
OPM demonstrou maior facilidade de compreensão. Enquanto a UML apresenta muitas
informações em cada um de seus diagramas, a visão do projeto como um todo é meio
ofuscada, enquanto a OPM apresenta todos os aspectos de uma única vez, junto com
suas iterações e permite que cada ponto seja analisado de forma mais prática e de
maneira mais clara.‖.
Para o ―entrevistado B‖, teve-se a seguinte resposta: ―Comparando a modelagem
UML e OPM utilizadas no exemplo explanado, a minha opinião é que a OPM é somente
uma forma elegante de apresentar os artefatos da modelagem. A OPM aparenta
diagramas (de caso, de classes, etc.) visualmente mais simples, mas que deve trazer as
mesmas informações de uma UML tradicional. A UML já traz uma grande comunidade
que já utiliza essa metodologia. Finalizando, não vi muita diferença no resultado final,
menos diagramas não quer dizer necessariamente um software melhor construído.‖
Por fim, a resposta do ―entrevistado C‖ foi: ―Ao observar os dois modelos de
63
diagramação, pode observar que o modelo OPM é de melhor compreensão. O motivo de
compreender mais a OPM é o texto gerado embaixo do diagrama, pois, em minha
opinião, os dois, no final, parecem um emaranhado onde só quem criou realmente
entende, assim como qualquer outro modo de programação usando nodes, como
mechanim e shader graph do próprio ―Unity3D‖, que, sem comentários ou guias dos
criadores, é muito difícil compreender‖.
Analisando as respostas, a OPM pareceu ser mais compreensível que a UML por
causa da menor simbologia e dos textos OPLs gerados automaticamente. Entretanto, a
amostra com três avaliadores é pequena e pode não representar a opinião da maioria das
pessoas. Deve-se considerar também que o nível de conhecimento das metodologias, a
experiência com criação de diagramas e preferências pessoais, podem ser fatores que
influenciam na percepção do avaliador com relação aos modelos dados.
Com a investigação do uso da UML e da OPM em jogos digitais, o próximo capítulo
trata-se da aplicação da OPM em outro jogo digital, com uma complexidade um pouco
maior que o ―Square Overflow‖, com as seguintes seções: desenvolvimento, análise e
discussão dos diagramas OPM gerados.
64
5. SEGUNDA APLICAÇÃO DA OPM EM UM JOGO DIGITAL
Para propor um conjunto de orientações para uso geral da OPM na modelagem de
software de jogos digitais, optou-se por criar um jogo novo por meio da modelagem OPM
e, a partir dele, analisar com maior aprofundamento, a sua aplicação. Um dos motivos de
fazer um novo jogo é que, no desenvolvimento dos diagramas do jogo ―Square Overflow‖,
a modelagem UML havia sido realizada por primeiro, e por isso existe uma possibilidade
de sua analogia influenciar no processo de criação dos diagramas OPM. Outro motivo é
também fazer uma investigação com um jogo mais complexo, apresentando outro
exemplo da aplicação da modelagem OPM em jogos digitais. Então, a partir desses
objetivos, foi criado o jogo chamado ―Blinky‖, que é um jogo do gênero plataforma 2D.
Este tipo de jogo foi escolhido porque, embora seja mais complexo que o anterior, não
exige o uso de soluções de inteligência artificial complexas, em relação a outros gêneros,
que poderia tornar a modelagem extensa. Para este jogo, deste modo, foi utilizado
apenas o recurso de máquinas de estados finitas. Entretanto, um jogo desse tipo, pode
ser tão complexo quanto qualquer outro gênero (Schwab, 2009). Este capítulo está
dividido em subcapítulos que irão abordar os seguintes itens com relação ao jogo: a
descrição, os requisitos definidos, as modelagens OPM e as especificações sobre a
programação envolvida. Por fim, no último subcapítulo, é apresentada uma proposta de
orientações sobre o uso do OPM em jogos digitais.
5.1. Descrição do jogo ―Blinky‖
Como o jogo ―Blinky‖ é um jogo do gênero plataforma 2D, o jogador deve controlar
um personagem através de um cenário e, dentre as ações possíveis que envolvem o
jogador, a principal é pular. Em um cenário, plataforma é definida como uma superfície
plana e horizontal mais alta que a área circundante. Desta forma, o nome ―plataforma‖
vem da necessidade de pular de plataforma a plataforma. O jogador precisa lidar com
padrões e também conseguir fazer pulos de forma precisa, no tempo certo, sendo em
inimigos ou em plataformas, para conseguir um objetivo. Dentre os tipos de obstáculos, os
inimigos são os mais comuns e seus comportamentos costumam ser simples. O principal
papel dos inimigos é aumentar a dificuldade dos desafios na exploração do cenário
65
(Schwab, 2009).
A Figura 46 mostra a tela inicial do jogo ―Blinky‖, que foi criado a partir dos
diagramas OPM. O jogo ―Blinky‖ inclui um personagem representado por uma raposa, que
tem o objetivo de salvar coelhos aprisionados por mágicos de um circo. Na tela inicial, o
jogador poderá apertar qualquer tecla para iniciar uma nova partida. Fazendo isso, o
jogador é então encaminhado à tela do ―Tutorial‖, demostrada na Figura 47. Esta tela
exibe uma imagem explicando, de forma resumida, os botões do teclado de computador
(entrada escolhida para este jogo) e as suas ações. E, então, quando o jogador aperta
qualquer tecla novamente, é iniciado o primeiro nível.
Figura 46 - Tela inicial do jogo "Blinky"
Fonte: autoria própria.
Figura 47 - Tela de Tutorial do jogo ―Blinky‖
Fonte: autoria própria.
66
Figura 48 - Tela de exemplo do jogo ―Blinky‖ mostrando um coelho seguindo o ―Blinky‖
Fonte: autoria própria.
A Figura 48 exibe um exemplo de andamento do jogo. O cenário é uma caverna com
chão, parede e plataformas. Os blocos em tom marrom são o chão e as plataformas. No
topo têm-se as informações gerais do jogo que são: contador de vida, contador de
coelhos, nível atual e contador de pontos. O ―Blinky‖ está no meio do cenário e logo ao
lado dele há um coelho. Existe também, ao lado direto dele, uma porta, que é a porta de
saída. O jogador deve controlar o ―Blinky‖ para que ele encontre todos os coelhos no
cenário e com eles o seguindo, deve ir de encontro com a saída, para que eles sejam
salvos. Desta maneira, quando todos os coelhos foram salvos, o jogador avança de nível.
Os mágicos atuam no jogo como obstáculos, se deslocando pelo cenário, podendo ir
de encontro com o herói. Quando isso acontece, o ―Blinky‖ perde uma vida. Atingindo um
determinado limite de vidas perdidas o jogo acaba. A Figura 49 exibe uma tela onde o
―Blinky‖ foi tocado pelo Mágico e, então, perdendo uma vida.
O ―Blinky‖, ao encontrar uma caixa, pode carregá-la e arremessá-la para frente, ao
apertar a tecla de arremesso. A Figura 50 mostra o ―Blinky‖ segurando uma caixa.
Quando a caixa é arremessada e ela colide com um ―Mágico‖, o ―Mágico‖ é destruído. E,
para aumentar o desafio, quando um mágico é destruído, após um período de tempo, um
novo mágico é criado na porta de reaparecimento. Um exemplo desta porta pode ser vista
no canto superior direito da Figura 50.
67
Figura 49 - Tela de exemplo do jogo ―Blinky‖ mostrando o Mágico encontrando o
"Blinky"
Fonte: autoria própria.
Figura 50 – Tela de exemplo do jogo ―Blinky‖ mostrando a porta de reaparecimento
Fonte: autoria própria.
68
5.2. Requisitos do jogo ―Blinky‖
Para realizar o desenvolvimento do jogo, foram definidos, primeiramente, os
requisitos. Os requisitos estão apresentados na Tabela 2. Para o desenvolvimento deste
software, foi dado foco nas funcionalidades, deste modo, temos apenas a descrição dos
requisitos funcionais.
69
Tabela 2 - Requisitos para o jogo ―Blinky‖
RF01 O software deverá exibir a tela inicial, com o nome do jogo, ao iniciar o jogo.
RF02 O software deverá permitir ao jogador avançar a tela inicial, tela de tutorial, tela de fim de jogo quando pressionar qualquer botão.
RF03 O software deverá exibir a tela de tutorial quando o jogador avançar da tela inicial.
RF04 O software deverá iniciar o primeiro nível quando o jogador avançar do tutorial.
RF05 O software deverá, durante a execução de um nível, exibir na tela o total de pontos.
RF06 O software deverá, durante a execução de um nível, exibir na tela a quantidade de vidas.
RF07 O software deverá, durante a execução de um nível, exibir na tela a quantidade de "Coelhos" coletados.
RF08 O software deverá, durante a execução de um nível, exibir na tela o nível atual.
RF09 O software deverá permitir ao jogador movimentar o "Blinky".
RF09.1 O software deverá manter a câmera focando o "Blinky" conforme ele se movimenta.
RF09.2 O software deverá permitir ao jogador fazer o ―Blinky" se movimentar horizontalmente.
RF09.3 O software deverá permitir ao jogador fazer o "Blinky" pular.
RF09.4 O software deverá emitir som de pulo quando ocorrer uma ação de pulo.
RF10 O software deverá permitir ao jogador fazer o "Blinky" pegar "Coelhos" pelo cenário.
RF10.1 O software deverá gerenciar os movimentos dos "Coelhos" coletados conforme o "Blinky" se movimenta.
RF10.2 O software deverá emitir som de coleta quando o "Blinky" pegar um "Coelho".
RF11 O software deverá permitir ao jogador fazer o "Blinky" entregar os "Coelhos" coletados na porta de saída.
RF11.1 O software deverá avançar de nível caso o jogador tenha coletado todos os "Coelhos" do cenário e exista um próximo nível.
RF12 O software deverá permitir ao jogador fazer o "Blinky" coletar uma caixa no cenário caso ele encontre uma caixa e não esteja carregando uma.
RF12.1 O software deverá anexar a posição da caixa ao "Blinky" caso a caixa esteja sendo segurada.
RF13 O software deverá permitir ao jogador fazer o "Blinky" atirar uma caixa caso ela esteja sendo carregada.
RF13.1 O software deverá emitir um som caso a caixa seja arremessada.
RF13.2 O software deverá desanexar a caixa caso ela seja arremessada.
RF13.3 O software deverá matar um "Mágico" caso haja uma colisão dele com uma caixa arremessada.
RF13.3.1 O software emitir um som caso um Mágico tenha morrido.
RF13.3.2 O software deverá criar um novo "Mágico" sempre que o jogo fique, por um período de tempo, com um "Mágico" a menos que o total.
RF14 O software deverá permitir ao jogador perder vida quando o "Blinky" for encontrado por um "Mágico".
RF14.1 O software deverá gerenciar os movimentos dos "Mágicos" pelo cenário.
RF14.2 O software deverá emitir um som quando o "Blinky" perder vida.
RF14.3 O software deverá posicionar o "Blinky" na "Porta de saída" quando perder vida.
RF15 O software deverá encaminhar para a tela de fim de jogo quando o limite de vida for atingido.
Fonte: autoria própria.
70
5.3. Modelagem OPM do jogo ―Blinky‖
A modelagem foi dada a partir do nível mais genérico possível foi sendo
detalhada através do recurso ―in-zooming” chegando até três níveis de aproximação.
Foi optado por modelar a partir das utilizações que o jogador pode fazer no jogo, da
mesma forma que foi feito para o jogo ―Square Overflow‖. Com o mesmo ponto de
início da modelagem, é possível visualizar se uma maior complexidade do software
comporta essa mesma abordagem.
Figura 51 – Diagrama principal do jogo ―Blinky"
Fonte: autoria própria.
A Figura 51 mostra o principal diagrama do jogo ―Blinky‖. O objeto ―Elementos
71
estáticos do cenário‖ se trata de um conjunto de objetos que são fixos no cenário e
seus papéis servem apenas como referência: chão, plataformas e paredes. Existem
mais de um objeto ―Coelhos‖, ―Caixas‖ e ―Mágicos‖ em um nível, por isso foram, foram
representados como conjuntos de objetos. Com isso, o sistema tem quatorze objetos e
sete processos principais. Neste diagrama, como possui várias relações, foi utilizado o
recurso de cores, para melhorar a visibilidade das relações entre os objetos e
processos. A ordenação dos processos, começando do topo, está de acordo com a
definição dos requisitos. A disposição começa com ―Iniciar partida‖, que irá permitir a
execução dos demais processos, porque estes só ocorrem quando um nível é
carregado. Os demais processos foram representados lado a lado por serem
assíncronos.
A Figura 52 mostra o processo ―Iniciando partida‖ in-zoomed. O processo consiste
da transição de três cenas que são a tela inicial, a tela de tutorial e a chamada do
primeiro nível. A transição de uma cena pela outra ocorre pelo script customizado
―AnyKey‖, que recebe qualquer tecla do teclado como entrada. Quando o primeiro nível
é chamado, o ―GameManager‖ faz a inicialização dos textos da tela (―LifeCounterUI‘,
―RabbitCounterUI‖, ―LevelTextUI‖ e ―TotalPointsUI‖) e posiciona o Blinky na mesma
posição da ―Porta de saída‖.
A Figura 53 exibe o processo ―Movimentando Blinky‖ ampliado. Este processo
trata-se da movimentação do ―Blinky‖ pelas ações do jogador. Em um jogo de
plataforma bidimensional, os movimentos básicos são andar e pular. Devido ao
tamanho do cenário, foi optado por exibir apenas uma parte do cenário na tela, que
está atrelada à posição do Blinky. A movimentação da câmera é feita pelo script
―CameraFollow‖. Uma das condições pra mover o Blinky é que ele não esteja morto
(Died == false).
A Figura 54 exibe o subprocesso ―Pulando‖ ampliado. Este processo trata da
movimentação vertical do Blinky. Quando o jogador pressiona o botão de pulo ―Jump‖
(configurável) no teclado, e se o Blinky estiver aterrado (sobre o chão, plataforma ou
caixa), o Blinky recebe um impulso para cima. A engine Unity3D simula a gravidade,
então, com o tempo, o Blinky tende a perder velocidade e cair. O processo de pulo
ativa a animação de pulo que ocorre que ocorre por meio do parâmetro ―jump‖, do
componente ―Animator‖. Por fim, o processo emite o som de pulo.
72
Figura 52 - Diagrama ―Iniciando partida" do jogo ―Blinky"
Fonte: autoria própria.
73
Figura 53 - Diagrama ―Movimentando Blinky" do jogo ―Blinky"
Fonte: autoria própria.
Figura 54 - Diagrama ―Pulando" do jogo ―Blinky"
Fonte: autoria própria.
74
A Figura 55 exibe o processo ―Movimentando na horizontal‖ in-zoomed. Este
processo trata da movimentação horizontal do Blinky. O jogador pode tanto direcionar o
Blinky para esquerda ou direita, dando uma velocidade positiva ou negativa no eixo
horizontal. A posição da parede no cenário é uma das condições que delimita a
movimentação do personagem. E, logo após a movimentação, caso exista uma
inversão de sinal da velocidade, o processo se encarrega de ajustar a imagem e
acordo com a orientação do movimento.
Figura 55 - Diagrama ―Movimentando na horizontal" do jogo ―Blinky"
Fonte: autoria própria.
A Figura 56 trata-se do processo ―Pegando coelho‖ ampliado. Este processo
assim como ―Salvando coelho‖, ―Pegando caixa‖ e ―Morrendo‖, não tem a
representação do jogador no processo, porque ocorrem de forma independente.
Entretanto, a movimentação do Blinky pode, de forma indireta, ocasionar a execução
desses processos. Estes processos tem uma condição de execução, que podemos
75
chamar de ―colisão‖, que é quando duas áreas no plano 2D, que estão dentro um
determinado espaço, entram em contato. Para a verificação de ―colisões‖, como
referência para comparação, foram escolhidos os valores presentes no componente
―Transform‖, que detêm a referência do GameObject no espaço. No processo
―Pegando coelho‖, quando o Blinky entra em contato com um coelho que ainda não
esteja o seguindo, é emitido o som de coleta, e o coelho começa a seguir o Blinky,
adotando então a posição dele como referência. O gerenciamento do comportamento
do coelho é feito pelo Script ―RabbitBehavior‖.
Figura 56 - Diagrama ―Pegando coelho" do jogo ―Blinky"
Fonte: autoria própria.
A Figura 57 exibe o processo ―Salvando coelho‖ in-zoomed. O script
―GameManager‖ faz a execução de todo o processo. O subprocesso ―Contando pontos―
ocorre quando o Blinky entra em contato com a porta de saída e então, para cada
coelho que estava seguindo-o, é feita sua remoção do jogo e a ocorre a contabilização
de pontos. O subprocesso ―Atualizando tela‖ faz a atualização dos textos do contador
de pontos e contador de coelhos, que são os objetos dentro do ―Canvas‖ (O
GameObject que contém todos os elementos da interface do usuário). Como o objetivo
do jogador é fazer com que o ―Blinky‖ guie os coelhos para a saída, para que o jogador
avance para o próximo nível, o subprocesso ―Checando a condição de vitória‖ é
chamado por consequência. Esse subprocesso verifica se ainda existem coelhos no
cenário, caso não tenha, ele aciona o gerenciador de cenas ―SceneManager‖ que
76
encaminha a partida para a próximo nível, ou para a tela de ―GameOver‖, caso não
tenha um próximo nível.
Figura 57 - Diagrama ―Salvando coelho" do jogo ―Blinky"
Fonte: autoria própria.
77
A Figura 58 mostra o diagrama referente ao processo ―Pegando caixa‖. Este
processo ocorre quando o jogador, ao se movimentar com o Blinky pelo cenário, entre
em contato com um caixa. Então caso ele não esteja segurando uma caixa,de acordo
com o parâmetro ―Grabbed‖, o Blinky ―pega‖ a caixa e começa carregar ela. Deste
modo a caixa então fica ―presa‖ na mão do Blinky, na posição ―PivotHero‖.
Figura 58 - Diagrama ―Pegando caixa" do jogo ―Blinky"
Fonte: autoria própria.
A Figura 59 mostra o diagrama referente ao processo ―Arremessando caixa‖. Este
processo ocorre quando o jogador aciona um botão de ação (No Unity3D o botão é
configurável) de arremesso de caixa. Como pré-requisito para o subprocesso
―Arremessando caixa‖, o ―Blinky‖ precisa estar carregando uma caixa no momento que
o botão for pressionado. Assim que começa o arremesso, a caixa ganha um impulso
para frente e tende a cair com a gravidade. Além de emitir um som de arremesso, pode
acontecer da caixa ―colidir‖ com um ―Mágico‖ ou com uma ―Parede‖, assim cessando
todo o movimento horizontal.
78
Figura 59 - Diagrama ―Arremessando caixa" do jogo ―Blinky"
Fonte: autoria própria.
O subprocesso ―Matando Mágico‖, em detalhes na Figura 60, ocorre quando uma
caixa arremessada, ainda em movimento, entra em contato com um ―Mágico‖. O
―Mágico‖ atingido é destruído e é emitido um som. Depois de atingir o tempo
―RespawnTime‖, um novo ―Mágico‖ é criado na posição da porta de reaparecimento.
79
Figura 60 - Diagrama ―Matando Mágico" do jogo ―Blinky"
Fonte: autoria própria.
A Figura 61 exibe o processo ―Morrendo‖ in-zoomed. O jogador tem obstáculos
que são os ―Mágicos‖. O jogador deve evitar que um ―Mágico‖ entre em contato com o
―Blinky‖, pois irá perder vida e, se atingir o limite de vidas, poderá perder também a
partida do jogo. Para que o jogo crie esta condição, o software deve gerenciar os
movimentos do ―Mágico‖, tratar suas colisões dele e verificar se a partida acabou por
falta de vidas, encaminhando o jogador para a tela de ―GameOver‖.
O subprocesso ―Movimentando Mágico‖ é detalhado na Figura 62. O movimento
do Mágico ocorre de forma contínua em uma direção. Entretanto, caso o mágico colida
com uma parede, ele inverte sua direção, ou seja, inverte o sinal da velocidade
aplicada no eixo horizontal pelo subprocesso ―Invertendo direção‖. Outra situação
possível é o ―Mágico‖ pode ficar ―preso‖ em elementos do cenário, como caixas ou
coelhos. Então para evitar isso, quando o ―Mágico‖ colide com alguns desses objetos, o
script ―MagicianBehavior‖ aciona um temporizador e pega a referência da posição atual
80
do ―Mágico‖. Quando passa dois segundos, é verificado se a posição do mágico
mudou. Caso a posição não tenha mudado, é chamado o subprocesso ―Invertendo
direção‖ ou o ―Pulando o Mágico‖ para ―desprender‖ o ―Mágico‖. Assim o script
consegue garantir que o Mágico continue em movimento no cenário por meio da
chamada desses subprocessos. Adicionalmente, para aumentar o desafio, o ―Mágico‖,
ao colidir com um coelho, faz com que o coelho pare seguir o ―Blinky‖. O subprocesso
―Pulando o Mágico‖ não está detalhado, porém o processo é análogo ao do movimento
de pulo do ―Blinky‖, mudando apenas a condição de chamada.
Figura 61 - Diagrama ―Morrendo" do jogo ―Blinky"
Fonte: autoria própria.
81
Figura 62 - Diagrama ―Movimentando Mágico in-zoomed" do jogo ―Blinky"
Fonte: autoria própria.
A Figura 63 representa o subprocesso ―Matando Blinky‖ in-zoomed. Este
subprocesso decorre do encontro com o objeto filho do ―Mágico‖, chamado
―MagicianSight‖, com o Blinky. O ―MagicianSight‖ representa o campo de visão do
Mágico, assim o ―Mágico‖ irá colidir com o ―Blinky‖ apenas pela sua a orientação
frontal. Então, quando o campo de visão do ―Mágico‖ encontra o ―Blinky‖, o ―Mágico‖
―mata‖ o ―Blinky‖, desencadeando cinco subprocessos: o subprocesso ―Liberando
coelhos‖ faz que todos os coelhos que estavam seguindo o ―Blinky‖ parem de segui-lo,
82
é emitido um som, a posição do ―Blinky‖ vai para a mesma posição da porta de saída, o
contador de vida é reduzido e todos os ―Mágicos‖ são destruídos. Entretanto, quando a
quantidade de ―Mágicos‖ é menor que o total, novos ―Mágicos‖ vão reaparecer, por
causa da execução do subprocesso ―Reaparecendo Mágico‖, representado na Figura
60, comentada anteriormente.
Figura 63 - Diagrama ―Matando Blinky" do jogo ―Blinky‖
Fonte: autoria própria.
83
Com a apresentação dos diagramas desenvolvidos, no próximo capítulo será
abordada a programação envolvida no jogo e, após isso, é apresentada a análise dos
diagramas gerados.
5.4. Programação do jogo ―Blinky‖
O jogo ―Blinky‖ foi realizado com o auxílio da engine Unity3D. Os eventos de
colisão, simulação de gravidade, velocidade e aceleração, controlador de animação,
simulador de corpo rígido, temporizador, player de áudio, câmera, renderizador de
imagem, painel de interface de usuário, gerenciador de cenas e gerenciador de
entradas de comandos do jogador foram fornecidos e controlados pela própria engine.
Desta forma, os diagramas não representam em detalhes o funcionamento destes
componentes. Os scripts desenvolvidos foram escritos na linguagem C#. O controlador
de animação utiliza a máquina de estados finita para fazer a transição entre cada
animação.
O executável com a versão final do jogo ―Blinky‖ está disponível online para
download (Kovalski, 2019b).
5.5. Discussão sobre o jogo ―Blinky‖
Foram gerados vinte diagramas OPM para o jogo ―Blinky‖, com certo nível de
detalhamento. O intuito foi abstrair e ilustrar os principais objetos, processos e suas
relações no jogo. A Figura 64 foi extraída do OPCAT e mostra a hierarquia dos
diagramas gerados para o jogo ―Blinky‖, que correspondem à relação in-zooming entre
os diagramas. Conforme era esperado, ao comparar com o jogo ―Square Overflow‖, o
jogo ―Blinky‖ teve uma demanda maior de diagramas, devido a seu tamanho e
complexidade. Durante o processo de modelagem, o tempo utilizado para gerar os
diagramas OPM foi, em média, similar ao tempo utilizado para o jogo ―Square
Overflow‖. Então, observa-se que um modelador que já gerou os diagramas UML, do
mesmo software, não desenvolve dos diagramas OPM com mais agilidade. Isso pode
indicar que, pelo menos, em softwares de jogos digitais de pequeno porte, a OPM
84
permite uma modelagem dos requisitos de forma fluída, mesmo sem outras
referências.
A OPM demonstrou uma modelagem consistente em um jogo digital mais
complexo. Como os diagramas OPM suportam níveis de detalhamento, é provável que
suporte um jogo de grande porte e mais complexo, pois, pelo menos em partes,
podem-se detalhar apenas os processos relevantes para o projeto. Em comparação
com a UML que utiliza, por exemplo, diagramas de Classe, o nível de detalhamento
algoritmo acaba sendo uma exigência.
Figura 64 - Hierarquia dos diagramas do jogo "Blinky"
Fonte: autoria própria.
Com a geração dos diagramas do jogo ―Square Overflow‖ e ―Blinky‖, foram
observados pontos durante sua aplicação. A análise destes pontos permitiu
realizar um conjunto de orientações, que são descritas no próximo capítulo.
85
6. PROPOSTA DE ORIENTAÇÕES SOBRE A OPM EM JOGOS
DIGITAIS
Analisando os diagramas que foram construídos para o desenvolvimento de jogos
digitais, foram observadas diversas características que compõem sua estrutura.
Propõe-se, como forma de guiar a modelagem OPM para um jogo digital, orientações
de uma possível forma de realizar a modelagem. Desta forma, as orientações
propostas formam um conjunto de tópicos que podem ser seguidos passo a passo.
A seguir são listadas as orientações para o desenvolvimento de diagramas OPM
para um jogo digital:
1. Modelar todos os objetos que serão utilizados no jogo
Um objeto é algo que, uma vez construído, existe ou pode existir física ou
informaticamente. Em todos os jogos digitais existem objetos que constituem as cenas
e que têm participação (estática ou dinâmica) no desenrolar das ações. Cada um
destes objetos do jogo seria modelado em OPM na forma de um "Objeto Informático".
Objetos como um texto na tela, um botão, um personagem ou um código são exemplos
de objetos em um jogo digital.
Objetos replicáveis podem ser representados por um conjunto, agrupados em um
objeto específico, com um nome parecido, por exemplo, utilizando no plural. A Figura
65 mostra um exemplo do uso do recurso de agrupamento. O objeto ―Árvores‖ é um
conjunto de objetos ―Árvore‖. Para exibir a relação utiliza-se o símbolo de composição
(triângulo preto preenchido) apontando para o objeto do conjunto, mostrando que uma
―Árvore‖ é uma parte de ―Árvores‖. O agrupamento, além de mostrar que existem vários
objetos do mesmo tipo, permite criar relações entre processos e seus conjuntos de
objetos, indicando o que todo objeto da composição será influenciado. O objeto
―Cenário de floresta‖ é composto pelos objetos ―Lago‖, ―Chão‖ e ―Árvores‖. Quando o
processo ―Criando cenário‖ é executado, é criado o objeto ―Cenário de floresta‖ e
também todos os seus objetos associados demonstrados no diagrama. Uma das regras
deste diagrama é que para existir um objeto ―Cenário de floresta‖ é preciso ter os
objetos ―Lago‖, ―Chão‖ e ―Árvores‖ e o para o objeto ―Árvores‖ existir tem que haver
pelo menos um objeto ―Árvore‖.
86
Figura 65 – Diagrama ―Criando cenário‖
Fonte: autoria própria.
2. Definir e criar os estados de cada objeto
Alguns objetos sofrerão mudanças de estado ao se relacionar com os processos.
Sendo assim, é necessário verificar e criar todos os estados de cada objeto. No
OPCAT é possível exibir e ocultar os estados de um objeto em cada diagrama. Assim,
podem-se exibir somente os estados que forem relevantes em cada contexto do
diagrama. A Figura 66 mostra um exemplo da representação dos estados de um
objeto. O estado ―fechado‖ é o estado inicial e é caracterizado por uma borda grossa.
Um objeto assume o estado inicial assim que é criado. O estado ―aberto‖ é um estado
comum e é caracterizado por uma borda simples. Um objeto pode assumir um estado
comum a qualquer momento, a não ser que ele esteja em seu estado final. O estado
―destruído‖ é o estado final do objeto ―Baú‖ e é caracterizado por uma borda dupla.
Quando um objeto assume o estado final, não muda mais de estado.
87
Figura 66 – Diagrama ―Estados do Baú‖
Fonte: autoria própria.
3. Representar o jogador
O jogador, que é um objeto físico (representado com um sombreado), é quem irá
controlar o jogo. É provável que o jogador utilize um objeto físico para controlar o jogo
(como um teclado ou mouse), atuando como entrada das informações. Pode ser
necessário também criar um objeto informático representando o jogador, como por
exemplo, o ―Personagem‖ da Figura 67. A Figura 67 mostra um exemplo de um
processo que é inicializado quando o jogador aciona um controlador físico. O processo
atua em um objeto ―Personagem‖ que representa o ―Jogador‖ no jogo.
88
Figura 67 – Diagrama ―Movimentando personagem para frente‖
Fonte: autoria própria.
4. Modelar os Macroprocessos do Jogo
Na UML emprega-se a visão de casos de uso para descrever as utilizações
pretendidas para o software. Na OPM, esse conceito não existe, pois a modelagem é
focada em processos. Assim, sugere-se que a modelagem se inicie pela determinação
dos processos de alto nível (macroprocessos) do jogo. Eles representam as "grandes"
(i.e., mais abstratas) atividades do jogo. Na sequência, os macroprocessos serão
detalhados em subprocessos. Para obter o conjunto correspondente às utilizações do
89
jogador é necessário adicionar também os processos que não ocorrem diretamente
pelo jogador. Dentre as utilizações não controladas pelo jogador, tem-se, por exemplo,
os processos relacionados às condições de derrota. Para perder uma partida, basta
que um ou mais ―obstáculos‖ atinjam uma condição determinada. Entretanto, existe um
objeto, que não é o jogador, que possui o código que controla a partida, fazendo a
verificação das condições de derrota. Um exemplo deste objeto é o ―GameManager‖
que foi utilizado na modelagem dos dois jogos.
5. Identificar os processos que o jogador irá acionar pelo controlador
O detalhamento dos macroprocessos pode se basear na mecânica pretendida
para o jogo. A Figura 67, citada na terceira orientação, mostra um exemplo de processo
que é inicializado por uma ação do jogador. A inicialização destes processos é
representada por eventos (link com a letra ―e‖), pois ―eventualmente‖ as entradas serão
disparadas pelo jogador. Para cada um desses processos deve-se adicionar a relação
de controle (círculo preenchido) com o jogador. Além do jogador, que é um objeto
físico, espera-se que exista pelo menos um objeto informático, também com relação de
controle, que processe as entradas de forma lógica. Se existir um objeto informático
representando o jogador no jogo também existirão processos entre as entradas do
controlador e este objeto.
6. Verificar e representar os processos relacionados aos ―botões
informáticos‖ de uma tela (interface do usuário)
São os processos relacionados aos botões que, ao serem acionados, disparam
uma funcionalidade. Um exemplo seria um botão na tela, que pode ser acionado
através de um cursor.
7. Posicionar os processos de acordo com a ordem de execução
Os processos são executados seguindo a partir da posição do topo para baixo.
Os processos que podem ocorrer paralelamente são representados lado a lado. A
Figura 68 mostra um diagrama de um processo ampliado ―in-zoomed‖ contendo um
exemplo das duas formas de posicionamento de processos. O processo ―Comprando
item‖ é composto por uma sequência de subprocessos. O processo ―Verificando saldo
do jogador‖ ocorre primeiro, em seguida os processos ―Adicionando item no inventário
do jogador‖ e ―Debitando saldo do jogador‖ são executados ao mesmo tempo e, por
90
último, ocorre o processo ―Atualizando os dados na tela‖.
Figura 68 – Diagrama ―Comprando item‖
Fonte: autoria própria.
8. Detalhar os processos
Com os macroprocessos criados, pode-se, por meio do recurso de ―in-zooming‖,
detalhar os processos decorrentes até um nível desejado. Pode-se ter uma situação,
por exemplo, que um algoritmo não foi bem detalhado, porque os detalhes de sua
implementação pode não ser relevante para o funcionamento do software. O
posicionamento e a ampliação dos processos tendem a seguir a mesma estrutura
lógica dos scripts. Por exemplo, quando uma função chama outra função auxiliar, esta
função auxiliar acaba sendo detalhada por ―in-zooming‖. Para as funções com
chamadas síncronas, os posicionamentos verticais dos processos também tendem a
seguir a mesma sequência do script.
9. Verificar a consistência dos diagramas
Os diagramas consistentes têm todos os objetos e seus estados com pelo menos
uma relação com algum processo. Outro ponto importante é verificar que todos os
processos são controlados por algum script com funções, que fica em algum objeto.
91
Então todos os processos devem ter pelo menos uma relação de controle (círculo
preenchido), direta ou indireta (herdada pelo ―in-zooming‖) com pelo menos um objeto.
Esses passos devem permitir uma modelagem apropriada para um jogo digital. A
modelagem para os dois jogos foi realizada a partir de suas utilizações. Para dar outra
forma de iniciar a modelagem de um jogo digital, foi criado um diagrama de modelo
funcional para servir como ponto de partida. A Figura 65 mostra um diagrama que pode
servir como base para a modelagem. O diagrama mostra de forma genérica alguns
grupos de objetos e conjuntos de processos que um jogo contém.
Figura 69 – Diagrama de um modelo funcional de jogo digital genérico
Fonte: autoria própria.
92
O processo ―Processando as entradas do jogador‖, através do ―in-zooming‖, pode
agrupar os processos que são os que interpretam as ações do jogador (citados na
orientação 4). O processo ―Gerenciando transição de telas do jogo‖, através do ―in-
zooming‖, pode agrupar os processos sobre o fluxo do jogo, que seria, por exemplo, a
―tela inicial‖, os ―níveis‖ e ―tela de fim de jogo‖. Estes processos costumam ter as regras
gerais do jogo, como condição de vitória e de derrota. Por fim, o processo
―Gerenciando objetos controláveis pelo jogador‖, através do ―in-zooming‖, pode agrupar
os demais processos que o jogador não controla diretamente. Estes processos contêm
funcionalidades mais específicas do jogo, que estão relacionadas a cada objeto.
O diagrama já exibe o ―Jogador‖ (citado na orientação 3) e prevê uma possível
representação do jogador no jogo. O modelo também mostra objetos que servem de
agrupamentos para objetos como: os de elementos da tela, os que fazem papel de
objetivo, os que fazem papel de obstáculo e os que compõem um cenário. Uma tela
pode conter objetos ―informativos‖, como por exemplo, um texto ou imagem, e
―funcionais‖, como por exemplo, um botão. O objeto ―Objetivos‖ agrupa os objetos
relacionados às condições de vitória. O objeto ―Obstáculos‖ agrupa os objetos
relacionados às condições de derrota. O objeto ―Cenário‖ contêm os demais objetos,
que não tem funcionalidade e são fixos em um espaço dimensional.
Com as orientações e um diagrama como modelo, é esperada uma modelagem
OPM adequada para um jogo digital. Entretanto, como existem vários tipos de jogos
digitais e podendo ter diversas complexidades, outros estudos da aplicação da OPM
com este tipo de software podem permitir a criação de um conjunto de orientações
mais amadurecido. Para validar o conjunto de orientações, sugere-se fazer uma
avaliação a partir da aplicação delas.
93
7. CONCLUSÃO E CONSIDERAÇÕES FINAIS
De acordo com as pesquisas realizadas, o desenvolvimento de software de jogos
digitais carece de métodos de modelagem compatíveis com as suas necessidades.
Uma vez que o uso da UML não tem sido uma opção convincente para os
desenvolvedores de jogos, a OPM pode ser explorada para este fim.
Neste trabalho de conclusão de curso foram feitos dois jogos digitais e, a partir
deles, foi possível fazer a correlação das características e alternativas de modelagem
da OPM no desenvolvimento de jogos com outras abordagens de modelagem,
notadamente a UML. Também foi proposto um conjunto de orientações para uso geral
da OPM na modelagem de software de jogos digitais e desta forma, foram cumpridos
os objetivos estabelecidos.
Para a criação dos dois jogos digitais foi realizado um estudo aprofundado das
metodologias UML e OPM e também foi feito um estudo sobre os aspectos que
envolvem o desenvolvimento de um software de jogo digital. Através desses conceitos,
foram definidos os requisitos dos jogos digitais e, por meio deles, foram feitas as
modelagens. A partir dos diagramas gerados, foi então possível o desenvolvimento dos
dois jogos digitais. Os mesmos foram desenvolvidos com a engine Unity3D, utilizando a
linguagem C# para a programação dos scripts.
O desenvolvimento do primeiro jogo digital, denominado ―Square Overflow‖,
permitiu realizar a comparação da aplicação da OPM com a UML. Concluiu-se que a
OPM, além de se mostrar adequada para a modelagem de softwares de jogos digitais,
demonstrou ser melhor que a UML em diversos aspectos, como sua maior simplicidade
de manutenção e sua representatividade visual e textual. A OPM possui apenas um
tipo de diagrama sendo que seu total de símbolos é menor que a UML e o seu
desenvolvimento gera um texto equivalente ao diagrama. Então, entende-se que o
modelador, trabalhando com menos tipos de informações, com apoio de textos e
detalhando conforme sua necessidade, terá uma visão do sistema mais representativa
e terá maior agilidade na manutenção dos seus diagramas.
O desenvolvimento do segundo jogo digital, denominado ―Blinky‖, forneceu mais
uma visão da aplicação da modelagem OPM em jogos digitais. Desta forma, a partir da
análise das características da aplicação da OPM, nos dois jogos desenvolvidos, e de
conceitos gerais da OPM, foi possível criar um conjunto de nove orientações para uso
geral da OPM na modelagem de software de jogos digitais.
94
As orientações propostas, com exemplos, seguem uma ordem passo a passo
partindo da identificação dos objetos e seus estados e, então, identificado os
macroprocessos do jogo e detalhando-os. As orientações enfatizam os objetos e os
processos comumente encontrados em um software de jogo digital, assim,
aproximando a OPM do contexto proposto. Acredita-se que, com essas orientações, o
modelador consiga realizar uma modelagem com maior facilidade e com uma
representatividade consistente e adequada para um software de jogo digital.
Este trabalho de conclusão de curso aplicou conhecimentos de várias disciplinas
do curso de Bacharelado em Sistemas de Informação da UTFPR. Algumas destas
disciplinas que estão diretamente associadas são as de engenharia de software,
programação, análise e modelagem. Pode-se observar que o conhecimento adquirido
nestas disciplinas forneceram os fundamentos necessários para o cumprimento dos
objetivos do projeto.
Espera-se que este trabalho possa trazer contribuições tanto para a área de
estudo da Tecnologia da Informação, com a apresentação do correlacionamento das
modelagens UML e OPM, quanto para a área de produção de jogos digitais, com o
conjunto de orientações para o uso geral da OPM na modelagem de software de jogos
digitais. Com o desenvolvimento dos jogos a partir dos diagramas OPM e com o
conjunto de orientações, espera-se que este estudo venha a motivar o uso da OPM na
área de desenvolvimento de jogos. Para trabalhos futuros, sugere-se um estudo com a
aplicação da OPM em outros tipos de jogos digitais ou com complexidades maiores.
95
8. REFERÊNCIAS
Alves, Lynn e Santos, William. A Aplicação da Linguagem de Modelagem
Unificada (UML): Novas Perspectivas para o Desenvolvimento de Games
Educacionais. 2015. Anais do Seminário de Jogos Eletrônicos, Educação e
Comunicação 1.1.
Ampatzoglou, Apostolos, e Alexander Chatzigeorgiou. Evaluation of object-
oriented design patterns in game development. 2007. Information e Software
Technology 49.5: 445-454. Disponível em:
<http://www.sciencedirect.com/science/article/pii/S0950584906000929> Acesso em: 28
de abril de 2017.
Barros, R. Análise de Metodologias de Desenvolvimento de Software
aplicadas ao Desenvolvimento de Jogos Eletrônicos. Trabalho de Conclusão de
Curso (Ciências da Computação) - Universidade Federal de Pernambuco. 2007.
Disponível em: <https://www.cin.ufpe.br/~tg/2007-1/rlbb.pdf> Acesso em: 29 de abril de
2017.
Bethke, Erik. Game development e production. Wordware Publishing, Inc.,
2003.
Carvalho, E. A. Os 5 Desprezíveis: desenvolvimento de um jogo eletrônico
utilizando os princípios de Engenharia de Software. 2013. Trabalho de
conclusão de graduação em Engenharia de Software, Universidade Federal de Brasília,
Brasília. Disponível em:
<https://repositorio.ufpb.br/jspui/handle/123456789/2860> Acesso em: 23 de
agosto de 2019.
Costa, Carlos Alberto. A aplicação da linguagem de modelagem unificada
(UML) para o suporte ao projeto de sistemas computacionais dentro de um
modelo de referência. Gestão & Produção 8.1 (2001): 19-36. Disponível em:
<http://www.scielo.br/scielo.php?pid=S0104-
96
530X2001000100003&script=sci_arttext&tlng=es> Acesso em: 02 de dezembro de
2019.
Demachy, T. Extreme Game Development: Right on Time, Every Time. 2003.
Disponível em:
<http://www.gamasutra.com/view/feature/131236/extreme_game_development_right_o
n_.php> Acesso em: 29 de abril de 2017
BNDES. Relatório Final: Mapeamento da Indústria Brasileira e global de
jogos. 2014. Disponível em:
<http://www.bndes.gov.br/SiteBNDES/bndes/bndes_pt/Galerias/Arquivos/
conhecimento/seminario/seminario_mapeamento_industria_games042014_Relatorio_F
inal.pdf> Acesso em: 23 de abril de 2017.
Dori, D. 1995. Object-process analysis: Maintaining the balance between
system structure e behavior. J. Logic Computation 5, 2 (April), 227-249.
Dori, Dov, e Edward Crawley. Towards a common computational synthesis
framework with object-process methodology. Proceedings of Computational
Synthesis, AAAI Spring Symposium, Stanford, CA. 2003. Disponível em:
<http://www.aaai.org/Papers/Symposia/Spring/2003/SS-03-02/SS03-02-008.pdf>
Acesso em: 18 de abril de 2017.
Dori, Dov, et al. OPCAT - An Object-Process CASE Tool for OPM-Based
Conceptual Modelling. First International Conference on Modelling e Management of
Engineering Processes. 2010. Disponível em: <http://esml.iem.technion.ac.il/wp-
content/uploads/2011/08/OPCAT-Description-and-Demo-to-MMEP-2010-Cambridge-
UK-DOC.pdf> Acesso em: 18 de abril de 2017.
Dori, Dov. e Peleg M. The model multiplicity problem: experimenting with
real-time specification methods, in IEEE Transactions on Software Engineering, vol.
26, no. 8, pp. 742-759, Aug 2000. Disponível em:
<http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=879812&isnumber=19036>
Acesso em: 28 de abril de 2017.
97
Dori, Dov. Object Process Methodology as a Business Process Modeling
Tool. ECIS 2000 Proceedings (2000): 172. Disponível em:
<http://aisel.aisnet.org/cgi/viewcontent.cgi?article=1199&context=ecis2000> Acesso
em: 18 de abril de 2017.
Dori, Dov. Object Process Methodology—a Holistic Systems Paradigm,
Springer, Berlin, Heidelberg, New York, 2002.
Dori, Dov. Object-process methodology applied to modeling credit card
transactions. Journal of Database Management 12.1 (2001): 4. Disponível em:
<http://search.proquest.com/docview/199597307?pq-origsite=gscholar> Acesso em: 18
de abril de 2017.
Fabichak, M. O uso de método Scrum em empresas de desenvolvimento de
software de jogos. 2009. Disponível em:< http://docplayer.com.br/131462-O-uso-de-
metodo-scrum-em-empresas-de-desenvolvimento-de-software-de-jogos.html> Acesso
em: 30 de abril de 2017.
Flynt, J. Software Engineering for Game Developers. Course Technology 2005.
Furtado, André Wilson Brotto. Domain-Specific Game Development. 2012.
Disponível em: <http://repositorio.ufpe.br/handle/123456789/2165> Acesso em: 29 de
abril de 2017.
Flood, K. Game Unified Process. 2013. Disponível em:
<http://www.gamasutra.com/view/feature/2827/extremegamedevelopmentrighton.php>
Acesso em: 30 de abril de 2017
Hamada, Olívia. Considerações sobre o desenvolvimento de jogos por meio
do framework Scrum. 2016. REFAS-Revista Fatec Zona Sul 2.2: 1-19. Disponível em:
<http://www.revistarefas.com.br/index.php/RevFATECZS/article/view/44> Acesso em:
30 de abril de 2017.
98
Kaimann, D., Stroh‐Maraun, N., e Cox, J. Variety in the video game industry:
An empirical study of the Wundt curve. 2018. Disponível em:
<https://onlinelibrary.wiley.com/doi/pdf/10.1002/mde.2909>
Acesso em: 14 de abril de 2019.
Kovalski, Rodrigo Luiz, 2019a. Square Overflow. Disponível em:
<https://redproxy.itch.io/square-overflow> Acesso em: 13 de novembro de 2019.
Kovalski, Rodrigo Luiz, 2019b. Blinky. Disponível em: <https://redproxy.itch.io/blinky> Acesso em: 13 de novembro de 2019.
Lima, Anderson da Silva. Utilizando o gênero do jogo para agilizar a
modelagem UML de jogos 3D. 2013. Anais do Encontro Regional de Comutação e
Sistemas de Informação. Disponível em:
<http://marconeds.com.br/eventos/artigos/resumo/112178_1.pdf> Acesso em: 30 de
abril de 2017.
Liu, Hong e Glunch, David P. 2004. Conceptual modeling with the object-
process methodology in software architecture. J. Comput. Sci. Coll. 19, 3 (January
2004), 10-21. Disponível em: <http://dl.acm.org/citation.cfm?id=948836> Acesso em:
27 de abril de 2017.
Mordecai, Yaniv, e Dori, D. Conceptual Modeling of System‐Based Decision‐
Making. INCOSE International Symposium. Vol. 24. No. 1. 2014. Disponível em:
<https://www.researchgate.net/publication/270510325_Conceptual_Modeling_of_Syste
m-Based_Decision-Making> Acesso em: 02 de maio de 2017.
OPCAT Systems. Object-Process CASE tool. [Online] Versão 4.0. 17 de julho de
2011. Disponível em: <http://esml.iem.technion.ac.il/> Acesso em: 02 de maio de 2017.
Peleg, Mor, e Dori, D. Extending the object-process methodology to handle
real-time systems. JOOP 11.8 (1999): 53-58. Disponível em:
<is.haifa.ac.il/~morpeleg/pubs/TEL_fig.pdf> Acesso em: 28 de abril de 2017.
99
Perelman, Valeriya. Operational Semantics for Object-Process Methodology.
Submitted to the Senate of the Technion — Israel Institute of Technology. Kislev 5772
Haifa November 2011. Disponível em: <http://esml.iem.technion.ac.il/wp-
content/uploads/2011/02/Lera-PhD-thesis-final.pdf> Acesso em: 1 de maio 2017.
Ramsin, Raman e Paige, Richard F. 2008. Process-centered review of object
oriented software development methodologies. ACM Comput. Surv. 40, 1, Article 3
(February 2008), 89 pages. Disponível em:
<http://dx.doi.org/10.1145/1322432.1322435> Acesso em: 14 de abril de 2019.
Reinhartz-Berger, Iris, Arnon Sturm e Dov Dori. Modeling Events in Object-
Process Methodology e in Statecharts. The Israeli Workshop on Programming
Languages e Development Environment. 2002. Disponível em:
<http://www.academia.edu/download/31242429/EventsHandlingInOPM.pdf> Acesso
em: 27 de abril de 2017.
Reinhartz-Berger, Iris, e Dori, D. Object-Process Methodology (OPM) vs. UML -
a Code Generation Perspective. CAiSE Workshops. 2004. Disponível em:
<https://www.researchgate.net/publication/220920423_Object-
Process_Methodology_OPM_vs_UML_-_a_Code_Generation_Perspective> Acesso
em: 2 de maio de 2017.
Schwab, Brian. AI Game Engine Programming. 2009. Course
Technology/Cengage Learning.
Soffer, P., Golany, B., Dori, D., Wand, Y. Modelling off-the-shelf information
systems requirements: an ontological approach, Requirements Engineering 183
(2001) 198. Disponível em: <https://web.iem.technion.ac.il/images/user-
files/golany/papers/RE_01.pdf> Acesso em: 28 de abril de 2017.
Soffer, Pnina, Boaz Golany, e Dov Dori. Aligning an ERP system with
enterprise requirements: An object-process based approach. Computers in
Industry 56.6 (2005): 639-662. Disponível em:
<http://www.sciencedirect.com/science/article/pii/S0166361505000771> Acesso em: 18
100
de abril de 2017.
Sturm, A., Dori, D. e Shehory, O., An Object-Process-Based Modeling
Language for Multiagent Systems, in IEEE Transactions on Systems, Man, e
Cybernetics, Part C (Applications e Reviews), vol. 40, no. 2, pp. 227-241, março de
2010. doi: 10.1109/TSMCC.2009.2037133. Disponível em:
<http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5398876&isnumber=54158
39> Acesso em: 27 de abril de 2017.
Tenzer, J., Improving UML design tools by formal games. Proceedings. 26th
International Conference on Software Engineering, 2004, pp. 75-77. doi:
10.1109/ICSE.2004.1317428. Disponível em:
<http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1317428&isnumber=29176
> Acesso em: 30 de abril de 2017.
Tenzer, Jennifer, e Stevens, Perdita. GUIDE: Games with UML for interactive
design exploration. Knowledge-Based Systems 20.7 (2007): 652-670. Disponível em:
<http://www.sciencedirect.com/science/article/pii/S0950705107000548> Acesso em: 28
de abril de 2017.
Unity Technologies. 2009. Unity - Game Engine [Online]. Versão 5.6.f03.
Disponível em: <https://unity3d.com/> Acesso em: 02 de maio de 2017.
Wenyin, Liu, e Dov Dori. Object-Process diagrams as an explicit algorithm-
specification tool. JOURNAL OF OBJECT ORIENTED PROGRAMMING 12 (1999):
52-59. Disponível em: <https://www.microsoft.com/en-us/research/wp-
content/uploads/2016/02/diagrams_explicit_algorithm.doc> Acesso em: 28 de abril de
2017.
Vision, Change. Astah Community. 2012. Disponível em:
<http://astah.net/editions/community> Acesso em: 28 de abril de 2017.
101
9. APÊNDICE A – CÓDIGOS DOS SCRIPTS DO JOGO ―SQUARE
OVERFLOW‖
GameManager.cs
using UnityEngine; using UnityEngine.UI; //Game Manager faz o gerenciamento das telas e níveis do jogo public class GameManager : MonoBehaviour { public int initialLines = 3; public int initialColumns = 2; public int limitErrors = 3; public int currentLines; public int currentColumns; public int totalPoints = 0; private bool toggleAxis = true; public int currentErrors = 0; public static int currentHits = 0; public int sizeLines; public int sizeColumns; public int totalSquares; public int numberOfPatterns; private bool[,] patternMap; public int offSetX = 10; public int offSetY = 10; public int offSetAdjustamentXDefault = 266; public int offSetAdjustamentYDefault = 150; public int offSetAdjustamentX = 272; public int offSetAdjustamentY = 150; public int offSetTile = 30; //Variáveis para referência pois as funções alteram diretamente nas variáveis public Canvas gameCanvas; public GameObject errorSquare; public GameObject patternSquare; public GameObject[] squareObjects; public Text infoGameUI; public GameObject titleUI; public Text pointsUI; public Text errorUI; public Button nextLevelButton; public Button playButton; //Função modifica os parametros para construir novo nível public void nextLevel() { //Adiciona alternadamente as linhas e colunas e faz ajuste de posição na tela if (toggleAxis == true) { currentColumns++; offSetAdjustamentY -= 10; toggleAxis = false; } else { currentLines++; offSetAdjustamentX -= 16; toggleAxis = true; } sizeColumns = initialColumns + currentColumns; sizeLines = initialLines + currentLines; //Definindo uma matriz de padrões patternMap = new bool[sizeLines, sizeColumns]; //Definindo o número de padrões que serão inseridos
102
totalSquares = (sizeLines * sizeColumns); numberOfPatterns = totalSquares / 3; //Variáveis auxiliares para sorteio do padrão int remaningPatterns = numberOfPatterns; int randomX; int randomY; while (remaningPatterns > 0) { //Função que faz o sorteio baseado nos limites dados randomX = Random.Range(0, sizeLines); randomY = Random.Range(0, sizeColumns); //Impede padrão seja marcado mais de uma vez na mesma posição if (patternMap[randomX, randomY] == false) { patternMap[randomX, randomY] = true; remaningPatterns--; } } //Criando os quadrados //Variaveis para auxiliar a identificação dos quadrados int positionY = 0; int positionX = 0; //Instancia os quadrados conforme a matriz de padrões for (int y = 0; y < sizeColumns; y++) { for (int x = 0; x < sizeLines; x++) { //Atualiza a posição do novo quadrado através de um objeto Vector que tem as coordenadas x, y e z Vector3 actualPosition = patternSquare.transform.position; actualPosition.x = (x * offSetTile) + offSetX + offSetAdjustamentX; actualPosition.y = (y * offSetTile) + offSetY + offSetAdjustamentY; actualPosition.z = 10; GameObject newSquareInstance; //Checa se é padrão if (patternMap[x, y] == true) { newSquareInstance = Instantiate(patternSquare) as GameObject; } else { newSquareInstance = Instantiate(errorSquare) as GameObject; } //Define o nome do novo quadrados newSquareInstance.name = "Square Y" + positionY + " X " + positionX; //Adiciona uma etiqueta para auxiliar a busca dos objetos que serão destruídos no final da fase newSquareInstance.tag = "ObjectToDestroy"; //Posiciona dentro do Canvas para que o unity renderize o botão corretamente newSquareInstance.transform.SetParent(gameCanvas.transform, false); newSquareInstance.transform.position = actualPosition; positionX++; } positionY++; } } //Checa o padrão do quadrado e encaminha para o procedimento correspondente public void selectedSquare(bool pattern) { if (pattern) { countPoint(); } else {
103
countError(); } } //Realiza diversas ações relacionadas a um padrão selecionado corretamente public void countPoint() { //Atualiza os pontos currentHits++; totalPoints++; //Atualiza a tela pointsUI.text = "Pontos: " + totalPoints; //Em caso de conclusão de fase if (numberOfPatterns <= currentHits) { //Limpa a tela GameObject[] squareObjects = GameObject.FindGameObjectsWithTag("ObjectToDestroy"); int lenght = squareObjects.Length; for (int i = 0; i < lenght; i++) { Destroy(squareObjects[i]); } //Atualiza a tela de erros errorUI.text = "Erros: 0"; infoGameUI.text = "Muito bom! Total de pontos: " + totalPoints; //Exibe um botão para que o jogador solicite uma nova fase nextLevelButton.gameObject.SetActive(true); //Reseta as ações da fase da fase currentErrors = 0; currentHits = 0; } } //Realiza diversas ações relacionadas a seleção errada public void countError() { //Atualiza os valores e a interface currentErrors++; errorUI.text = "Erros: " + currentErrors; //Checa se o jogador excedeu o limite de erros if (limitErrors <= currentErrors) { //Limpa a tela GameObject[] squareObjects = GameObject.FindGameObjectsWithTag("ObjectToDestroy"); int lenght = squareObjects.Length; for (int i = 0; i < lenght; i++) { Destroy(squareObjects[i]); } //Exibe o botão de jogar novamente playButton.gameObject.SetActive(true); //Reseta as ações para um novo jogo currentErrors = 0; currentHits = 0; offSetAdjustamentY = offSetAdjustamentYDefault; offSetAdjustamentX = offSetAdjustamentXDefault; currentColumns = 0; currentLines = 0; toggleAxis = true; infoGameUI.text = "Fim de jogo! Total de pontos: " + totalPoints; titleUI.SetActive(true); } } }
104
SquareManager.cs
using System.Collections; using UnityEngine; using UnityEngine.UI; // Este script gerencia requisitos visuais do quadrado public class SquareButton : MonoBehaviour { public bool pattern; public bool selected; public Sprite standardFrame; public Sprite selectedFrame; public GameObject itself; //Realiza a transição inicial da aparencia do quadrado void Start() { // Impede que o quadrados originais interajam com o jogo pois serão clonados várias vezes if (!System.String.Equals(itself.name, "SquarePatternObject") && !System.String.Equals(itself.name,
"ErrorSquareObject")) { //Impede ações no botão GetComponent<Button>().interactable = false; //Realiza a espera e conclui o padrão StartCoroutine(showingFrame()); } } IEnumerator showingFrame() { //Aguarda por segundos yield return new WaitForSeconds(2); //Torna o botão clicável GetComponent<Button>().interactable = true; //Esconde o padrão if (pattern == true) { GetComponent<Image>().sprite = standardFrame; } } }
quitAplication.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class quitApplication : MonoBehaviour { //Função que encerra a aplicação. Ela é chamada acionando o botão ExitGameButton. public void quitGame() { Application.Quit(); } }
105
10. APÊNDICE B – CÓDIGOS DOS SCRIPTS DO JOGO ―BLINKY‖
AnyKey.cs
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class AnyKey : MonoBehaviour { public int sceneIndex; public string sceneName; // Verifica se um tecla foi ativada e caminha para a próxima tela (scene) void FixedUpdate () { if (Input.anyKey) { if (!String.IsNullOrEmpty(sceneName)) { SceneManager.LoadScene(sceneName); }else if (sceneIndex > 0) { SceneManager.LoadScene(sceneIndex); } } } }
BlinkyBehavior.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BlinkyBehavior : MonoBehaviour { public bool facingRight = true; public bool jump = false; public float moveForce = 365f; public float maxSpeed = 5f; public float jumpForce = 1000f; private float moviment; public Transform groundCheck; public bool grounded = false; public bool died = false; private Animator anim; private Transform pivot; private Vector3 playerPos; public GameObject player; public float offsetX = 0.3f; public float offsetY = 0.6f; public int rabbitCounter; public GameObject grabbedBox; public GameObject[] rabbits; private int rabbitsSize; public GameObject mainScripts; public GameObject exit; public AudioSource audioSource;
106
public AudioClip audioJump; public AudioClip audioRabbit; public AudioClip audioDie; public AudioClip audioCrash; private Rigidbody2D rigidbd2D; // Inicializa as variáveis void Awake() { pivot = transform.Find("pivot"); anim = GetComponent<Animator>(); rigidbd2D = GetComponent<Rigidbody2D>(); mainScripts = GameObject.Find("GameManager"); } void Update () { /* Dispara um vetor apontando para baixo, caso a distância esteja curta, então o herói deve para de cair pos encontrou um chão ou a caixa */ if (Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground")) || Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Box"))) { grounded = true; } // Ajusta animação de movimento if (grounded) { anim.ResetTrigger("jump"); } // Permite pular se o herói estiver asentado if (Input.GetButtonDown("Jump") && grounded) { jump = true; grounded = false; audioSource.PlayOneShot(audioJump); } /* Quando o herói morre o jogo libera os coelhos de segui-lo reseta os inimigos e renasce o herói na sáida */ if (died) { died = false; anim.SetTrigger("die"); audioSource.PlayOneShot(audioDie); GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); moviment = 0; rabbitCounter = 0; rabbits = GameObject.FindGameObjectsWithTag("Rabbit"); foreach (GameObject rabbit in rabbits) { rabbit.GetComponent<RabbitBehavior>().following = false; rabbit.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); } StartCoroutine (respawnHeroPosition()); } } void FixedUpdate() { // Caso o herói não esteja morto, procede as ações de movimento if (died == false) { moviment = Input.GetAxis("Horizontal"); anim.SetFloat("speed", Mathf.Abs(moviment));
107
// Ajuste do sinal da velocidade de acordo com a direção if (moviment * GetComponent<Rigidbody2D>().velocity.x < maxSpeed) { GetComponent<Rigidbody2D>().AddForce(Vector2.right * moviment * moveForce); } if (Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed) { GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed, GetComponent<Rigidbody2D>().velocity.y); } // Ajuste da orientação da imagem if (moviment > 0 && !facingRight) { Flip(); } else if (moviment < 0 && facingRight) { Flip(); } // Ajuste da animação para o pulo if (jump) { anim.SetTrigger("jump"); GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce)); jump = false; } // Atira uma caixa caso o herói esteja segurando ela if (Input.GetButtonDown("Fire1")) { if (anim.GetBool("grab") == true) { audioSource.PlayOneShot(audioCrash); anim.SetBool("grab", false); if (grabbedBox) { grabbedBox.GetComponent<BoxBehavior>().grabbed = false; grabbedBox.GetComponent<BoxBehavior>().throwed = true; if (facingRight) { grabbedBox.GetComponent<BoxBehavior>().right = true; } else { grabbedBox.GetComponent<BoxBehavior>().right = false; } } } } } } // Ajuste da orientação da imagem do herói void Flip() { facingRight = !facingRight; Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; } // Colisões
108
void OnTriggerEnter2D(Collider2D other) { // Colidir com a caixa faz o herói pegá-la de ele ainda não está com uma if (other.gameObject.CompareTag("Box")) { if (anim.GetBool("grab") == false) { grabbedBox = other.gameObject; other.GetComponent<BoxBehavior>().grabbed = true; anim.SetBool("grab", true); other.GetComponent<BoxBehavior>().pivot = pivot; } } // Quando o herói colide com o coelho, o coelho começa seguí-lo if (other.gameObject.CompareTag("Rabbit") && other.gameObject.GetComponent<RabbitBehavior>().following == false) { audioSource.PlayOneShot(audioRabbit); rabbitCounter += 1; RabbitBehavior rabbit = other.gameObject.GetComponent<RabbitBehavior>(); rabbit.following = true; rabbit.GetComponent<RabbitBehavior>().posHero = new Vector3(player.transform.position.x, player.transform.localPosition.y, transform.localPosition.z); // Ajuste na animação other.gameObject.GetComponent<Animator>().SetTrigger("released"); // Ajuste no posicionamenot e direção do coelho if (GetComponent<Rigidbody2D>().velocity.x < 0) { if (facingRight) { rabbit.offset = new Vector3(-offsetX * (rabbitCounter * 0.1f), 0, 0); } else { rabbit.offset = new Vector3(offsetX * (rabbitCounter * 0.1f), 0, 0); } } else { if (facingRight) { rabbit.offset = new Vector3(-offsetX * (rabbitCounter * 0.1f), 0, 0); } else { rabbit.offset = new Vector3(offsetX * (rabbitCounter * 0.1f), 0, 0); } } } // Quando o herói colide com a saída, se tiver coelhos, ele os entrega if (other.gameObject.CompareTag("Exit")) { rabbits = GameObject.FindGameObjectsWithTag("Rabbit");
109
int multiply = 1; foreach (GameObject rabbit in rabbits) { if (rabbit.GetComponent<RabbitBehavior>().following == true) { mainScripts.GetComponent<GameManager>().increasePoints(100 * multiply); rabbit.GetComponent<RabbitBehavior>().leave(); multiply++; rabbitCounter--; mainScripts.GetComponent<GameManager>().reduceRabbits(); } } } } // Recria o herói na posição doa saída IEnumerator respawnHeroPosition() { rigidbd2D.constraints = RigidbodyConstraints2D.FreezeAll; yield return new WaitForSeconds(2); mainScripts.GetComponent<GameManager>().heroDied(); transform.position = new Vector3(exit.transform.position.x, exit.transform.position.y, 0); anim.ResetTrigger("die"); rigidbd2D.constraints = RigidbodyConstraints2D.None; rigidbd2D.constraints = RigidbodyConstraints2D.FreezeRotation; mainScripts.GetComponent<GameManager>().resetEnemies(); } }
BoxBehavior.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; //Funções relacionadas à caixa "box" public class BoxBehavior : MonoBehaviour { public bool grabbed = false; public Transform pivot; public bool throwed = false; public bool right; public float velocity = 0.05f; public GameObject itSelf; public BoxCollider2D gravityManager; public GameObject gameManager; void Start () { gameManager = GameObject.FindGameObjectWithTag("GameManager"); } private void Update() { /*Se caixa estiver no estado segurada "grabbed" ela assume a posição da mão * do herói "pivotHero" e perde a gravidade */ if(grabbed == true) {
110
pivot = GameObject.FindGameObjectWithTag("pivotHero").GetComponent<Transform>(); GetComponent<Rigidbody2D>().gravityScale = 0; gravityManager.enabled = false; transform.localPosition = pivot.transform.position; } /* Se a caixa for arremessada "throwed" ela deve se deslocar na direção que o herói estava olhando e assume as forças da gravidade */ if (throwed == true) { if (right == true) { transform.Translate(Vector3.right * velocity); } else { transform.Translate(Vector3.left * velocity); } GetComponent<Rigidbody2D>().gravityScale = 1; gravityManager.enabled = true; } } //Colisões void OnTriggerEnter2D(Collider2D other) { // Ao colidir com a parede "Wall", a caixa perde a velocidade if (other.gameObject.CompareTag("Wall")) { throwed = false; transform.Translate(Vector3.zero); } // Ao colidir com o solo "Ground", a caixa perde a velocidade if (other.gameObject.CompareTag("Ground")) { throwed = false; transform.Translate(Vector3.zero); } /* Ao colidir com o inimigo "Enemy", a caixa causa dano "hit" no inimigo e então ela é destruída*/ if (other.gameObject.CompareTag("Enemy") && throwed == true) { //throwed = false; //transform.Translate(Vector3.zero); other.gameObject.GetComponent<MagicianBehaviour>().hit = true; //GetComponent<BoxCollider2D>().enabled = false; //GetComponent<SpriteRenderer>().enabled = false; GameObject.Destroy(itSelf); } } }
CameraFollow.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraFollow : MonoBehaviour {
111
public GameObject player; private Vector3 offset; void Start() { //Calcula e armazena o valor de deslocamento, obtendo a distância entre a posição do player e a posição da câmera. player = GameObject.FindGameObjectWithTag("Player"); transform.position = new Vector3(player.transform.position.x, player.transform.position.y + 0.5f, transform.position.z); offset = transform.position - player.transform.position; } void LateUpdate() { // Define a posição da transformação da câmera para ser a mesma que a do jogador, mas compensada pela distância de deslocamento calculada. transform.position = player.transform.position + offset; } }
DataGame.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; // Variáveis globais que se mantêm entre a troca de telas public static class DataGame { public static int totalPoints = 0; public static int lifeCounter = 3; public static int actualLevel = 1; }
GameManager.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public int totalEnemies; public static int remainingEnemies = 0; public GameObject[] respawns; public int respawnTime = 4; public int sizeOfRespawns; public GameObject[] rabbits; public static int remainingRabbits; private bool createEnemy = false; public GameObject exit; public GameObject hero; public GameObject totalPoints; public GameObject lifeCounter; public GameObject rabbitText; public GameObject levelText; void Start() { //Pega referências levelText = GameObject.Find("levelTextUI");
112
totalPoints = GameObject.Find("totalPointsUI"); lifeCounter = GameObject.Find("lifeCounterUI"); rabbitText = GameObject.Find("rabbitCounterUI"); respawns = GameObject.FindGameObjectsWithTag("RespawnZone"); rabbits = GameObject.FindGameObjectsWithTag("Rabbit"); sizeOfRespawns = respawns.Length; totalEnemies = sizeOfRespawns; remainingRabbits = rabbits.Length; //Posiciona o Blinky na porta de saída hero.transform.position = exit.transform.position; //Inicializa textos lifeCounter.GetComponent<Text>().text = "x" + DataGame.lifeCounter; levelText.GetComponent<Text>().text = "level " + DataGame.actualLevel; rabbitText.GetComponent<Text>().text = remainingRabbits + "/" + remainingRabbits; totalPoints.GetComponent<Text>().text = DataGame.totalPoints.ToString(); } // Popula os inimigos void FixedUpdate() { if (createEnemy == false && remainingEnemies < totalEnemies) { StartCoroutine("respawnOrder"); createEnemy = true; } } // Cria uma inimigo numa zona de reaparecimento aleatória IEnumerator respawnOrder() { remainingEnemies++; yield return new WaitForSeconds(respawnTime); int randSpot = Random.Range(0, sizeOfRespawns); respawns[randSpot].GetComponent<RespawnZone>().respawnEnemy(); createEnemy = false; } public void reduceEnemies(){ remainingEnemies--; } // Faz a contabilização dos coelhos e procede à próxima tela ou fim do jogo public void reduceRabbits() { remainingRabbits--; rabbitText.GetComponent<Text>().text = remainingRabbits + "/" + rabbits.Length; /* Condicao de vitoria */ if (remainingRabbits <= 0) { /* Verifica final do jogo ou procede ao próximo level */ if (DataGame.actualLevel + 4 == SceneManager.sceneCountInBuildSettings) { SceneManager.LoadScene("GameOver"); } else { DataGame.actualLevel++; SceneManager.LoadScene(DataGame.actualLevel); } } } // Remove todos os inimigos do cenário
113
public void resetEnemies() { GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); foreach (GameObject enemy in enemies) { GameObject.Destroy(enemy); } remainingEnemies = 0; } // Contabiliza pontos e atrualiza o marcador da tela public void increasePoints(int points) { DataGame.totalPoints += points; totalPoints.GetComponent<Text>().text = DataGame.totalPoints.ToString(); } // Checa final do jogo por falta de vidas do jogador public void heroDied() { /* checa se o heroi morreu */ if (DataGame.lifeCounter <= 0) { /* procede o fim do jogo */ SceneManager.LoadScene("GameOver"); } else { /* Procede o reset do jogador */ DataGame.lifeCounter--; lifeCounter.GetComponent<Text>().text = "x"+DataGame.lifeCounter; } } }
LoadFinalTexts.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; //Função que exibe os créditos finais quando o jogo acaba public class LoadFinalTexts : MonoBehaviour { public GameObject finalScore; void Start () { finalScore.GetComponent<Text>().text = DataGame.totalPoints.ToString(); } private void FixedUpdate() { if (Input.anyKey) { SceneManager.LoadScene("Credits"); DataGame.lifeCounter = 3; DataGame.totalPoints = 0; } } }
114
MagicianBehavior.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MagicianBehaviour : MonoBehaviour { public bool facingRight = true; public bool jump = false; public float moveForce = 700f; public float maxSpeed = 5f; public float jumpForce = 2000f; private Transform groundCheck; private bool grounded = false; private Animator anim; public float moviment = 1; public bool hit = false; public bool died = false; public GameObject itSelf; public AudioSource audioSource; public AudioClip audioDie; public GameObject gameManager; public Transform collided; private int chanceToTurn; // Inicialiação das variáveis void Awake() { groundCheck = transform.Find("groundCheck"); anim = GetComponent<Animator>(); if (!facingRight) { moveForce *= -1; } } void Update () { // Checa posição no solo grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground")); if (died == false) { // Quando uma caixa arremesada encontra um inimigo (hit), o inimigo morre if (hit == true) { audioSource.PlayOneShot(audioDie); GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); anim.SetTrigger("died");; gameManager.GetComponent<GameManager>().reduceEnemies(); died = true; hit = false; StartCoroutine(erase()); } else { // Ajuste de animação de pulo
115
if (grounded) { anim.ResetTrigger("jump_magi"); } } } } private void FixedUpdate() { // Se o nimigo não estiver morto, realiza ajustes de velocidade e orientação if(died == false) { anim.SetFloat("speed", Mathf.Abs(moviment)); if (moviment * GetComponent<Rigidbody2D>().velocity.x < maxSpeed) { GetComponent<Rigidbody2D>().AddForce(Vector2.right * moviment * moveForce); } if (Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed) { GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed, GetComponent<Rigidbody2D>().velocity.y); } if (moviment > 0 && !facingRight) { Flip(); } else if (moviment < 0 && facingRight) { Flip(); } } } // Colisões void OnTriggerEnter2D(Collider2D other) { if (died == false) { // Quando colide com uma parede ele muda de direção if (other.gameObject.CompareTag("Wall")) { if (moviment == 1) { moviment = -1; } else { moviment = 1; } GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); } // Quando colide com um coelho, faz o coelho para de seguir o herói if (other.gameObject.CompareTag("Rabbit")) { other.GetComponent<RabbitBehavior>().stopFollow(); /* Evita ficar preso */ StartCoroutine(checkStuck()); } // Quando colide com o jogador, mata o jogador if (other.gameObject.CompareTag("Player"))
116
{ other.GetComponent<BlinkyBehavior>().died = true; GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); } // Quando colide com uma caixa que não foi arremessada tenta pular por cima if (other.gameObject.CompareTag("Box")) { if (other.gameObject.GetComponent<BoxBehavior>().grabbed == false && other.GetComponent<BoxBehavior>().throwed == false) { /* Evita ficar preso */ StartCoroutine(checkStuck()); } } } } // Ajuste de orientação de imagem void Flip() { facingRight = !facingRight; Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; } /* De tempos em tempos checa se o inimigo ficou "preso" no mapa e * realiza um pulo ou inverte a direção do movimento */ IEnumerator checkStuck() { collided = transform; yield return new WaitForSeconds(2); if (collided = transform) { chanceToTurn = Random.Range(0, 2); if (chanceToTurn == 0) { anim.SetTrigger("jump_magi"); GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce)); } else { Flip(); } //StartCoroutine(checkStuck()); } } // Função que destrói o inimigo IEnumerator erase() { yield return new WaitForSeconds(3); Destroy(itSelf); } }
MagicianSight.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MagicianSight : MonoBehaviour {
117
public GameObject magician; /* Parte do inimigo que mata o herói, está separada pois * somente a parte da frente do inimigo que colide */ void OnTriggerEnter2D(Collider2D other) { if (magician.GetComponent<MagicianBehaviour>().died == false) { if (other.gameObject.CompareTag("Player")) { other.GetComponent<BlinkyBehavior>().died = true; } } } }
RabbitBehavior.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; // Gerencia as ações do coelho "rabbitBehavior" public class RabbitBehavior : MonoBehaviour { public bool following; public GameObject player; public Vector3 offset; public bool facingRight = true; private Animator anim; public Transform exit; public int MoveSpeed = 4; public GameObject itSelf; public Vector3 posHero; public float offsetY; public BoxCollider2D gravityManager; public float speed = 2.0F; private float startTime; private float journeyLength; // Inicializa as variáveis void Start () { following = false; anim = GetComponent<Animator>(); player = GameObject.FindGameObjectWithTag("Player"); exit = GameObject.FindGameObjectWithTag("Exit").transform; startTime = Time.time; journeyLength = Vector3.Distance(transform.position, posHero); } private void FixedUpdate() { /* Caso o coelho esteja seguindo o herói, ele se desloca se o herói estiver * longe à uma distância determinada */ if (following == true) { GetComponent<Rigidbody2D>().gravityScale = 0; gravityManager.enabled = false; float distCovered = (Time.time - startTime) * speed;
118
float fracJourney = distCovered / journeyLength; if (facingRight) { posHero = new Vector3(player.transform.position.x + offset.x, player.transform.localPosition.y - offsetY, transform.localPosition.z); } else { posHero = new Vector3(player.transform.position.x - offset.x, player.transform.localPosition.y - offsetY , transform.localPosition.z); } transform.position = Vector3.Lerp(transform.position, posHero, fracJourney); } else { GetComponent<Rigidbody2D>().gravityScale = 1; gravityManager.enabled = true; } // Realiza o ajuste na orientação do coelho float h = Input.GetAxis("Horizontal"); if (following == true && h > 0 && !facingRight) { Flip(); } else if (following == true && h < 0 && facingRight) { Flip(); } // Ativa a animação caso o coelho esteja seguindo if (following == true) { if (player.GetComponent<Rigidbody2D>().velocity.x != 0) { anim.SetTrigger("follow"); } else { anim.ResetTrigger("follow"); } } else { anim.ResetTrigger("follow"); } } // Função que inverte a orientação do coelho void Flip() { facingRight = !facingRight; Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = new Vector3(theScale.x, transform.localScale.y, transform.localScale.z); } // Quando o coelho chega na saída ele deixa o jogo public void leave() { /*following = false; anim.ResetTrigger("follow"); GetComponent<BoxCollider2D>().enabled = false;
119
GetComponent<SpriteRenderer>().enabled = false;*/ GameObject.Destroy(itSelf); } /* Função faz com que o coelho para de seguir o herói porque o herói morreu ou porque o inimigo colidiu com o coelho */ public void stopFollow() { if(following == true) { following = false; GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0); player.GetComponent<BlinkyBehavior>().rabbitCounter--; } } }
RespawnZone.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RespawnZone : MonoBehaviour { public GameObject enemy; public GameObject respawnPosition; public Animator anim; private void Start() { anim = GetComponent<Animator>(); } // Função instancia um inimigo, que é criado na mesma posição da zona de reaparecimento "respawnZone" public void respawnEnemy() { anim.SetTrigger("open"); Instantiate(enemy, respawnPosition.gameObject.transform.position, respawnPosition.gameObject.transform.rotation); StartCoroutine("closeDoor"); } // Anima a porta fechando IEnumerator closeDoor() { yield return new WaitForSeconds(1); anim.ResetTrigger("open"); } }