TCC com numeração

Transcrição

TCC com numeração
UNIVERSIDADE FEDERAL DE SANTA CATARINA
Metodologia para Ensino de Programação
Orientada a Objetos com Jogos 2D
Kaléu Caminha
Florianópolis, 2º semestre de 2012
1 / 227
UNIVERSIDADE FEDERAL DE SANTA CATARINA
DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE SISTEMAS DE INFORMAÇÃO
Metodologia para Ensino de Programação
Orientada a Objetos com Jogos 2D
Kaléu Caminha
Trabalho de Conclusão de Curso
apresentado como requisito parcial para a
obtenção de grau de Bacharel em
Sistemas de Informação.
Florianópolis, 2º semestre de 2012
2 / 227
Kaléu Caminha
Metodologia para Ensino de Programação
Orientada a Objetos com Jogos 2D
Trabalho de Conclusão de Curso apresentado
como requisito parcial para a obtenção de grau
de Bacharel em Sistemas de Informação.
Orientador
Professor Doutor Ricardo Pereira e Silva
Banca Examinadora
Leandro José Komosinski
Patrícia Vilain
3 / 227
Sumário
Lista de Reduções............................................................................................................................. 13
Resumo.............................................................................................................................................. 14
1 Introdução...................................................................................................................................... 15
1.1 Justificativa.............................................................................................................................. 16
1.2 Objetivo Geral..........................................................................................................................18
1.3 Objetivos Específicos ............................................................................................................ 18
1.4 Metodologia de Pesquisa......................................................................................................... 19
2 Fundamentação Teórica................................................................................................................ 20
2.1 Programação Orientada a Objetos........................................................................................... 20
2.1.1 Conceitos POO ...............................................................................................................21
2.1.2 Estruturas Básicas de Programação em Java................................................................... 21
2.1.3 Conceitos da Linguagem Java..........................................................................................22
2.2 Jogos 2D.................................................................................................................................. 22
2.2.1 Desenho de imagens........................................................................................................23
2.2.2 Animações........................................................................................................................ 24
2.2.3 Tiles e Composição de Cenários...................................................................................... 24
2.2.4 Pontos / Plano Cartesiano................................................................................................ 24
2.2.5 Sprites...............................................................................................................................25
2.2.6 Dispositivos de Entrada .................................................................................................. 25
2.2.7 Execução de sons............................................................................................................. 25
2.2.8 Taxa de Quadros e atualização do jogo............................................................................25
2.2.9 Acumuladores de Tempo..................................................................................................26
2.2.10 Gravidade....................................................................................................................... 26
2.2.11 Detecção e Tratamento de Colisões............................................................................... 26
2.2.12 O Game Loop.................................................................................................................27
2.2.13 Movimentação e Gravidade nos cenários...................................................................... 27
2.3 Frameworks Orientado a Objetos............................................................................................ 27
2.3.1 Frameworks OO............................................................................................................... 27
2.3.2 Metodologias de Desenvolvimento de Frameworks OO................................................. 28
2.3.3 Uso de Frameworks OO...................................................................................................29
2.4 Padrões Pedagógicos................................................................................................................29
2.4.1 O Mais Importante Primeiro (Early Bird)........................................................................30
2.4.2 Espiral (Spiral)................................................................................................................. 30
2.4.3 Metáfora Consistente (Consistent Mataphor).................................................................. 30
2.4.4 Caixa de Brinquedos (Toy Box).......................................................................................31
4 / 227
2.4.5 Caixa de Ferramentas (Tool Box).................................................................................... 31
2.4.6 Disposição do território (Lay of the Land)...................................................................... 31
2.4.7 Corrigir para cima (Fixer Upper)..................................................................................... 32
2.4.8 Maior que a Vida (Larger than Life)................................................................................ 32
2.4.9 Sprint de Projeto dos Estudantes (Student Design Sprint)...............................................33
2.4.10 Engano (Mistake)........................................................................................................... 33
2.4.11 Canal de Teste (Test Tube)............................................................................................. 33
2.4.12 Preencha as Lacunas (Fill in the Blanks)....................................................................... 34
2.4.13 Estrela de Ouro (Gold Star)........................................................................................... 34
2.4.14 Avalie isto novamente Sam (Grade it again Sam)..........................................................34
3 Experiência prévia com ensino de POO e Jogos.........................................................................35
3.1 Conteúdos trabalhados............................................................................................................. 35
3.2 Metodologia............................................................................................................................. 37
3.2.1 Exemplo 1 – Movimentando uma bola............................................................................ 38
3.2.2 Exemplo 2 – Construindo o primeiro jogo.......................................................................39
3.2.3 Exemplo 3 – Ítens e fases.................................................................................................39
3.2.4 Exemplo 4 – Guerra Especial...........................................................................................40
3.2.5 – Personagens e Cenários.................................................................................................41
3.2.6 – Jogo de Luta.................................................................................................................. 42
3.2.7 – Revisão..........................................................................................................................42
3.3 Avaliação e Resultados............................................................................................................ 43
3.3.1 Avaliação Teórica............................................................................................................. 43
3.3.2 Avaliação da Motivação................................................................................................... 44
3.3.3 Avaliação Prática.............................................................................................................. 44
3.3.3.1 Grupo 1 – PowerMusic.............................................................................................45
3.3.3.2 Grupo 2 – Champions Fighter.................................................................................. 45
3.3.3.3 Grupo 3 – Ghomaine................................................................................................ 45
3.3.3.4 Grupo 4 – Ice Crown Citadel................................................................................... 45
3.3.3.5 Grupo 5 – Moluscation.............................................................................................45
3.3.3.6 Grupo 6 – Terrorist Strategy.....................................................................................45
3.3.3.7 Grupo 7 – God of Worms......................................................................................... 45
3.3.3.8 Grupo 8 – Sami Game.............................................................................................. 45
3.3.4 Resultado avaliação prática..............................................................................................46
3.3.4 Conclusão ao final do módulo......................................................................................... 46
4 Ensino de Programação Orientada a Objetos............................................................................ 48
4.1 Metodologias para Ensino OO.................................................................................................48
4.1.1 Isaias Camilo Boratti........................................................................................................49
4.1.1.1 Análise Geral do Método..........................................................................................51
4.1.1.2 Pontos Fortes ........................................................................................................... 52
4.1.1.3 Pontos Fracos........................................................................................................... 56
4.1.1.4 Conclusão................................................................................................................. 58
4.1.2 David J. Barnes e Michael Kölling.................................................................................. 59
5 / 227
4.1.2.1 Diretrizes ................................................................................................................. 61
4.1.2.2 Análise geral do método........................................................................................... 63
4.1.2.3 Pontos fracos............................................................................................................ 64
4.1.2.4 Conclusão................................................................................................................. 65
4.1.3 Bruno Feijó et al...............................................................................................................66
4.1.3.1 Análise geral do método........................................................................................... 68
4.1.4 Stelios Xinogalos............................................................................................................. 68
4.1.4.1 O Uso de ambientes de programação....................................................................... 69
4.1.4.2 Diretrizes para o Ensino das lições propostas.......................................................... 70
4.1.4.3 Análise Geral do método.......................................................................................... 77
4.1.5 Michael Caspersen........................................................................................................... 77
4.1.5.1 As etapas da metodologias....................................................................................... 79
4.1.5.2 O Framework conceitual.......................................................................................... 79
4.1.5.3 O início..................................................................................................................... 79
4.1.5.4 Padrões de Código....................................................................................................80
4.1.5.5 Outros elementos da metodologia............................................................................ 80
4.1.5.6 Análise Geral da Metodologia.................................................................................. 81
4.2 Diretrizes para o Ensino de OO ............................................................................................. 81
4.2.1 Princípios baseados na prática com o BlueJ.................................................................... 81
4.3.2 Representações visuais para todas as estruturas e conceitos trabalhados........................81
4.3.3 Operações de abstração e framework conceitual............................................................. 82
4.3.4 Ambiente educacional + Ambiente profissional.............................................................. 82
4.3.5 Processo sistemático de desenvolvimento....................................................................... 82
4.3.6 A partir do zero.................................................................................................................82
4.3.7 Recursos computacionais devem ter acesso fácil.............................................................82
4.3.8 Estilo de código-fonte...................................................................................................... 83
4.3.9 Modelagens genéricas...................................................................................................... 83
4.3.10 Códigos e documentação na língua materna..................................................................83
5 Framework Java para Jogos 2D.................................................................................................. 85
5.1 Aquisição do Conhecimento de Domínio................................................................................ 85
5.2 Modelagem do Framework:.....................................................................................................85
5.2.1 Generalização...................................................................................................................86
5.2.2 Flexibilização................................................................................................................... 86
5.2.3 Modelagem das Classes................................................................................................... 87
5.2.3.1 Pacote aljava.............................................................................................................87
5.2.3.2 Pacote aljava.entrada................................................................................................ 87
5.2.3.3 Pacote aljava.saida....................................................................................................88
5.2.3.4 Pacote aljava.midia...................................................................................................88
5.2.3.5 Pacote aljava.jogo.....................................................................................................88
5.2.3.6 Pacote aljava.util...................................................................................................... 90
5.3 Validação..................................................................................................................................90
5.4 Documentação......................................................................................................................... 91
5.4.1 Livro de Receitas............................................................................................................. 91
5.4.2 JavaDoc............................................................................................................................ 93
6 / 227
5.5 Código Fonte............................................................................................................................95
6 Metodologia de Ensino.................................................................................................................. 96
6.1 Introdução................................................................................................................................ 97
6.2 Módulo 1 – Animações computadorizadas............................................................................ 100
6.2.1 Modelagem – Classe Carro............................................................................................ 101
6.2.2 Tipos Básicos................................................................................................................. 101
6.2.3 Live Coding – Classe Carro........................................................................................... 103
6.2.3 Live Coding – Desenhando............................................................................................107
6.4.4 Live Coding – Animações.............................................................................................. 112
6.2.5 Live Coding – Parâmetros e estruturas condicionais..................................................... 114
6.4.6 Resultados...................................................................................................................... 120
6.4.6.1 Classe Sapo.............................................................................................................121
6.4.6.2 Classe BatmanLogo................................................................................................122
6.4.6.3 Classe Onibus ........................................................................................................ 123
6.4.6.4 Classe Carro........................................................................................................... 124
6.3 Módulo 2 – Mini Game......................................................................................................... 124
6.5.1 Resultados...................................................................................................................... 135
6.4 Módulo 3 – Um Jogo, Muitos Objetos.................................................................................. 136
6.4.1 Modelagem Básica......................................................................................................... 136
6.4.2 Lógica do Jogo............................................................................................................... 141
6.4.3 Herança.......................................................................................................................... 145
6.4.4 Listas.............................................................................................................................. 149
6.4.5 Tiros e Métodos com Retorno........................................................................................ 151
6.4.6 Colisões entre listas e finalização do jogo..................................................................... 154
6.4.7 Classe ContadorTempo.................................................................................................. 157
6.4.8 Pacote de Mídia..............................................................................................................157
6.4.9 Resultados...................................................................................................................... 157
6.4.9.1 A Ponte................................................................................................................... 158
6.4.9.2 Pacman................................................................................................................... 158
6.4.9.3 Ken vs Akuma........................................................................................................ 159
6.4.9.4 Mundo de Molland................................................................................................. 160
6.5 Módulo 4 – Pequeno mundo virtual...................................................................................... 160
6.5.1 Modelando um jogo escalável........................................................................................161
6.5.2 Ambiente de Desenvolvimento Profissional.................................................................. 164
6.5.3 Compartilhamento de Objetos e o método Main........................................................... 165
6.5.4 Variáveis e Métodos Estáticos........................................................................................168
6.5.5 Resultados...................................................................................................................... 170
6.6 Módulo 5 – Frameworks........................................................................................................171
6.6.1 Frameworks....................................................................................................................172
6.6.2 Classe Motor e Ciclo de Vida.........................................................................................172
6.6.2 Classes Interfaces........................................................................................................... 174
7 / 227
6.6.3 Troca de fases e o método “main”................................................................................. 180
6.6.4 Classes Abstratas............................................................................................................183
6.6.5 Polimorfismo..................................................................................................................189
6.6.6 Resultados...................................................................................................................... 193
6.7 Limitações da Metodologia Apresentada ..............................................................................194
7 Conclusão..................................................................................................................................... 195
7.1 Revisão dos Objetivos propostos........................................................................................... 197
7.2 As 10 diretrizes...................................................................................................................... 199
7.2.1 Princípios baseados na prática com o BlueJ.................................................................. 199
4.3.2 Representações visuais para todas as estruturas e conceitos trabalhados......................199
4.3.3 Operações de abstração e “framework” conceitual........................................................200
4.3.4 Ambiente educacional + Ambiente profissional............................................................ 200
4.3.5 Processo sistemático de desenvolvimento..................................................................... 200
4.3.6 A partir do zero...............................................................................................................200
4.3.7 Recursos computacionais devem ter acesso fácil...........................................................201
4.3.8 Estilo de código-fonte.................................................................................................... 201
4.3.9 Modelagens genéricas.................................................................................................... 201
4.3.10 Códigos e documentação na língua materna................................................................201
7.3 Outros Aprendizados..............................................................................................................201
7.3.1 Aplicações conectadas com a realidade do educando.................................................... 201
7.3.2 Frameworks e bibliotecas como apoio ao desenvolvimento mesmo em etapas iniciais
.................................................................................................................................................202
7.3.3 Modelagem é essencial.................................................................................................. 202
7.4 Trabalhos Futuros.................................................................................................................. 202
7.4.1 Compreensão do Pensamento Computacional e Abstrato..............................................203
7.4.2 Conexão com a pedagogia e produção de REA `s– Recursos Educacionais Abertos....203
7.4.3 Uso abrangente da UML................................................................................................ 203
7.4.4 Técnicas de documentação de software para estudantes novatos..................................204
7.4.5 Ensino de POO Avançada com Android;....................................................................... 204
7.5 Considerações Finais ............................................................................................................ 205
8 Bibliografia...................................................................................................................................206
8.1 Livros..................................................................................................................................... 206
8.2 Artigos e Documentos acadêmicos........................................................................................ 206
8.3 Bibliografia para código-fonte e materiais didáticos desenvolvidos pelo autor....................207
8.4 Bibliografia Consultada......................................................................................................... 208
9. Anexos.......................................................................................................................................... 210
9.1 Anexo I - Classe Carro........................................................................................................... 211
9.2 Anexo II – Personagens do jogo “A Aventura do Quadrado” ...............................................212
8 / 227
9.2.1 Classe SenhorQ.............................................................................................................. 212
9.2.2 Classe InimigoQuadradao.............................................................................................. 215
9.2.3 Classe InimigoTic.......................................................................................................... 215
9.2.4 Classe SuperQuadrado................................................................................................... 216
9.3 Anexo III – Classe “TelaSelecao”..........................................................................................217
9.4 Anexo IV – Fases do jogo “A Aventura do Quadrado”.........................................................220
9.4.1 Classe TelaInicial........................................................................................................... 220
9.4.2 Classe Fase1................................................................................................................... 222
9.4.3 Classe Fase2................................................................................................................... 225
9.4.4 Classe FaseChefao......................................................................................................... 228
9 / 227
Índice de ilustrações
Ilustração 1: Cenário baseado em Tiles.............................................................................................. 24
Ilustração 2: Exemplo de uma Sprite..................................................................................................25
Ilustração 3: Movimentando uma bola na tela................................................................................... 38
Ilustração 4: Exemplo mais complexo utilizando a bola criada anteriormente..................................38
Ilustração 5: Tela final do jogo desenvolvido com o auxílio do roteiro............................................. 39
Ilustração 6: Terceira fase do exemplo com diversos itens na tela.....................................................40
Ilustração 7: Versão final do jogo Guerra Espacial............................................................................ 41
Ilustração 8: Personagem saltando sobre um inimigo representado por uma bola vermelha.............42
Ilustração 9: Exemplo jogo de luta..................................................................................................... 42
Ilustração 10: A Construção do modelo. Fonte: Boratti..................................................................... 53
Ilustração 11: Representação Visual de Objetos. Fonte: Boratti. Adaptado por Kaléu Caminha.......54
Ilustração 12: Implementação de Objetos. Fonte: Boratti. Adaptado por Kaléu Caminha................55
Ilustração 13: Representação Visual de um Array. Fonte: Boratti. adaptado por Kaléu Caminha.....55
Ilustração 14: Instanciação de objeto e chamada de método em código............................................ 64
Ilustração 15: Objetos na bancada de objetos (em vermelho) e chamada de método de um objeto. .65
Ilustração 16: Instanciação de um objeto no objectKarel com a ajuda da interface gráfica...............71
Ilustração 17: Criação de uma tarefa a partir dos métodos de um robô.............................................72
Ilustração 18: Execução de um programa. à direita a visualização do robô, à esquerda a lista de
tarefas e abaixo a descrição do que ocorre no interior do método em execução................................72
Ilustração 19: Criação sistemática de um programa orientado a objetos...........................................78
Ilustração 20: Texto de introdução ao Aljava..................................................................................... 91
Ilustração 21: Submenu da seção sobre os comandos da classe Alj...................................................92
Ilustração 22: Submenu com alguns exemplos integrando diferentes comandos da classe Alj.........92
Ilustração 23: Outros submenus da documentação............................................................................ 92
Ilustração 24: Documentação de como desenhar um Retângulo........................................................92
Ilustração 25: Exemplo de uso dos recursos de acesso ao Mouse......................................................93
Ilustração 26: Exemplo de detalhe da tradução do gerador de JavaDoc............................................93
Ilustração 27: Visualização de diversas classes do mesmo pacote..................................................... 94
Ilustração 28: Métodos da classe som................................................................................................ 94
Ilustração 29: Detalhamento do método "configTile"........................................................................ 94
Ilustração 30: Tela do Jogo Space Invaders........................................................................................97
Ilustração 31: Representação de uma classe do jogo SpaceInvaders.................................................99
Ilustração 32: Representação visual de dois objetos criados a partir da classe Inimigo.................... 99
Ilustração 33: Exemplo de Classes "Carro" com diferentes objetivos.............................................101
Ilustração 34: Exemplo de uma classe motor com as características e os respectivos tipos............103
Ilustração 35: Exemplo de Classe Carro.......................................................................................... 107
Ilustração 36: Exemplos de objetos da classe Carro ao lado após execução de alguns dos métodos.
.......................................................................................................................................................... 107
Ilustração 37: Exemplo de criação de objetos usando parâmetros pelo construtor..........................118
Ilustração 38: Exemplo Classe Sapo desenvolvida por um aluno.................................................... 121
Ilustração 39: Variáveis na classe Sapo............................................................................................ 122
Ilustração 40: Classe BatmanLogo................................................................................................... 122
Ilustração 41: Classe Onibus............................................................................................................ 123
Ilustração 42: Exemplo de má formatação de código na classe Onibus...........................................124
Ilustração 43: Exemplo Classe Carro............................................................................................... 124
Ilustração 44: Representação visual do uso de matriz......................................................................128
Ilustração 45: Métodos classe JogoDaVelha.................................................................................... 131
Ilustração 46: Modelagem básica do jogo Guerra Espacial............................................................. 138
Ilustração 47: Sintaxe de Construção de objetos.............................................................................. 143
10 / 227
Ilustração 48: Telas da implementação parcial do jogo GuerraEspacial.......................................... 145
Ilustração 49: Representação Visual da Lista................................................................................... 150
Ilustração 50: Representação visual para o "loop foreach" ............................................................. 151
Ilustração 51: Exemplo de tela do jogo "A Ponte"........................................................................... 158
Ilustração 52: Tela do jogo Pacman..................................................................................................159
Ilustração 53: Tela do jogo Ryu vs Akuma.......................................................................................159
Ilustração 54: Tela do jogo Mundo de Molland................................................................................160
Ilustração 55: Representação Visual dos padrões.............................................................................162
Ilustração 56: Organização de Pacotes do Jogo "A Aventura do Quadrado"....................................164
Ilustração 57: Classe Fase1 com os métodos minimizados..............................................................165
Ilustração 58: Exemplo de visualização de "referência".................................................................. 167
Ilustração 59: Exemplo de classe Fase com os três métodos vazios................................................ 175
Ilustração 60: Exemplo de sobrescrita do método inicia da classe Fase.......................................... 175
Ilustração 61: NetBeans sugerindo implementar os métodos abstratos...........................................176
Ilustração 62: Métodos criados pelo NetBeans após clicar na sugestão de implementar os métodos
abstratos............................................................................................................................................ 177
Ilustração 63: Exemplo de uso de uma interface ObjetoJogo.......................................................... 184
Ilustração 64: Implementação da Interface "ObjetoJogo" por um dos objetos do jogo...................184
Ilustração 65: Exemplo da classe abstrata "ObjetoJogo"................................................................. 187
Ilustração 66: Classe abstrata "ObjetoJogo" estendendo a classe "RetanguloGravidade" ..............187
Ilustração 67: Métodos que encapsulam os métodos "processa" e "desenha" da superclasse..........189
Ilustração 68: Exemplo de Hierarquia de Herança na classe "SenhorQ"......................................... 190
Ilustração 69: Classe que representa um item de cura......................................................................191
Ilustração 70: Classe que representa um item que diminui a forca do Pulo.....................................191
Ilustração 71: Exemplo da fase final contendo os itens implementados.......................................... 193
11 / 227
Índice de tabelas
Tabela 1: Conceitos POO................................................................................................................... 21
Tabela 2: Documentação de “frameworks”........................................................................................ 29
Tabela 3: Tabela demonstrando os conteúdos trabalhados na experiência prévia com ensino de
orientação a objetos baseado em jogos...............................................................................................36
Tabela 4: Índice de acerto em cada um dos critérios de avaliação do jogo 2D.................................. 46
Tabela 5: Conteúdos e Exemplos da metodologia de Boratti............................................................. 51
Tabela 6: Conteúdos e exemplos da metodologia de Barnes..............................................................61
Tabela 7: Conteúdos e exemplos da metodologia de Feijó................................................................ 67
Tabela 8: Conteúdos e ambiente de programação na metodologia de Xinogalos..............................69
Tabela 9: "Live Coding" para a classe Carro....................................................................................106
Tabela 10: "Live Coding"- Desenhando um carro............................................................................110
Tabela 11: Demonstração comparativa para uso de parâmetros....................................................... 118
Tabela 12: "Live Coding" para desenho das casas do Jogo da Velha............................................... 131
Tabela 13: "Live Coding" para finalização do jogo da velha........................................................... 135
Tabela 14: Comparação com e sem uso da herança......................................................................... 147
12 / 227
Lista de Reduções
POO
Programação Orientada a Objetos
OO
Orientação a Objetos
2D
Duas dimensões
13 / 227
Resumo
O presente trabalho apresenta uma metodologia de ensino de Programação
Orientada a Objetos tendo como campo de prática os jogos em duas dimensões. A
Metodologia foi desenvolvida a partir do estudo de seis autores da área: 1) Barnes; 2)
Kölling; 3) Boratti; 4) Feijó; 5) Xinogalos; 6) Caspersen. O método é apresentado
detalhadamente em cinco módulos, está baseado em dez princípios e acompanha um
framework Java que permite aos estudantes o uso fácil de recursos essenciais para o
desenvolvimento de jogos.
14 / 227
1 Introdução
Por volta de abril de 2011 o autor deste trabalho iniciou a experiência de ensinar
Programação Orientação a Objetos para alunos entre 15 e 17 anos no curso técnico de
programação no SENAI de São José, em Santa Catarina.
Dentre muitas dificuldades, as que mais se destacaram eram: 1) a desmotivação
dos alunos com a programação; 2) a dificuldade com a sintaxe e recursos específicos do
Java e 3) a ausência de método para transformação de um problema em um conjunto de
classes que representariam sua respectiva solução.
A partir desta constatação, iniciou-se na turma do segundo semestre de 2011 a
adoção da metodologia de ensino criada por David J. Barnes e Michael Kölling utilizando
o BlueJ como ambiente de programação. No semestre seguinte, no início de 2012 e com
a mesma turma, iniciou-se um trabalho de desenvolvimento de jogos em Java a partir dos
materiais desenvolvidos por Bruno Feijó e Esteban Clua.
Ficou evidente após a aplicação destas práticas que a motivação dos estudantes
aumentou e os problemas com certas sintaxes e recursos do Java também diminuíram.
Entretanto, na análise dos trabalhos finais de desenvolvimento de jogos, ficou evidente
que para metade da turma, ainda havia muita dificuldade em resolver problemas
aplicando os conceitos de Programação Orientada a Objetos, sem auxílio do professor.
Acredita-se que a inexperiência e a falta de método do autor acarretou nas
dificuldades percebidas nos alunos ao final do processo de ensino aprendizagem.
E é com este ponto de partida que se inicia este trabalho com a busca por métodos,
práticas, conceitos e ferramentas que auxiliem alunos – principalmente os que possuem
maiores dificuldades com programação – a modelarem e desenvolverem softwares que
solucionem problemas com os quais eles próprios venham a se deparar no seu dia a dia,
de modo, que se aprenda não apenas a desenvolver códigos orientado a objetos, mas
principalmente, conseguir “enxergar os objetos”, como bem colocado pelo professor
Ricardo Pereira e Silva na primeira reunião de orientação.
15 / 227
1.1 Justificativa
Na Orientação a Objetos, as metodologias e ferramentas de ensino não são tão
maduras quanto nos paradigmas mais antigos como a programação estruturada e
funcional (Xinogalos), de forma que muitos professores de ciência da computação
(Xinogalos, Proulx, Caspersen, Bennedsen, Rosenberg, Kölling, Barnes, Boratti) que se
depararam diante da tarefa de ensinar orientação a objetos, iniciaram uma série de
pesquisas em busca de diretrizes, ferramentas e metodologias que norteasse essa
importante tarefa.
O autor considera, pela experiência com ensino, que a grande maioria dos
exemplos didáticos em Java, mesmo em algumas metodologias recentes, trabalha com
softwares muito simples para serem interessantes ou ainda fora da área de interesse e
conhecimento da maioria dos jovens estudantes de programação.
Um exemplo é o primeiro projeto apresentado no livro texto do ambiente BlueJ,
uma máquina de vender bilhetes de trem, algo completamente fora da realidade brasileira,
porém, mesmo que adaptássemos o projeto para, por exemplo, uma máquina de vender
café, ainda teríamos a distância do aluno entre simular uma máquina de vender café e
programar uma máquina de vender café da vida real.
Esta é a vantagem da área de jogos, é possível que o estudante crie algo com o
qual ele efetivamente poderá se divertir e além disso, a maioria dos jovens com os quais o
autor pode trabalhar, aos 15 e 16 anos, já possuem um grande número de horas de
experiência com jogos, permitindo que eles tragam um conhecimento prévio para a
atividade de programação, facilitando a fixação dos conceitos com situações problema
com as quais eles já estão familiarizados.
Além desta perspectiva, o uso de jogos para o ensino de programação é um
recurso já utilizado por muitos instrutores na comunidade de educadores de ciência da
computação, não só pela sua capacidade de estimular os alunos, mas também por ser um
tipo de aplicação para o qual convergem os maiores desafios da computação (Feijó)
independente do paradigma de programação utilizado.
Porém, livros com conteúdos nesta área geralmente são complexos, utilizando
recursos das linguagens de programação que envolvem um grande número de conceitos
e regras de sintaxe, o que dificulta sua aplicação didática em sala de aula. Por exemplo,
para que seja possível desenhar uma imagem na tela em Java (recurso essencial no
desenvolvimento de jogos) é preciso conhecer conceitos complexos como herança e
16 / 227
sobrecarga de métodos.
A partir disto, percebe-se que o suporte ao desenvolvimento de jogos em fases
iniciais do ensino de programação exige o auxilio de ferramentas que tornem mais fácil o
desenvolvimento de recursos como uso de sons, imagens e cenários.
Duas soluções atuais foram encontradas, a primeira, um ambiente de programação
denominado Greenfoot (Kölling, 2010) desenvolvido para permitir o ensino de
programação com interação e visualização, permitindo uma inclusão rápida e fácil de
imagens, sons e posicionamento de elementos em um cenário. A segunda, é o conjunto
de bibliotecas denominado JavaLib (Proulx, 2010), cujo objetivo é permitir que o
estudante mantenha o foco no projeto do jogo, no seu comportamento e na representação
de cada cena através de formas geométricas simples. Mais recentemente a biblioteca foi
ampliada para permitir o ensino de OO através da arte de escrever e tocar músicas com
abstrações de notas e arranjos musicais.
Para este projeto, foi escolhida uma abordagem próxima a de Proulx pois como
relata Xinogalos - que utilizou e ainda utiliza o ambiente BlueJ parcialmente em sua
metodologia - é importante preparar os estudantes para serem profissionais usando
ferramentas profissionais de desenvolvimento, manter o aluno por muito tempo em
ambientes especificamente voltados para o ensino pode torná-lo por demais acostumado
aos recursos didáticos e limitadores destes ambientes, não desenvolvendo plenamente as
habilidades de programação e abstração, necessárias a um profissional.
Outro fator favorável ao uso de bibliotecas e frameworks no ensino deriva do fato
de ser muito comum no desenvolvimento de software o aprendizado de novas bibliotecas
e frameworks. Sendo necessário ao profissional de programação o domínio das
habilidades de compreensão da documentação e utilização de tais bibliotecas e
frameworks.
Observa-se também que alguns conceitos como Interfaces e classes abstratas tem
sua aplicação observada mais frequentemente em frameworks, sendo a extensão de um
framework uma forma de estudo de tais conceitos.
Deste modo, considera-se essencial para este trabalho o desenvolvimento de um
framework cuja responsabilidade é abstrair as funções básicas necessárias para jogos 2D
como construção de cenários, execução de sons, animações, desenho de imagens e
demais necessidades dos jogos 2D de modo que o aluno possa se concentrar, no projeto
17 / 227
e construção das classes e de suas interações.
A proposta da metodologia deve conter em detalhes o processo de ensino de modo
a ser facilmente replicado. É essencial também para o planejamento de outros
professores, a estimativa da carga horária utilizada e de exemplos de projetos e tarefas a
serem solicitados aos alunos.
Por fim, justifica-se a escolha da linguagem Java em uníssono com Feijó que
caracteriza cinco vantagens para esta linguagem: 1) Permite aplicações em um grande
número de plataformas; 2) Roda em mais de um Sistema Operacional e conta com um
bom ambiente de programação gratuito (NetBeans); 3) O Java é uma linguagem
Orientada a Objetos; 4) Java é um ponto de partida para a programação para internet; e
5) A próxima geração de linguagens orientadas a objetos será uma evolução natural do
Java.
1.2 Objetivo Geral
Criar uma metodologia de ensino de Orientação a Objetos através do
desenvolvimento de jogos 2D.
1.3 Objetivos Específicos
•
Apresentar e analisar algumas das principais metodologias de ensino de
programação orientada a objetos ressaltando seus pontos fortes e fracos segundo
a experiência do autor;
•
Definir diretrizes para o desenvolvimento da metodologia a partir das metodologias
estudadas e da experiência anterior do autor;
•
Elencar elementos pedagógicos que auxiliem a construção da metodologia;
•
Construir um “framework” Orientado a Objetos que atenda as principais
características de jogos 2D e esteja de acordo com as diretrizes definidas;
•
Documentar uma metodologia que atenda a um curso introdutório de programação
orientada a objetos de 72 horas aula de modo a ser facilmente replicada por
qualquer professor de orientação a objetos;
18 / 227
1.4 Metodologia de Pesquisa
Inicia-se o trabalho com a fundamentação teórica de alguns elementos
considerados essenciais ao trabalho como programação orientada a objetos, jogos em
duas dimensões, “frameworks” orientados a objeto e elementos pedagógicos para a
ciência da computação.
Após, considera-se essencial a documentação da metodologia utilizada para o
ensino de orientação a objetos baseados em jogos 2D na experiência que deu origem ao
tema do presente trabalho, de modo que as dificuldades e pontos fortes do ensino anterior
fortaleçam as observações sobre a nova metodologia a ser desenvolvida.
Após, será realizada uma pesquisa nas metodologias para ensino de orientação a
objetos, sendo escolhidas para detalhamento as consideradas pelo autor como mais
relevantes ao desenvolvimento deste trabalho.
A partir deste detalhamento serão definidas diretrizes para o ensino de OO que
deverão ser contempladas nesta metodologia.
Com as diretrizes definidas, bem como os elementos de jogos em duas dimensões,
será proposto um framework que atenda a estes elementos.
Em seguida, é proposta a metodologia de ensino utilizando os elementos
apresentados nos capítulos anteriores.
19 / 227
2 Fundamentação Teórica
Este capítulo apresenta alguns elementos básicos ao trabalho sem, entretanto,
apresentar um estrutura lógica sequencial entre estes elementos, de modo que servem
como base para os demais capítulos e discussões.
2.1 Programação Orientada a Objetos
Biologia e matemática. Esta era a formação base de Alan Kay quando ele criou a
Smalltalk, reconhecida como a primeira linguagem totalmente orientada a objetos, no
famoso laboratório da Xerox PARC em Palo Alto, no final dos anos 60.
Observamos a influência desta formação em dois dos princípios iniciais que
nortearam sua pesquisa, o primeiro era que ele inicialmente pensava em objetos ”como
células biológicas e/ou computadores individuais em uma rede, apenas habilitados a se
comunicarem através de mensagens.”. O segundo, que pode ter sido uma das origens às
modernas classes, é derivado de sua raiz matemática, que lhe fez perceber que “cada
objeto poderia ter certas álgebras relacionadas a ele, e que poderiam haver famílias
destas álgebras, o que seria muito útil.”
Além disso, foi fortemente influenciado pela Sketchpad, Simula, Lisp, o projeto da
ARPAnet e a (segundo ele), quase inacreditável arquitetura dos discos rígidos B500 da
Burroughs.
Estes princípios são compatíveis com Boratti que coloca sobre o paradigma de
Programação Orientada a Objetos:
“Esse paradigma procura abordar a resolução de um problema através de uma
construção que represente, da melhor forma possível, como as coisas acontecem no
mundo real.
O mundo real é constituído por entidades que interagem entre si. Uma entidade pode
ser definida como alguma coisa que tenha sua própria existência, características e que
apresente alguma função no mundo real...uma entidade pode ser denominada objeto e,
consequentemente a identificação do paradigma de programação orientada a objetos”.
20 / 227
Portanto Programação Orientada a Objetos corresponde um modo de programar no
qual são construídos objetos (entidades, células), pertencentes à classes, que interagem
entre si através de mensagens e possuem características próprias.
2.1.1 Conceitos POO
Os conceitos relacionados à POO que serão abordados pela metodologia foram
selecionados principalmente a partir da metodologia de Barnes. Para uma melhor
organização, estes foram categorizados em dois níveis de dificuldade segundo a
experiência do autor:
Nível Básico
Nível Avançado
•
Classe;
•
Métodos de acesso;
•
Interfaces;
•
Métodos modificadores;
•
Classes abstratas;
•
Variáveis e Tipos;
•
•
Variável de objeto / Variável de
Instância / atributo;
Polimorfismo: Variáveis polimórficas /
Polimorfismo de método;
•
Sobrescrita de método;
•
Objetos / Instâncias;
•
•
Parâmetros;
Modificador static: contantes de classe /
métodos estáticos;
•
Construtores;
•
Coesão;
•
Abstração;
•
Encapsulamento / Modificadores de
acesso;
•
Associação / Composição;
•
Herança / Especialização /
Generalização;
Tabela 1: Conceitos POO
Alguns conceitos importantes como “Tratamento de Exceção” e “Acoplamento” não
foram abordados por limitação do escopo do trabalho.
2.1.2 Estruturas Básicas de Programação em Java
De modo a permitir o uso desta metodologia em cursos introdutórios de
programação se faz fundamental o ensino de conceitos de determinadas estruturas
básicas de controle e de repetição. as estruturas e conceitos básicos que serão
abordadas na metodologia serão:
21 / 227
•
Estruturas condicionais (if, else e else if);
•
Estruturas de repetição (while, for e foreach);
•
Arrays / Matrizes unidimensionais e bidimensionais;
•
Instrução de atribuição (=, +=, -=, etc);
•
Variáveis Locais;
•
Comentários;
•
Tipos primitivos;
2.1.3 Conceitos da Linguagem Java
A linguagem utilizada como base para o trabalho é o Java, versão 6, de modo que
algumas de suas especificidades deverão ser levadas aos alunos sempre que necessário.
Estas especificidades podem incluir certas construções sem nenhuma relação com
orientação a objetos, processo de compilação, tipos de arquivos (bytecode, .class, etc) e
certas classes específicas que utilizaremos ao longo do projeto como “ArrayList”.
2.2 Jogos 2D
Esta seção apresenta os principais conceitos utilizados na arquitetura de jogos em
duas dimensões a partir do material desenvolvido por Perucia e que acompanha um
framework desenvolvido na linguagem de programação C++ para o desenvolvimento de
jogos. Um jogo desenvolvido com o framework apresentado por Perucia, pode apresentar,
dentre outros recursos:
•
Menu principal e de opções;
•
Personagem animado controlável por teclado;
•
Cenários com profundidade;
•
Itens especiais de jogo;
•
Interação do personagem com cenário e itens;
•
Inimigos e interação do personagem com estes inimigos;
22 / 227
•
Controle de pontos de vida do personagem;
•
Execução de sons;
A arquitetura de um jogo pode envolver diversos subsistemas, um jogo 2D sempre
apresentará pelo menos alguns dos subsistemas abaixo:
•
Interface gráfica (menus, botões, controle, etc);
•
Tratador de eventos de teclado e/ou joystick;
•
Gerenciador de dados (fases, gráficos, etc);
•
Gerenciador de física (velocidade, movimento, colisão, etc);
•
Engine gráfica (exibição de imagens, rotação, efeitos especiais, etc);
•
Engine sonora;
•
Engine lógica (o coração do jogo);
•
Camadas de abstração de hardware;
•
Sistema de configuração do jogo (opções, nível de dificuldade, salvamento, etc);
•
Sistema de menus;
•
Sistema de ajuda;
•
Sistema de música;
A partir de Perucia et al, dos exemplos tratados por Feijó e da experiência pessoal do
autor foram selecionados os principais conceitos envolvendo a arquitetura de jogos e que
serão indispensavelmente cobertos pelo framework que oferecerá suporte a metodologia
2.2.1 Desenho de imagens
O desenho de imagens na tela a partir de determinados arquivos-fonte é uma
operação frequente e pode ser complementada com recursos desejáveis como
transparência, rotação, aumento ou redução do tamanho original e espelhamento que
corresponde ao desenho da mesma imagem só que em posição invertida ou espelhada.
23 / 227
2.2.2 Animações
Animações são sequências de imagens que se alternam em função de um
determinado tempo. Em um jogo, é importante que seja possível aumentar e diminuir a
velocidade de uma animação (em casos por exemplo, da movimentação de um
personagem mais rápido ou devagar) e que assim como nas imagens, seja possível
aplicar efeitos de transparência, rotação, aumento ou redução do tamanho e
espelhamento.
2.2.3 Tiles e Composição de Cenários
“Tiles são imagens adicionadas em um cenário e divididas em pedaços iguais de
tamanho fixo” (Perucia et al). Tiles podem ser utilizados em conjunto com arquivos de
configuração para criar cenários complexos. Segue abaixo uma demonstração de
construção de um cenário baseado em Tiles.
Ilustração 1: Cenário baseado em Tiles
Na experiência de ensino de POO baseado em jogos, os alunos requisitaram em
vários momentos recursos extras associados ao uso de cenários com Tiles, como por
exemplo: que os tiles possam ser escondidos e reexibidos (para casos por exemplo onde
existam passagens secretas), que possuam tratamento de colisão com o personagem e
demais objetos do jogo e que possam também serem movimentados
2.2.4 Pontos / Plano Cartesiano
Um jogo em duas dimensões ocorre em um plano cartesiano. É importante que
existam abstrações para pontos neste plano e operações entre estes pontos como calculo
da distância e detecção de ponto mais próximo dentre um conjunto de pontos por
exemplo.
24 / 227
2.2.5 Sprites
“Sprites são estruturas com imagens próprias que permitem a criação de
animações e o livre posicionamento na tela” (Perucia). Uma sprite em geral é
representada por um único arquivo dividido em quadros de tamanho fixo, contendo cada
quadro uma imagem. A mesma sprite pode ser posicionada em um determinado ponto da
tela exibindo apenas um dos seus quadros internos por vez. A mudança da exibição
destes quadros ao longo do tempo resulta em uma animação.
Ilustração 2: Exemplo de uma Sprite
2.2.6 Dispositivos de Entrada
A interação com o jogo irá ocorrer sempre através de um dispositivo. Os dois mais
comuns são teclado e mouse. No caso do teclado é preciso que o desenvolver tenha
disponível a informação de se uma (ou um conjunto) determinada tecla está ou não
pressionada em um determinado momento no tempo. No caso do mouse, as principais
necessidades são a posição do ponteiro do mouse e se o botão esquerdo foi pressionado.
Também é importante que exista uma interface para um joystick, ou seja, um
controle tradicional de video-game com 4 botões de ação e quatro botões direcionais.
2.2.7 Execução de sons
Os recursos de som disponíveis para o desenvolvedor são apenas: 1)
carregamento dos arquivos de som; 2) tocar um som (com ou sem loop) e 3) parar um
som. O arquivo de áudio pode ser no formato wave, comumente usado em jogos.
2.2.8 Taxa de Quadros e atualização do jogo
Representa o número de quadros de um jogo que uma aplicação consegue
executar em um segundo. O jogo irá sempre executar uma chamada de atualização do
estado do jogo em loop. A taxa de quadros representa o número de repetições deste
quadro em um segundo.
25 / 227
2.2.9 Acumuladores de Tempo
É comum em jogos eletrônicos determinadas ações somente ocorrerem após um
determinado tempo. Para realizar este cálculo de tempo uma estrutura conhecida como
acumulador de tempo pode ser fornecida. Esta estrutura inicializa com o tempo que irá
controlar e, a cada atualização do jogo, deve também ser atualizada. A estrutura fornece
uma interface para que o desenvolver identifique se o fim do tempo já chegou e a
possibilidade de reiniciar o acumulador.
2.2.10 Gravidade
A gravidade pode ser representada em um jogo por um número em pixels por
segundo que representa a aceleração da gravidade. Na vida real, a força da gravidade
pode ser contrabalanceada pelo atrito com o ar. Em um jogo, ao invés de utilizar o atrito
com o ar, cada objeto recebe um número que representa a aceleração da gravidade sobre
ele. Isso permite por exemplo, que um objeto passe a ter um salto maior, simplesmente se
a força da gravidade sobre ele for diminuída.
No mundo real, existe um ponto em que o atrito com o ar se iguala a força
gravitacional de modo que a velocidade de queda permanece constante. Isto é
reproduzido em um jogo, através de uma velocidade máxima que um objeto pode receber
quando está em queda.
2.2.11 Detecção e Tratamento de Colisões
A detecção de colisões ocorre verificando se duas formas geométricas que
representam objetos do jogo, se tocam. Estas formas geométricas são comumente
retângulos e/ou círculos, e a colisão será verificada através de operações matemáticas
simples que verificam a intersecção destas formas.
Após a detecção ter ocorrido é necessário tratar a colisão. Ou seja, se o
personagem colidir com uma parede à direita, ele não poderá mais se mover para a
direita e deverá ser reposicionado para o exato momento antes da colisão.
Uma das formas de dividir este tratamento é tratando primeiro a colisão com o eixo
vertical e somente após, com o eixo horizontal.
Também é importante que o desenvolvedor tenha condições de saber para qual
direção ocorreu a colisão.
26 / 227
2.2.12 O Game Loop
Todo jogo de computador ocorre dentro de um laço de repetição. Este laço realiza
três operações básicas:
•
Entrada: onde são verificados os comandos emitidos pelos dispositivos de entrada,
mensagens via rede, etc;
•
Processamento: onde é feito o cálculo das posições dos objetos, colisão, etc;
•
Desenho: onde os objetos são apresentados na tela do dispositivo.
2.2.13 Movimentação e Gravidade nos cenários
Os cenários são um dos grandes núcleos do jogo. A grande maioria dos jogos
possuem cenários grandes que podem ser percorridos por um jogador. Além disso, o
efeito da gravidade deve parar de ocorrer quando um jogador encosta no chão,
geralmente definido em função do cenário.
2.3 Frameworks Orientado a Objetos
Este capítulo disserta sobre o desenvolvimento e uso de frameworks orientados a
objetos a partir do trabalho de Silva, esclarecendo as metodologias de desenvolvimento
existentes bem como as maneiras de documentá-la de modo a proporcionar o uso
adequado dos frameworks de acordo com as diferentes necessidades dos seus usuários.
2.3.1 Frameworks OO
Frameworks Orientados a Objetos correspondem a um conjunto de classes que se
adaptam ao desenvolvimento de aplicações de um domínio específico, oferecendo
estruturas flexíveis para os pontos em que aplicações de um mesmo domínio diferem
entre si.
Duas das principais características de um framework são alterabilidade e
extensibilidade:
•
Alterabilidade: Permite que os conceitos específicos das aplicações sejam
suportados a partir de estruturas flexíveis do framework;
•
Extensibilidade: Garante que o framework possa ser estendido no seu conjunto
de funcionalidades, ou seja, tenha sua manutenibilidade garantida;
27 / 227
Um framework sempre depende de outros artefatos de software para existir,
basicamente, as aplicações específicas de um domínio que o originaram e as aplicações
geradas a partir dele.
2.3.2 Metodologias de Desenvolvimento de Frameworks OO
Muitos elementos do processo de desenvolvimento de um framework são comuns à
diversas metodologias, podemos elencar estes elementos da seguinte forma:
•
Aquisição de conhecimento de domínio: A primeira etapa é o estudo de
aplicações desenvolvidas para o mesmo domínio do framework de modo a
identificar generalidades e especificidades dentro das aplicações.
•
Construção da estrutura de classes: Após a análise, é realizada a modelagem
de classes. Esta modelagem pode ser dividida em cinco etapas iterativas:
◦ Generalização: Criação de classes para as estruturas idênticas das aplicações;
◦ Flexibilização: Localização das especificidades dos frameworks;
◦ Aplicação de meta padrões: Criação de métodos template que podem ser
flexibilizados através de métodos hooks para os pontos de flexibilização
encontrados;
◦ Aplicação de Padrões de Projeto: Incluir classes de um padrão (design
pattern) já catalogado e conhecido para uma determinada estrutura do
framework;
◦ Aplicação de Princípios de OO: Aplicação de princípios específicos de
Orientação a Objetos como uso de herança e composição.
•
Implementação: Criação do framework em uma linguagem de programação;
•
Avaliação: O framework deve ser avaliado a partir do desenvolvimento de
aplicações do domínio para o qual foi criado;
•
Refinamento: A partir do desenvolvimento de novas aplicações, o conhecimento
sobre o domínio aumentará, possibilitando a melhoria do framework.
28 / 227
2.3.3 Uso de Frameworks OO
Um framework deve facilitar o desenvolvimento de aplicações de um domínio. Se
entender o framework for muito complexo, pode ser mais fácil desenvolver a aplicação
sem o framework.
Uma das formas de garantir uma documentação que atenda às necessidades dos
usuários do framework é adaptando a documentação à estas necessidades. Segue
abaixo uma proposta de documentação específica para três tipos de usuários comuns:
Tipo de Usuário
Tipo de Documentação
Precisa decidir qual framework
utilizar para o desenvolvimento de
uma aplicação
Descrição do que pode e do que não pode ser feito com o
framework.
Precisa descobrir como desenvolver
uma aplicação
Receitas específicas de como utilizar um determinado
recurso e/ou desenvolver uma aplicação (Cookbook).
Precisam conhecer em detalhes o
projeto do framework para o
desenvolvimento de aplicações
complexas
Podem ser utilizados diagramas, descrições mais detalhadas
da estrutura das classes, código fonte e outras ferramentas.
As questões chave para este entendimento são:
• Quais classes usar: Quais classes concretas do
framework podem ser utilizadas e quais devem ser
criadas pelo desenvolvedor;
• Quais métodos: devem ser redefinidos pelo
desenvolvedor (métodos abstratos) e quais devem
ser definidos pelo framework. Entra aqui também a
definição dos métodos template;
• O que os métodos fazem: qual o cmportamento dos
métodos definidos pelo framework.
Tabela 2: Documentação de “frameworks”
2.4 Padrões Pedagógicos
Como apoio às metodologias de ensino de programação orientada a objetos os
autores frequentemente recorrem à padrões pedagógicos que são projetados para
capturar as melhores práticas e a excelência da arte de aprender e ensinar (THE
PEDAGOGICAL PATTERNS PROJECT) .
Para o ensino de ciências da computação, Joseph Bergin documentou catorze
padrões pedagógicos. Os padrões possuem vários níveis de aplicação, desde a
organização geral de uma disciplina até mesmo práticas em sala de aula. Os padrões são
apresentados em ordem de escala, iniciando pelos que envolvem o planejamento de
cursos semestrais até atividades diárias em salas de aula.
29 / 227
2.4.1 O Mais Importante Primeiro (Early Bird)
O curso é organizado de modo que o mais importante deve ser apresentado
primeiro (e frequentemente), e caso isto seja impossível, o quanto antes. Por exemplo, se
funções for mais importante que estruturas if, ensine funções primeiro, se objetos são
mais importantes que funções, ensine objetos primeiro.
Esta prática é importante porque os estudantes geralmente se lembram melhor do
que viram primeiro e é importante que eles percebam desde o início a ideia principal do
curso.
Alguns exemplos são:
•
Ensinar objetos primeiro;
•
Ensinar projeto primeiro;
•
Ensinar concorrência primeiro em sistemas operacionais;
•
Ensinar requisitos de usuário primeiro em Banco de Dados;
•
Ensinar recursão antes de loops;
2.4.2 Espiral (Spiral)
Quando um conteúdo é trabalhado em sua ordem lógica, o instrutor precisa entrar
em muitos detalhes, tornando o ensino desgastante para os estudantes.
Uma solução é trabalhar os conteúdos em fragmentos que permitam que o
estudante resolva um determinado problema, posteriormente, mais fragmentos são
trabalhados de modo a resolver outros problemas, e assim, sucessivamente, trabalhando
o mesmo conteúdo mas em nível de detalhe crescente.
Deste modo, desde cedo o estudante é empoderado a construir aplicações.
2.4.3 Metáfora Consistente (Consistent Mataphor)
Ao ensinar tópicos complexos, é importante utilizar metáforas cuja base seja
conhecida pelos estudantes, de modo que ele tenham clareza sobre como o sistema deve
se comportar e possam fazer conexões dos novos conceitos com conceitos que já são
bem conhecidos por eles.
30 / 227
2.4.4 Caixa de Brinquedos (Toy Box)
O objetivo deste padrão é permitir que desde cedo os estudantes possam entrar em
contato com o conhecimento da área do curso através de ferramentas pedagógicas
ilustrativas, os brinquedos.
Estes brinquedos podem ser classes que abstraem parte da complexidade
envolvida no desenvolvimento de um software de maior escala, ferramentas que tornam a
programação mais acessível, ou qualquer outro tipo de artefato que permita que os
estudantes desenvolvam projetos maiores e mais interessantes.
Um dos requisitos deste padrão é que os instrutores precisam preparar o material e
ter tempo disponível para que os estudantes explorem os recursos disponibilizados.
2.4.5 Caixa de Ferramentas (Tool Box)
Desde o início do curso os estudantes desenvolvem ferramentas que lhes serão
úteis em fases avançadas do curso, funcionando também como ensino de reuso de
software.
Os exercícios do curso devem ter diversos níveis e nos níveis iniciais os estudantes
são estimulados a discutir e desenvolver seus componentes. É importante também que o
projeto de software para reuso seja discutido e apresentado o quanto antes pelo instrutor.
Estes componentes desenvolvidos pelos alunos podem ser complementados por
bibliotecas fornecidas pelo instrutor. Um bom exemplo da aplicação deste padrão é o uso
de elementos construídos em disciplinas de estruturas de dados.
2.4.6 Disposição do território (Lay of the Land)
Os estudantes devem examinar um artefato do domínio que estão estudando de
maior complexidade, de modo a ver a imagem real de um produto na sua área de
atuação.
Isto permite que eles façam conexões das diversas partes do sistema com os
conteúdos que estão aprendendo, situando cada um deles no contexto de uma aplicação
real.
Exemplos podem ser:
•
Um software com várias classes interagindo em Orientação a Objetos;
31 / 227
•
Um modelo entidade relacionamento com diversos relacionamentos em um curso
de bases de dados;
•
O projeto completo de um software em um curso de projeto orientado a objetos.
É importante que o artefato seja algo semelhante ao que o instrutor deseja que o
estudante desenvolva ao final do curso. É essencial também, que o artefato tenha um
design e utilize os conceitos do curso de forma excelente.
Assim, as diversas partes do artefato a suas interações podem ser examinadas
pelos estudantes e posteriormente utilizadas como exemplo de um determinado conceito
do curso.
2.4.7 Corrigir para cima (Fixer Upper)
Neste padrão, um artefato de grande porte é oferecido aos alunos com falhas
cuidadosamente preparadas. Este padrão permite o ensino de novos conceitos e da
análise e correção de erros.
As falhas devem ser óbvias para a maioria dos leitores, contendo uma ou duas
falhas de maior complexidade.
A origem do nome do padrão vem da expressão “Fixxer Upper” que representa uma
casa vendida em condições ruins, de modo que o comprador precisará repará-la após a
compra.
2.4.8 Maior que a Vida (Larger than Life)
Em cursos de literatura, sociologia e história por exemplo, é comum que os
estudantes trabalhem com textos que eles não teriam condições de criar.
E como ler é mais fácil do que escrever, este padrão fala sobre usar artefatos de
software de maior complexidade e bem escritos como exemplos a serem copiados.
Esta é uma forma de estimular o conhecimento sobre o desenvolvimento de
softwares reais que os estudantes ainda não teriam condições de projetar e desenvolver.
Um exemplo são bibliotecas padrão das linguagens de programação atuais.
32 / 227
2.4.9 Sprint de Projeto dos Estudantes (Student Design Sprint)
Ensinar a projetar softwares é hoje reconhecido como necessidade por muitos
instrutores. Este padrão sugere o uso de atividades que permitam que os estudantes
projetem soluções para problemas, recebam feedback, projetem novamente, recebam
novo feedback, e assim sucessivamente.
Um exemplo de atividade é separar os alunos em grupos de dois ou três e solicitar
o projeto para um determinado problema. Ao final, são levantadas questões que não
podem ser respondidas com um design inadequado e os estudantes são organizados em
grupos de 4 ou 5 de modo que cada grupo tem pelo menos duas propostas de projeto.
Eles são desafiados a criarem uma nova proposta, ao final, mais questões podem ser
levantadas e alguns projetos discutidos. O processo pode continuar enquanto o professor
desejar.
2.4.10 Engano (Mistake)
Os estudantes são estimulados a criarem artefatos com erros propositais, de modo
a ensiná-los como reconhecer erros e suas consequências.
Todos
cometemos erros, profissionais
experientes
geralmente
conseguem
reconhecer um erro quando visualizam as consequências de um, estudantes não sabem
reconhecer estes erros.
2.4.11 Canal de Teste (Test Tube)
Também conhecido como “teste e veja”, este padrão força que os estudantes
testem suas próprias perguntas para questões do tipo “O que aconteceria se eu..”. Desde
que exista acesso a um computador, eles podem testar suas hipóteses.
É importante que o instrutor forneça listas de exercícios levando em conta as
principais dúvidas apresentadas colocando em diversos pontos questões do tipo “O que
aconteceria se você...”.
Isto pode ser usado para testar as regras de sintaxe de uma linguagem por
exemplo e/ou o uso de operadores.
Um bom exemplo é o ensino de loops, onde a simples mudança de algumas
variáveis podem gerar impressões na tela diferentes, de 1 até 10 ou mesmo um loop
infinito.
33 / 227
2.4.12 Preencha as Lacunas (Fill in the Blanks)
É muito difícil e o tempo gasto seria muito alto para estudantes iniciantes
desenvolverem softwares complexos, porém, o que eles podem fazer com as habilidades
iniciais geralmente é muito chato.
A solução proposta é disponibilizar um software complexo que os estudantes
possam analisar e deixar pequenas lacunas no software a serem implementadas pelos
alunos com os conhecimentos que possuem. Um exemplo simples é uma definição de
classe em Java onde o corpo de um método foi deixado em branco.
2.4.13 Estrela de Ouro (Gold Star)
Os estudantes devem ser recompensados pelo que eles fazem bem e jamais os
deprecia por ainda não terem atingido as competências almejadas.
2.4.14 Avalie isto novamente Sam (Grade it again Sam)
Permita que trabalhos e atividades sejam enviados posteriormente para
reavaliação. Isso estimula os estudantes a criarem erros e os motiva a melhorarem seus
trabalhos para melhorar suas notas.
34 / 227
3 Experiência prévia com ensino de POO e Jogos
A
documentação
detalhada
da
primeira
experiência
do
autor
com
o
desenvolvimento de jogos e ensino de OO se fez necessária para demonstração das
principais dificuldades encontradas, de modo a justificar certas escolhas para a
metodologia a ser construída, bem como, os resultados na motivação dos estudantes.
No primeiro semestre de 2012, no curso Técnico em Programação articulado com o
Ensino Médio do SENAI São José em Santa Catarina, na disciplina de Programação
Orientada a Objetos II, foi trabalhado um módulo de desenvolvimento de jogos com Java.
A turma possuia 33 alunos entre 16 e 18 anos.
Esta disciplina está presente no terceiro semestre do curso. Os estudantes já
chegam a esta disciplina com uma base sobre alguns conceitos básicos de OO como
construção de classes, métodos, atributos e parâmetros, bem como conceitos básicos de
estruturas de programação como if, while, switch, dentre outros. Entretanto, por ser um
curso paralelo ao ensino médio e pelo perfil do público, é comum que eles cheguem na
terceira fase após o período de férias sem se lembrar com exatidão dos conteúdos
trabalhados nos semestres anteriores, sendo necessário relembrá-los.
Este módulo teve duração de 76 horas/aula. Destas, 40 horas/aula foram utilizadas
para o ensino dos conceitos de Programação e Jogos 2D. As demais 28 horas foram
utilizadas pelos alunos em sala com orientação do professor para o desenvolvimento do
jogo.
3.1 Conteúdos trabalhados
O conteúdo foi dividido em duas categorias, Programação Orientada a Objetos
(foco da disciplina) e Jogos 2D. Além destes conteúdos, questões como uso de controle
de versão e uma IDE de programação também foram abordados, porém, por não fazerem
parte deste estudo, não serão citados.
Segue abaixo tabela com os conteúdos trabalhados:
35 / 227
Conteúdos POO
C1) Composição;
C2) Encapsulamento;
C3) Herança;
C4) Polimorfismo;
C5) sobrecarga e sobreescrita de métodos e
construtores;
C6) Classes abstratas,
C7) Interfaces;
C8) Enum;
C9) Métodos e atributos estáticos
C10) Tratamento de Exceção
C11) Padrões de desenvolvimento (frameworks);
Conteúdos Jogos 2D
C20) Sprites;
C21) TileMaps;
C22) Animação;
C23) Desenho 2D;
C23) Captura Eventos Teclado;
C24) Captura Eventos Mouse.
Tabela 3: Tabela demonstrando os conteúdos trabalhados na experiência prévia com ensino de
orientação a objetos baseado em jogos.
Para melhor entendimento, segue abaixo uma descrição breve de como cada um
dos conteúdos foi trabalhado:
•
C1) Composição: Para formar objetos de um jogo, como personagens de luta, era preciso
ter uma classe composta de outras que representassem imagens, 'magias' dos
personagens, etc;
•
C2) Encapsulamento: Alguns recursos como colisão de personagens com o cenário foi
encapsulado pelo professor e fornecido através de classes, como forma de passar o
conceito, depois, no desenvolvimento do jogo e dos exemplos em aula eles foram sembre
lembrados de encapsular a lógica de alguns elementos do jogo dentro de sua respectiva
classe;
•
C3) Herança: Todos os objetos do jogo precisavam estender uma classe chamada
GameObject que já possuía características básicas de um objeto, como a posição inicial,
métodos de acesso e métodos modificadores a estes atributos;
•
C4) Polimorfismo: É comum termos itens em jogos 2D, estes itens podem aumentar a
vida do personagem, deixá-lo mais rápido ou mais lento, dentre outras características.
Uma das formas de se trabalhar o polimorfismo foi com classes que representavam itens,
estas classes estendiam uma classe Item, e todos os itens, representados com subclasses
abstratas eram referenciados no projeto como objetos da classe Item, para permitir
extensão do software. Também foi visto polimorfismo de método com métodos de colisão
que podiam receber diferentes parâmetros.
•
C5) Sobrescrita de métodos e construtores: A maioria dos métodos implementados
pelos estudantes eram da própria classe ou abstratos. A sobrescrita foi trabalhada apenas
quando os estudantes estendiam uma classe que representava um objeto com gravidade.
A lógica responsável por parar o objeto em caso de queda se ele colidisse com um chão
era um comportamento padrão que os estudantes precisavam sobrescrever quando
haviam especificidades nos seus objetos, sempre lembrando de chamar o método
sobrescrito da classe superior para não perder o efeito da gravidade;
•
C6) Classes abstratas: A classe GameObject, da qual todos os objetos do jogo devem
herdar, é abstrata e exige a implementação de dois métodos, um para execução da lógica
do objeto e outro para desenhá-lo.
•
C7) Classes Interface: Cada fase do jogo era representada por uma classe que
implementava uma interface. Esta interface apresentava métodos para quando uma fase
iniciava, era carregada, desenhada ou estava em execução;
36 / 227
•
C8) Enum: Quando foram trabalhados jogos de luta, um enum foi utilizado para controlar o
estado do personagem, ou seja, se ele estava pulando, apanhando ou em estado normal;
•
C9) Métodos e atributos estáticos: O framework utilizado apresentava diversos métodos
estáticos, principalmente para recuperar a referência aos objetos que capturam ações dos
periféricos e realizam operações de desenho. Os atributos estáticos foram trabalhados
para representar as teclas do teclado;
•
C10) Tratamento de Exceção: Sempre que uma imagem era carregada para o jogo,
corria-se o risco dela não existir. Neste caso, uma exceção era gerada internamente pelo
software e o estudante deveria tratá-la. Infelizmente neste ponto, apenas era exibida uma
mensagem de erro ao usuário e o tratamento de exceção não foi visto em sua plenitude,
quando o programador usa exceções para manter o software funcionando mesmo em caso
de falhas.
•
C11) Padrões de desenvolvimento (frameworks): Foi utilizado durante toda a disciplina
o framework javaPlay (Feijó et al), de modo que o conceito de framework foi trabalhado
constantemente;
•
C20) Sprites: Em um jogo onde o jogador precisava mover uma nave pelo cenário, foi
utilizada uma sprite com a imagem da nave em todas as direções. Como suporte, foi
fornecida uma classe que desenhava os quadros de uma sprite, adaptada do framework
javaPlay;
•
C21) TileMaps: Cada cenário era representado por um conjunto de Tiles e um arquivo de
configuração que dizia como posicionar os tiles no cenário. Uma classe que desenhava o
cenário a partir do arquivo de configuração foi fornecida;
•
C22) Animação: Foi usado o efeito de bombas explodindo, onde a cada fatia de tempo era
preciso mudar a imagem da bomba desenhada na tela;
•
C23) Desenho 2D: Nos exemplos iniciais foram utilizados somente figuras geométricas
simples como círculos e linhas. Todas desenhadas pela API Graphics do próprio Java;
•
C24) Captura de Eventos Teclado: Através da classe Keyboard fornecida pelo framework
javaPlay com métodos para saber se uma determinada tecla estava pressionada;
•
C25) Captura de Eventos Mouse: Através da classe Mouse fornecida pelo framework
javaPlay com métodos para saber se o botão esquerdo ou direito do mouse estava
pressionado e qual a posição do cursor na tela;
3.2 Metodologia
O principal elemento da metodologia foi o uso de exemplos, no qual era aplicado
um determinado conjunto de conceitos na construção de um jogo e, a seguir, atividades
práticas de melhoria do exemplo apresentado de modo a permitir que o estudante tivesse
um contato com o conceito e a sua implementação.
Apenas em um único momento os estudantes iniciaram o desenvolvimento com
uma tela vazia, neste caso, tinham em mãos um script que os guiaria pelos conceitos e
recursos básicos do javaPlay (Feijo), framework utilizado como base para o projeto.
Antes do início deste módulo com jogos houve uma revisão breve dos conceitos de
classe, métodos, atributos, e outros conceitos básicos de OO.
37 / 227
Todos os exemplos foram desenvolvidos tendo como base o framework javaPlay
(Feijó). E, após um período de aulas teóricas, os alunos puderam desenvolver seu próprio
jogo, com tema livre. Seguem abaixo o relato dos exemplos utilizados:
3.2.1 Exemplo 1 – Movimentando uma bola
No primeiro momento, foi apresentado um exemplo de uma bola se movimentando
horizontalmente na tela a partir do movimento do teclado (Caminha, Exemplo 1). Esta
lição demonstrou o uso básico do framework, como acessar o teclado e como criar um
objeto de jogo, no caso, a bola.
Ilustração 3: Movimentando uma bola na tela
Após a apresentação, os estudantes receberam a tarefa de permitir o movimento
vertical da bola no eixo vertical sem perder o movimento horizontal existente. Ao final, um
exemplo de um jogo mais complexo (Caminha, Exemplo 2) utilizando o objeto da bola foi
mostrado para exemplificar o potencial do que eles estavam aprendendo. Também foi
disponibilizado um tempo para que eles fizessem alterações neste exemplo mais
complexo, agora porém, de forma livre.
Ilustração 4: Exemplo mais complexo utilizando a bola criada
anteriormente
38 / 227
3.2.2 Exemplo 2 – Construindo o primeiro jogo
No segundo momento, era importante que os estudantes iniciassem o
desenvolvimento de um jogo simples, porém, passando por todas as etapas do processo
de desenvolvimento, já que na etapa anterior, haviam apenas realizado uma modificação.
Para auxiliá-los foi fornecido um roteiro de 10 passos (Caminha, javaPlay em 10
passos) que guiava a construção de um jogo (Caminha, Exemplo 3) no qual o
personagem controla um jogador em formato de bola (verde) que deve fugir de alguns
inimigos (bolas amarelas e vermelhas) até um elemento de chegada, uma estrela.
Ilustração 5: Tela final do jogo desenvolvido com o auxílio do roteiro
3.2.3 Exemplo 3 – Ítens e fases
Passamos agora a melhorar o jogo desenvolvido com o auxílio do roteiro. A
primeira atividade foi o uso do framework para poder realizar a passagem de fases.
Então, foi construído um jogo com três fases.
1. A primeira fase corresponde ao jogo já criado na etapa anterior;
2. Na segunda fase o personagem também pode capturar itens. Um dos itens é
representado por um quadrado verde e aumenta a velocidade do jogador. O
segundo é um quadrado vermelho e inverte a movimentação. Para a construção
dos itens foi criada uma classe abstrata que obriga o programador a implementar
um método de ação quando o personagem tem colisão com alguns dos itens.
Antes de avançar para a terceira fase, os estudantes são orientados a criar um
novo tipo de item;
3. Na terceira fase, uma única lista é utilizada para armazenar os diversos itens do
39 / 227
jogo. Quando existe colisão com algum deles o método definido na classe abstrata
é executado.
Ilustração 6: Terceira fase do exemplo com diversos itens na tela
3.2.4 Exemplo 4 – Guerra Especial
A partir deste ponto, iniciou-se o trabalhando com o uso de imagens e a criação de
novos objetos a partir de objetos já existentes. Decidi utilizar uma metáfora similar aos
projetos anteriores e escolhi um jogo no qual o jogador controla uma nave que se move
pelo cenário e precisa destruir as naves inimigas (Caminha, Guerra Espacial).
Como este projeto era complexo, ele foi divido em 4 etapas:
•
Etapa 1: apenas foi desenhada uma nave que se movimentava livremente pelo
cenário, de modo a trabalhar o uso das classes para desenho de imagens;
•
Etapa 2: a nave foi capaz de atirar. Os tiros eram criados pela nave, de modo a
trabalhar que um objeto era capaz de criar outros objetos ao longo da execução do
software. Estes tiros são armazenados em uma lista, trabalhando a capacidade
dinâmica de armazenamento das listas;
•
Etapa 3: uma nave inimiga é criada e o objetivo é, com os tiros, eliminar a nave
inimiga. Este módulo trabalha principalmente a interação entre três objetos
diferentes em tempo de execução. Também é adicionada uma classe que gerencia
a explosão que ocorre quando o tiro acerta a nave.
•
Etapa 4: um segundo jogador é adicionado e explosões especiais são adicionadas
quando uma nave inimiga atinge um dos jogadores. Várias naves inimigas são
40 / 227
criadas e os tiros de ambos os jogadores podem acertar as naves. Isto cria um
ambiente complexo que só pode ser gerenciado através do uso de listas. Cada
jogador é construído com uma classe de modo a estimular os estudantes na
identificação de código duplicado e possibilidade de herança.
Ilustração 7: Versão final do jogo Guerra Espacial
3.2.5 – Personagens e Cenários
Nesta etapa, era importante demonstrar os mesmos conceitos abordados em outro
contexto. Foi escolhido o contexto de jogos com cenários e gravidade. Nestes jogos um
personagem se movimenta por um cenário que possui uma estrutura considerada como
chão e pode saltar sobre obstáculos, plataformas e outros. Como este projeto envolvia
grande complexidade, foi dividido em 2 etapas:
•
Etapa 1: Apenas um personagem (chamado Ryu) se movimentando por um
cenário construído a partir de um arquivo de configuração. Toda a colisão com o
cenário é feita por uma classe que encapsula a lógica. Os alunos não são
instruídos sobre a lógica utilizada pela classe devido a sua complexidade. Os
estudantes são instruídos sobre como controlar os pulos do personagem
(Caminha, Exemplo Ryu);
•
Etapa 2:
Após, são adicionados inimigos na fase representados por bolas
vermelhas que rolam em direção ao jogador, semelhante as naves inimigas no jogo
Guerra Espacial (Caminha, Exemplo Ryu 2).
41 / 227
Ilustração 8: Personagem saltando sobre um inimigo
representado por uma bola vermelha
3.2.6 – Jogo de Luta
Como exemplo final foi trabalhado um jogo de luta utilizando o mesmo personagem
anterior contra outro personagem (chamado Vegeta). Neste jogo os personagens
possuem golpes e um deles pode atingir o outro. Este material serviu principalmente
como estímulo ao desenvolvimento dos jogos dos alunos no projeto final e demonstrou
comportamentos mais complexos de interação entre os objetos (Caminha, Ryu vs
Vegeta).
Ilustração 9: Exemplo jogo de luta
3.2.7 – Revisão
Ao final foi preparado um material de revisão de todos os conceitos relembrando os
tópicos abordados e todos os conceitos apresentados (Caminha, Revisão jogos 2D).
42 / 227
3.3 Avaliação e Resultados
A avaliação da disciplina foi feita através de conhecimentos e habilidades. Por
conhecimento entende-se as capacidades teóricas, avaliadas com três provas de curta
duração e uma de revisão sobre todo o conteúdo. Por habilidades entende-se a
capacidade prática de desenvolver um jogo utilizando os conceitos aprendidos.
Para avaliar o nível de motivação com a disciplina, principalmente ao trabalharmos
o tema de jogos, foram incluídas questões sem peso avaliativo e de resposta voluntária
nas provas teóricas.
3.3.1 Avaliação Teórica
As três primeiras provas avaliaram diferentes aspectos ao longo das 40 horas/aula
trabalhadas e ao final do conteúdo, houve uma prova com todo o conteúdo abordado
durante o ensino. As três primeiras provas foram divididas em duas partes, a primeira
parte era sempre aplicada no início das atividades e a segunda ao final. Segue a
descrição de cada uma e a média de pontuação obtida.
•
Primeira prova: foi aplicada logo após a construção do primeiro jogo e abordou
conceitos complexos como classes abstratas, interface e herança. A média geral da
prova em uma escala de 0 a 100 foi de 66 pontos e meio (Caminha, Prova 2 a e
Prova 2b).
•
Segunda prova: Após este resultado baixo os mesmos conceitos foram
retrabalhados nos exemplos posteriores e a segunda prova foi aplicada após o
exemplo com uso de itens e diversas fases, de modo que polimorfismo foi incluído
com os demais conteúdos na prova. A média geral da turma foi de 90 pontos em
uma escala de 0 a 105 (Caminha, Prova 3a e Prova 3b).
•
Terceira Prova: A terceira prova teve como foco o reuso de código com
composição e herança, acrescido de alguns poucos tópicos sobre jogos 2D. A
média geral foi de 73 em uma escala de 0 a 100 (Caminha, Prova 4a e 4b).
•
Prova de Revisão: A prova revisão foi aplicada a todos os alunos após a revisão
com o objetivo de verificar de forma ampla o entendimento teórico da disciplina
após todo o conteúdo trabalhado. Esta prova teve pelo menos um tópico sobre
cada conteúdo trabalhado e a média geral da turma foi de 72 pontos em uma
escala de 0 a 100 (Caminha, Prova de Revisão).
43 / 227
Após a análise da prova percebi que as questões envolvendo os conceitos de
herança, composição, polimorfismo, classes abstratas e classes interface foram
devidamente absorvidos.
Porém, tive índice de erro de quase 50% em uma questão que envolvia a
identificação e classificação de algumas estruturas básicas como atributos, métodos e
construtores (questão 3 da prova de revisão). Porém, no momento de correção da prova
praticamente todos percebiam e compreendiam o erro após este ter sido identificado.
A hipótese levantada é que esta dificuldade ocorreu poque foi trabalhado muito com
estruturas básicas já prontas que eles apenas copiavam, colavam e modificavam para a
sua necessidade, até mesmo quando era criada uma aplicação do zero, eles tinham um
roteiro com códigos fonte de apoio.
Como trabalhamos neste modelo por dois meses e a disciplina anterior de
Orientação a Objetos havia sido ministrada no ano anterior, acredito que eles acabaram
esquecendo o nome de algumas estruturas simples.
3.3.2 Avaliação da Motivação
Na primeira prova, logo após a construção do primeiro jogo os estudantes foram
perguntados se estava sendo interessante aprender Orientação a Objetos com Jogos.
82% disseram que sim, 9% não responderam e 9% disseram que não fazia diferença.
Havia uma opção para o caso de não estar gostando, nenhum estudante marcou esta
opção.
Ficou claro também na relação de convivência que o interesse havia aumentado
muito em relação à disciplina de Programação Orientada a Objetos I onde havíamos
trabalhado com softwares Desktop e com exemplos proposto por Barnes.
Ao final, pelo menos 5 alunos demonstraram grande interesse em seguir a carreira
de programador de jogos.
3.3.3 Avaliação Prática
Ao final das 40 horas aula teóricas, os estudantes tiveram 28 horas aula para
desenvolver o próprio jogo. Os 33 alunos se organizaram em 8 grupos e desenvolveram
os seguintes trabalhos:
44 / 227
3.3.3.1 Grupo 1 – PowerMusic
Jogo similar ao popular GuitarHero onde o jogador simula que está tocando uma
guitarra no acompanhamento da música e deve pressionar os botões correspondendo a
nota da guitarra no momento exato indicado por uma animação na tela.
3.3.3.2 Grupo 2 – Champions Fighter
Jogo de luta como o apresentado no exemplo para a turma com personagens
clássicos de diferentes desenhos animados e jogos de vídeo-game. Cada personagem
pode dar socos, chutes e alguns contém um especial.
3.3.3.3 Grupo 3 – Ghomaine
Jogo de luta como o apresentado no exemplo para a turma com personagens
clássicos de diferentes desenhos animados e jogos de vídeo-game com o diferencial de
cada personagem contém de 2 à 3 ataques especiais específicos.
3.3.3.4 Grupo 4 – Ice Crown Citadel
Jogo com muitas fases onde três jogadores unem habilidades distintas para
derrotar diversos inimigos. Cada inimigo representa uma fase no jogo.
3.3.3.5 Grupo 5 – Moluscation
Um personagem criado pelos estudantes deve percorrer um cenário pulando por
obstáculos e bombas. A cada fase é possível ganhar alguns poderes especiais.
3.3.3.6 Grupo 6 – Terrorist Strategy
Jogo no estilo do clássico Bomberman onde dois personagens disputam entre si
lançando bombas em um cenário com obstáculos.
3.3.3.7 Grupo 7 – God of Worms
Disputa entre duas minhocas realizado em turnos. Cada minhoca, no seu turno,
pode lançar um tiro sobre a outra escolhendo um ângulo e uma força.
3.3.3.8 Grupo 8 – Sami Game
Jogo similar a um futebol de botão no qual cada personagem é um círculo que
precisa acertar uma bola e jogá-la para dentro do gol adversário.
45 / 227
3.3.4 Resultado avaliação prática
A avaliação técnica do jogo contou com diversos critérios para verificar se os
conceitos de Orientação a Objetos foram aprendidos corretamente, segue abaixo os
critérios, o respectivo índice de acerto médio dos grupos e o número de grupos que
atenderam perfeitamente ao critério:
Critério
Porcentagem de
Acerto
Número de Grupos com
acerto máximo
Uso de Composição
90%
6
Uso de Herança
81%
4
Uso de Polimorfismo
38%
3
Classes Enum
38%
3
Classes Abstratas
38%
3
Uso de Listas (ArrayList)
88%
5
Tabela 4: Índice de acerto em cada um dos critérios de avaliação do jogo 2D
A avaliação mostrou de forma clara que os estudantes não conseguiram identificar
em seus projetos oportunidades para uso de recursos mais avançados de programação
como polimorfismo e classes abstratas.
Foi identificado na maioria dos projetos oportunidades do uso destes recursos, de
modo que as restrições não foram decorrentes dos jogos projetados.
Outros conceitos mais básicos como herança e composição foram absorvidos com
tranquilidade e implementados com qualidade pela maioria dos grupos. No caso de
herança, apesar de todos terem utilizado pelo menos alguma classe com herança,
existiam muitos lugares no código onde a herança seria adequada e o grupo não
percebeu. Por isso que apenas metade dos grupos atingiram aproveitamento perfeito
neste quesito, tendo, todos os outros, aproveitamento parcial.
3.3.4 Conclusão ao final do módulo
Ficou evidente o grande aumento da motivação dos alunos, principalmente pela
46 / 227
qualidade de muitos dos jogos apresentados ao final da disciplina.
Porém, a ênfase em um grande conjunto de códigos previamente elaborados que
eles apenas modificavam acabou por gerar dificuldade em reconhecer quando e como
aplicar um determinado conceito aprendido para um problema novo. Por exemplo, eles
tinham facilidade em entender quando usar herança para os casos semelhantes aos
apresentados em sala, mas não em casos diferentes.
Acredito que a metodologia aqui adotada carece de maturidade na elaboração de
atividades e exemplos que permita aos estudantes adquirirem maturidade no processo de
desenvolvimento e identificarem adequadamente onde cada conceito pode ser aplicado.
47 / 227
4 Ensino de Programação Orientada a Objetos
O ensino de programação em Java implica em grandes desafios para o ensino de
programação orientada a objetos. segundo Barnes, um programa mínimo em java possui
numerosos obstáculos de sintaxe tas como: escrever uma classe; escrever um método
main; a criação de um objeto utilizando a palavra-chave new; uma atribuição a uma
variável, a declaração de uma variável, incluindo o tipo; uma chamada de método;
utilizando a notação de ponto; possivelmente, uma lista de parâmetros.
Podemos somar a isso o excesso de conhecimento necessário para realizar
operações básicas de input e output, o grande número de termos como instância,
herança, método com os quais os estudantes não estão familiarizados e a dificuldade
adicional para os estudantes cuja língua nativa não é o inglês (Clark).
Por fim, alguns autores (Barnes, Feijó) identificaram a necessidade de ensinar
através de projetos, para que os conceitos possam ser vistos em aplicações reais.
Esta seção visa apresentar algumas metodologias para o ensino de Orientação a
Objetos com Java e extrair ao final, um conjunto de diretrizes guia para o presente
trabalho.
4.1 Metodologias para Ensino OO
Para a elaboração deste trabalho foram escolhidas cinco metodologias de ensino
de Orientação a Objetos. Os critérios para a escolha foram a sua relevância entre os
instrutores de programação e a experiência prática do autor deste trabalho com cada
metodologia.
A primeira metodologia é a desenvolvida pelo professor do Departamento de
Informática e Estatística da Universidade Federal de Santa Catarina, Isais Camilo Boratti.
Metodologia responsável pelo primeiro contato do autor com Orientação a Objetos.
A segunda é a de maior abrangência internacional, principalmente por ter sido a
48 / 227
primeira metodologia a vir acompanhada de um livro texto e de uma ferramenta que
oferecesse suporte total a ela. É a metodologia construída por David J. Barnes e Michael
Kolling utilizando o BlueJ como ambiente de programação. Esta metodologia foi utilizada
parcialmente pelo autor para um curso de Programação Orientada a Objetos I de 90 horas
aula.
A terceira escolhida foi a metodologia de introdução à ciência da computação com
jogos que deu origem ao curso apresentado no capítulo três, baseada no trabalho de
Bruno Feijó do VisionLab da PUC do Rio de Janeiro.
A quarta, é a metodologia desenvolvida por Stelios Xinogalos ao longo de quatro
anos de ensino de programação orientada a objetos. Xinogalos também trabalhou com a
metodologia de Barnes e Kolling, porém com o tempo, passou a adotá-la apenas
parcialmente no projeto do seu curso, utilizando um conjunto mais abrangente de
ferramentas.
Por fim, para atender uma necessidade observada pelo autor deste trabalho, foi
adotada a metodologia de Caspersen, que trabalha com uma abordagem baseada na
modelagem do problema a ser resolvido antes de trabalhar como produzir o código para
um determinado problema.
Para cada metodologia é apresentada a sequencia de seções da metodologia com
os respectivos conteúdos e exemplos trabalhados. Após, é feita uma descrição geral do
método, uma análise dos pontos fortes e fracos de cada metodologia e uma revisão final.
4.1.1 Isaias Camilo Boratti
Esta metodologia foi vivenciada pelo autor como aluno no primeiro semestre de
2007, no curso de Sistemas de Informação da Universidade Federal de Santa Catarina,
na disciplina de Programação Orientada a Objetos I.
A disciplina foi ministrada pelo próprio professor Isaias Camilo Boratti que, no
mesmo ano, em agosto, publicou o livro que documenta a metodologia intitulado
“Programação Orientada a Objetos em Java”.
O livro está organizado em oito capítulos conforme tabela abaixo:
49 / 227
Capítulo
Exemplos de Projetos Desenvolvidos
Principais Conceitos abordados
Capítulo 1
Nenhum projeto desenvolvido
• Relação POO com o mundo
real;
• Processo de Abstração;
• Operações de Abstração.
Capítulo 2
Nenhum projeto desenvolvido
• Objetos e Classes;
• Representação visual de objetos
e classes;
• Linguagem Java;
Capítulo 3
• Imprimir na tela uma linha de texto;
• Calcular a soma de dois números;
• Escrever um programa que determine a área
de um círculo;
• Método main;
• Identificadores;
• Tipagem de valores;
• Variáveis;
• Criação de objetos;
• String / sequência de caracteres;
• Declaração de atributos;
• Declaração de métodos;
• Construtores;
• Parâmetros e Argumentos;
• Compilação Java;
• Processo de modelagem de um
software a partir de um problema;
Capítulo 4
• Escrever uma aplicação que determine a
distância entre dois pontos;
• Implementação de métodos;
• Métodos de acesso e métodos
modificadores;
• Implementação de construtores;
• Escopo;
• Comentários;
• Parâmetros;
• Implementação de objetos /
referência para um espaço de
memória;
• Tipagem de valores;
• Atribuição;
• Conversão explícita de tipo;
• Expressões aritméticas;
• Expressões Lógicas;
Capítulo 5
• Escrever um programa que determine a
• Processos de repetição / loops;
idade média de um grupo de pessoas;
• Processos de tomada de decisão.
• Escrever um programa que determine a
Ex: if, switch;
média de idade das pessoas do sexo masculino e • Encapsulamento;
também a média de idade das pessoas do sexo
• Modificadores de acesso;
feminino de um grupo de pessoas;
• Palavra chave this;
• Classe Aluno;
• Classe Triângulo;
50 / 227
• Verificar se um número é primo;
Capítulo 6
• Desenvolver uma aplicação que faça uma
análise do desempenho de alunos em
determinada disciplina. A aplicação deve
determinar, para cada um dos alunos, a sua
média final, juntamente com uma informação
dizendo se o aluno foi aprovado ou não.
Considerar que o aluno tenha realizado três
avaliações, todas com o mesmo peso;
• Em um determinado jogo de dados
participam dois jogadores. Cada jogador deve
lançar o dado e computar para si os pontos
obtidos. Será considerado vencedor o jogador
que atingir um total de 100 pontos ou mais.
Sempre que no lançamento do dado, o jogador
obter o valor 1 ou 6, este terá direito a um novo
lançamento;
• Modelagem das classes Funcionario, Chefe
e Apoio, sendo as duas últimas subclasses de
Funcionario;
• Modelagem da classe abstrata Contribuinte e
das subclasses Fisico e Juridico.
•
•
•
•
•
•
•
•
Capítulo 7
• “Desenvolver uma aplicação que avalie o
desempenho de um grupo de estudantes em
determinada disciplina...que prevê a realização
de vários testes e uma prova final...a média dos
testes terá peso de 60% e a prova final peso de
40%.... ”
• Arranjos / Arrays;
• Arrays Multidimensionais;
• Operações com arrays.
Capítulo 8
•
•
•
•
•
Herança;
A palavra-chave super;
Reutilização de código;
Sobreposição de métodos;
Polimorfismo;
Polimorfismo de método;
Sobrecarga de métodos;
Classes abstratas;
Atributos de classe;
Métodos de classe;
Métodos da classe Math;
Manipulação de Strings;
Classe Character;
Tabela 5: Conteúdos e Exemplos da metodologia de Boratti
4.1.1.1 Análise Geral do Método
A metodologia inicia demonstrando que o mundo real “é constituído por entidades
que interagem entre si”, e que tais entidades possuem características e funções, podendo
também serem chamadas de objetos.
Dessa forma, a construção de um software orientado a objetos passa pelo processo
de identificação dos objetos envolvidos e de como estes objetos irão se relacionar entre si
para a resolução de um determinado problema.
51 / 227
A partir disto, Boratti conduz o estudante pelo conceito de abstração, que
corresponde:
“ao processo utilizado na análise de determinada situação, através da qual observa-se
uma realidade, tendo-se por objetivo a determinação dos aspectos e fenômenos
considerados essenciais, excluindo-se todos os aspectos considerados irrelevantes.”
E a partir de problemas simples como “determinar o raio de um círculo” demonstra
como o problema pode ser modelado em termos de objetos com características e funções
interagindo entre si, modela as classes que representam estes objetos e apresenta sua
respectiva implementação em Java.
Os conceitos chave são demonstrados na medida em que são úteis para resolver
problemas mais complexos e sub seções complementares se encarregam de
determinados aspectos da linguagem Java como operadores matemáticos e detalhes de
sintaxe, sem necessariamente, serem parte da solução dos problemas apresentados.
Ao final de cada seção, é apresentado um resumo dos conceitos e conhecimentos
trabalhados, uma lista de exercícios, geralmente extensa e abrangente, nos casos que
apresentem conteúdo prático, diversos exercícios resolvidos também são fornecidos.
Por fim, ressalta-se que todos os códigos construídos por Boratti são em língua
portuguesa e sempre que apresentam recursos novos, são comentados com descrições
detalhadas do seu comportamento.
4.1.1.2 Pontos Fortes
4.2.1.2.1 Operações de Abstração
No capítulo introdutório da metodologia, Boratti traz o conceito de operações de
abstração que “mostram como o ser humano mentaliza, organiza e modela o mundo ao
seu redor”. Estas operações são úteis na medida em que definem uma taxionomia para
as interações entre as entidades no mundo real e podem ser representadas diretamente
através de código orientado a objetos. Logo, o processo de analisar uma interação entre
entidades no mundo real e o código que deve ser construído para resolver problemas
envolvendo esta interação pode ser mais adequadamente identificado.
As Operações de abstração são demonstradas utilizando representações parecidas
com o utilizado pelo diagrama de classes da UML para as classes identificadas.
Segue abaixo as quatro operações de abstração:
52 / 227
•
Classificação / Instanciação: Classificação corresponde a determinar um
conjunto de características de um determinado grupo de objetos de modo a
classificá-los em uma categoria ou classe. Instanciação é o processo inverso, no
qual exemplos (instâncias) de determinadas categorias são ressaltados. Por
exemplo a Classe Carro e Instância carro vermelho do josé;
•
Generalização e Especialização: Generalização ocorre quando determinamos
características comuns a conjunto de classes e assim, criamos uma classe mais
genérica. Especialização é o inverso, quando a partir de uma classe genérica,
determinamos classes especialistas. Por exemplo, a classe genérica Médico
poderia ser especializada em Obstetra, Pediatra e Ornitolaringologista;
•
Agregação / Decomposição: A Agregação é caracterizada pela relação de “é
composto por” entre duas classes. A decomposição é quando dizemos que um
objeto “é parte de” outro objeto. Por exemplo, a classe Carro é composta por
objetos da classe Motor. Já um objeto da classe Motor é parte de um objeto da
classe Carro;
•
Associação: Ocorre quando dois objetos possuem algum tipo de ligação entre si
mas podem existir independentemente do outro, Por exemplo, na relação que
ocorre entre objetos das classes Professor e Aluno.
4.2.1.2.2 Processo de Modelagem
Boratti coloca que o modelo de resolução de um problema, ou seja, o software, é o
resultado de um processo de abstração que em orientação a objetos corresponde à
identificação dos objetos com suas características e funções e a respectiva modelagem
das suas classes.
Ilustração 10: A Construção do modelo. Fonte: Boratti
53 / 227
4.2.1.2.3 Representação Visual de Objetos
Após a identificação dos objetos é necessário representá-los visualmente pelo
projetista de software. A visualização proposta por Boratti utiliza um círculo para
representar um objeto com um texto dentro representando o identificador deste objeto.
Quando um objeto é composto por outros objetos estes são representados como círculos
dentro do círculo maior. No caso de atributos simples de um objeto como números e
textos, estes objetos são representados com um retângulo.
Ilustração 11: Representação Visual de Objetos. Fonte: Boratti. Adaptado por Kaléu Caminha
4.2.1.2.4 Implementação de Objetos
Recordo, como estuante do professor Isaías Boratti, que fortaleceu muito o meu
aprendizado no momento que compreendi que cada objeto ocupava um espaço na
memória e que uma variável, na verdade, era um apontador para este espaço na
memória.
Este aspecto da implementação de objetos é tratada na seção 4.8 onde Boratti
coloca que “a identificação de um objeto constitui-se em uma posição na memória
(portanto, uma variável) que armazena o endereço do espaço de memória ocupado por
aquele objeto”.
Para exemplificar este conceito o seguinte código é apresentado:
Ponto umPonto, outroPonto; // Um ponto contém um atributo inteiro x e um
y
umPonto = new Ponto();
54 / 227
outroPonto = new Ponto();
outroPonto.redefina_se(2.0, 3.0); // este método altera os valores de x
e y
E a partir do código acima, é utilizada uma adaptação da visualização de objetos
demonstrando que as variáveis são apenas apontadores para os objetos:
Ilustração 12: Implementação de Objetos. Fonte: Boratti.
Adaptado por Kaléu Caminha
4.2.1.2.5 Representação Visual de um Array
Arranjos, como são chamados os tradicionais Arrays por Boratti são “elementos que
armazenam vários valores”. Para facilitar o ensino foi criado um modelo visual para o uso
de arrays. Para exemplificar o modelo usaremos o seguinte código:
int[] numeros = new int[8];
int cont = 2;
numeros[1] = 34;
numeros[cont] = 15;
numeros[cont+1] = numeros[cont] – 10;
O código acima apresentaria a seguinte representação visual:
Ilustração 13: Representação Visual de um
Array. Fonte: Boratti. adaptado por Kaléu
Caminha
55 / 227
4.1.1.3 Pontos Fracos
4.2.1.3.1 Início pelo método main com Hello World
Após os dois primeiros capítulos de introdução, com uma explicação detalhada e
abrangente sobre orientação a objetos e o processo de modelagem, o primeiro programa
mostrado tem como problema “Imprimir uma linha na tela” e o seguinte código-fonte:
public class Programa1
{
//Declaração do método main
public static void main(String[] parametro)
{
System.out.println(“Primeiro Programa!”);
}
}
O programa que resolve este problema não envolve a criação de nenhum objeto, e
o único método chamado é um método acessado através de um atributo estático da
classe System, usando notação de ponto.
E isto é feito dentro do método main, um método estático que exige como
parâmetro um array de strings, conteúdos que somente serão trabalhado nos capítulos
sete e oito.
É evidente que esta abordagem se torna necessária na medida em que Boratti, por
não adotar nenhuma ferramenta que suporte a execução de código sem a criação do
método main, não tem saída a não ser iniciar por ele.
Esta abordagem porém, não é interessante pois a primeira porção de código que o
estudante enxerga é algo absolutamente incompreensível para ele, devido a grande
quantidade de conceitos envolvidos (Kolling e Rosemberg).
4.2.1.3.2 Primeiro o código, depois o conceito
Em diversos exemplos, certas regras de sintaxe são apresentadas, cujos conceitos
envolvidos somente são trabalhados em seções ou capítulos posteriores.
Um exemplo é a primeira classe com a qual os alunos tem contato. A classe
Círculo, apresentada como o terceiro trecho de código com o qual os estudantes tem
contato.
public class Circulo
{
//Declaração do atributo
56 / 227
protected double raio;
//Declaração dos métodos
public Circulo()
{
raio = 0.0;
}
public double forneceArea()
{
double area;
area = 3.1415*raio*raio;
return area;
}
public void recebaValorRaio(double vRaio)
{
raio = vRaio;
}
}
Esta classe apresenta mais de 10 conceitos: comentários, declaração de atributos,
tipagem de variáveis, declaração de método com retorno, declaração de método sem
retorno, declaração de um construtor, assinatura de classe, parâmetros, atribuições,
operações matemáticas e uso de modificadores de acesso.
A maioria destes conceitos só serão trabalhados posteriormente, por exemplo,
atribuições serão detalhadas no capítulo 4 enquanto modificadores de acesso somente
serão vistos no capítulo 5.
Percebe-se que esta abordagem tem como intenção demonstrar a modelagem
completa de uma classe adequadamente escrita para resolver um problema. Isto fica
claro pelo uso de modificadores de acesso desde o início, com a intenção de evitar que
estudantes declarem atributos como públicos.
Isto causa, porém, uma sobrecarga de conceitos apresentados sem a devida
possibilidade do estudante experimentar cada um deles e suas consequências para o
programa, sem saber qual a função de cada palavra-chave.
4.2.1.3.3 Métodos estáticos desde o início
Para complementar o exemplo do capítulo 3 no qual é preciso determinar a área de
um círculo a partir do seu raio, é apresentada uma classe chamada Interface (que não
tem nenhuma relação com o conceito de interfaces em Java) responsável por solicitar ao
usuário um número que irá representar o raio do círculo.
O principal método desta classe chamado “pegaValorRaio” contém 4 linhas,
conforme apresentado abaixo:
57 / 227
…
String valorLido;
valorLido = JoptionPane.showImputDialog(“Digite o raio: ”);
double valor = Double.parseDouble(valorLido);
return valor;
…
O problema deste método é que as principais instruções são métodos estáticos de
classes específicos da biblioteca do Java. Isso nada ensina sobre orientação a objetos,
sendo necessários apenas para que o programa seja minimamente interessante.
Construções como esta são utilizadas em outros pontos como no capítulo 4 com o
uso do método sqrt da classe Math, responsável por recuperar a raiz quadrada de um
número.
A grande crítica a esta abordagem é que métodos e atributos estáticos são
ensinados apenas no capítulo 8, de modo que o estudante precisa simplesmente ignorar
o fato da sintaxe ser diferente de outros objetos com os quais ele trabalha.
O autor já presenciou, como professor, estudantes que foram ensinados sob
metodologias parecidas chamando métodos diretamente das classes, sem diferenciar se
um método era ou não estático.
4.1.1.4 Conclusão
A metodologia se mostra muito interessante ao tornar claro para o estudante o
processo de construção de um software, a sua respectiva modelagem de objetos e
classes e as diversas representações visuais do programa.
Também se mostra interessante a forma de abordar os conceitos sempre que
possível a partir de problemas do mundo real. Observa-se porém que a complexidade dos
problemas tratados é muito pequena como por exemplo, calcular a média de um grupo de
alunos ou determinar a área de um círculo.
Um dos motivos para o uso de exemplos triviais é a dificuldade em utilizar recursos
avançados de programação em função da complexidade destes recursos conforme
apresentado pela linguagem Java. De forma mais clara isto é visto na modelagem da
classe Interface que para recuperar um valor digitado pelo usuário precisa de métodos
estáticos logo no início da metodologia.
Este ponto ressalta que alguns dos pontos fracos observados na metodologia
poderiam ser melhor trabalhados com o apoio de um ferramental adequado como um
58 / 227
editor que não exigisse a criação de um método main para executar código ou uma
ferramenta que permitisse executar métodos diretamente dos objetos.
4.1.2 David J. Barnes e Michael Kölling
“Partindo de Objetos em Java”. Esta é a primeira frase do livro-texto para a
metodologia. A metodologia utiliza o ambiente de programação BlueJ e possui como
algumas de suas linhas guia:
•
Uma abordagem iterativa: A partir do uso do padrão “Early Bird”, documentado na
seção 2.4 os principais conceitos são apresentados primeiro de uma forma
simplificada para que um determinado problema seja resolvido. Posteriormente no
curso, os mesmos conceitos são retomados segundo outro ponto de vista e o
conhecimento é aprofundado;
•
Sem completa cobertura da linguagem: em função do foco do livro ser em POO,
detalhes específicos da linguagem java não são abordados a menos que sejam
necessários para a resolução de um determinado problema;
•
Abordagem baseada em projeto: ao invés de introduzir uma nova construção e
então fornecer exercícios para aplicar a construção aprendida, primeiro é fornecido
um objetivo e um problema. A análise do problema determina o que será
necessário e então, os recursos da linguagem e os conceitos são apresentados;
•
Sequencia dos conceitos em vez de construções de linguagem: é preferível,
sempre que existe conflito entre trabalhar construções de linguagem ou os
conceitos, trabalhar os conceitos e o mínimo possível das construções de
linguagem que auxiliem a implementar o conceito.
A metodologia está organizada em duas partes: 1) Fundamentos da Orientação a
Objetos e 2) Estruturas de aplicação. Na primeira parte são abordados os conceitos
básicos como classes, objetos, métodos, etc. Na segunda, conceitos importantes para o
desenvolvimento de aplicações e reuso como herança, polimorfismo e interfaces são
abordados.
O livro-texto da metodologia possui 13 capítulos, sendo os 7 primeiros reservados
para a primeira parte e os seis últimos para a segunda. O último capítulo é reservado para
um estudo de caso de uma aplicação de maior porte. Segue abaixo descrição dos
exemplos e conteúdos trabalhados em cada capítulo:
59 / 227
Capítulo
Exemplos de Projetos Desenvolvidos
Capítulo 1
Objetos e
Classes
• Desenhos simples de algumas formas
geométricas;
• Exemplo utilizando um objetos do projeto
anterior para desenhar uma figura;
• Exemplo simples com classes de alunos que
participam de aulas de laboratório.
Capítulo 2
Entendendo as
definições de
classe
• Simulação uma máquina de vender bilhetes
de trem;
• Armazenamento de informações sobre um
livro.
Capítulo 3
Interação entre
objetos
• Implementação de um mostrador de um
relógio digital com horas e minutos;
• Uma simulação simples de um correio
eletrônico.
•
•
•
•
•
•
Abstração;
Modularização;
Criação de objeto;
Diagramas de objeto;
chamadas de método;
depuradores.
Capítulo 4
Agrupando
objetos
• Implementação simples de um bloco de
anotações eletrônico;
• Um sistema de leilão;
• Um analisador de registros de acesso a uma
página web.
•
•
•
•
Iteradores;
Coleções;
Arrays;
Loops.
Capítulo 5
• Implementação de um programa de diálogo
Comportamento semelhante ao Eliza utilizado para fornecer um
mais sofisticado “suporte técnico” para clientes;
• Animação gráfica com bolas que quicam.
Capítulo 6
Objetos bemcomportados
• Estágios iniciais de um diário que armazena
compromissos;
• Implementação de uma calculadora de mesa;
Capítulo 7
Design de
Classes
• Um jogo iterativo de aventura baseado em
texto;
Principais Conceitos
abordados
•
•
•
•
Objetos;
Classes;
Métodos;
Parâmetros.
• Campos;
• Construtores;
• Parâmetros;
• Métodos de acesso e
modificadores;
• Atribuição e instrução
condicional.
• Utilizando classes de
biblioteca;
• Lendo a documentação;
• Escrevendo a
documentação.
• Testes;
• Depuração;
• Automação de testes.
• Design baseado na
responsabilidade;
• Acoplamento;
• Coesão;
• Refatoração.
Capítulo 8
Herança
• Um banco de dados de CDs e vídeos;
•
•
•
•
Capítulo 9
• Continuação do jogo iterativo do capítulo 7;
• Polimorfismo de método;
Herança;
Subtipagem;
Substituição;
Variáveis polimórficas.
60 / 227
Mais sobre
herança
• Continuação do banco de dados de CDs e
vídeos do capítulo 8;
Capítulo 10
Técnicas
adicionais de
abstração
Uma simulação de caçador-caça conhecida como
“raposa-coelho”.
Capítulo 11
Tratamento de
erros
• Implementação de um catálogo de endereços;
Capítulo 12
Design de
aplicações
• Sistema de reserva de lugares em um cinema;
Capítulo 13
Estudo de caso
• Combinação de um sistema de reserva de
táxis com um sistema de gerenciamento e de
simulação.
• tipo estático e dinâmico;
• Sobrescrição;
• Escolha dinâmica de
método.
• Classes abstratas;
• Interfaces.
• Programação defensiva;
• Lançamento e tratamento
de exceção;
• Informe de erro;
• Processamento de
arquivos simples.
•
•
•
•
Descobrindo classes;
Cartões CRC;
Padrões;
Design de interfaces.
• Desenvolvimento integral
de aplicação.
Tabela 6: Conteúdos e exemplos da metodologia de Barnes
4.1.2.1 Diretrizes
De forma complementar, para que obtenha uma boa compreensão da metodologia,
segue-se o trabalho de KÖLLING e ROSENBERG, que, a partir da experiência com o
desenvolvimento de diversos cursos utilizando o ambiente BlueJ elencaram oito diretrizes
adequadas para o ensino de programação orientada a objetos:
4.1.2.1.1 Objetos primeiro
É consenso entre muitos professores de Programação Orientada a Objetos que é
melhor ensinar a criar e manipular objetos antes de qualquer outra coisa. Esta atividade,
porém, é difícil nos ambientes tradicionais, pois para executar o método de um objeto é
preciso:
1. Uma classe contendo um método main estático com um array de Strings como
parâmetro;
2. Uso de uma variável tipada;
3. Uma atribuição de um objeto à uma variável;
61 / 227
4. A instanciação de um objeto;
5. A sintaxe de chamada de um método;
6. A visualização do resultado da chamada do método.
Com BlueJ a primeira atividade é abrir um projeto existente e criar objetos a partir
das classes, em seguida, os estudantes podem chamar métodos destes objetos e
visualizar seu estado. Tudo isso sem escrever nenhuma linha de código.
4.1.2.1.2 Não inicie com uma tela em branco.
Um dos maiores erros em programação OO é iniciar com uma tela vazia.
Escrever projetos OO envolvem a definição de quais classes o programa terá e
quais métodos cada classe deverá ter, e este, é um exercício extremamente difícil para
estudantes novatos.
Ao invés disso, pode-se iniciar com pequenas modificações e adições em código
existente.
4.1.2.1.3 Leia código
Muitos estudantes são forçados a começar a programar sem terem lido
praticamente nenhum código. Isso não acontece em nenhuma outra disciplina.
Estudantes aprendem mais quando tem acesso a códigos bem escritos que eles
possam utilizar como base para os seus projetos.
4.1.2.1.4 Use projetos grandes
Programas curtos dificilmente deixam claro as vantagens em se utilizar Orientação
a Objetos.
A sugestão é que sejam utilizados programas bem escritos com um número maior
de classes e métodos que permitam aos estudantes compreenderem as vantagens do
uso de OO, assimilarem a importância de um código limpo e comentado, pratiquem a
leitura de código e estudem a interação entre as classes.
4.1.2.1.5 Não inicie com o método main
O método main exige muitos conceitos para ser compreendido. O ideal é que os
62 / 227
estudantes só sejam apresentados a ele após terem se envolvido com os conceitos
principais como a criação de objetos e chamada de métodos.
4.1.2.1.6 Não use “Hello world”
Para se fazer um “Hello World” em Java é preciso iniciar do método main, que por
sua vez significa: 1) construir uma classe da qual nenhum objeto é criado. 2) construir um
método (o main) que não age sobre um objeto.
Isso não é Programação OO e fere outras diretrizes já apresentadas.
4.1.2.1.7 Mostre a estrutura do programa
Classes e seus relacionamentos são muito importantes. É essencial que os
estudantes possam visualizar a estrutura dos programas nos quais trabalham.
O BlueJ exibe a estrutura do programa em um diagrama semelhante ao diagrama
de classes da UML. Quando o BlueJ não estiver sendo utilizado é importante que o
professor encontre meios de mostrar claramente esta estrutura.
4.1.2.1.8 Tenha cuidado com a interface do usuário
É importante ensinar uma forma de realizar a interface com o usuário para
fornecimento de parâmetros e para a impressão de resultados do software.
Em Java, podemos fazer isso com Applets, com a API de entrada e saída ou com
frameworks GUI como o Swing.
Porém, nenhuma destas alternativas é simples o suficiente para ser utilizada em
cursos introdutórios. São sugeridos então, dois caminhos para lidar com este problema:
1. Específico no BlueJ, são as janelas pop-up que solicitam ao usuário os valores
para os parâmetros dos métodos e as janelas que exibem os retornos dos
métodos;
2. Um projeto maior com classes que encapsulem a interface com o usuário e que os
estudantes apenas precisem aprender a utilizar seus métodos.
4.1.2.2 Análise geral do método
Não é sem mérito que esta metodologia está sendo adotada por um grande número
de instrutores de programação orientada a objetos em todo o mundo. Sem dúvida que a
63 / 227
metodologia trouxe grandes contribuições e dentre os pontos fortes podemos destacar: 1)
a abordagem baseada em projetos que permite ao estudante aprender a resolver
problemas; 2) a priorização do conceito antes das estruturas de construção da linguagem,
dando sentido ao que o aluno está aprendendo; 3) O rico acervo de projetos trabalhados,
trazendo diversas dimensões importantes da computação; 4) O uso do Bluej que permite
que se inicie a tarefa de ensinar diretamente através de objetos e escrita de seus
métodos.
Além destes, na prática com a metodologia foi possível perceber que os estudantes
que em geral possuem mais dificuldade com programação se sentiam mais seguros e
confiantes ao verem os objetos na tela e poder manipulá-los. É visível que muitos alunos
não se sentem a vontade quando se deparam diariamente nas aulas de programação
com telas repletas de código-fonte, sem outras representações visuais do trabalho que ele
está realizando.
4.1.2.3 Pontos fracos
Apesar do inúmero sucesso, é importante ressaltar algumas dificuldades geradas
pela metodologia. Estas dificuldades foram percebidas em prática do autor com a mesma
e através da pesquisa de Xinogalos.
4.1.2.3.1 Ênfase nas técnicas de visualização e manipulação direta do BlueJ
Em função do BlueJ disponibilizar interface gráfica para instanciação de objetos e
chamada de métodos, alguns alunos ficam por demais “acomodados” a esta maneira de
trabalhar, o que gera dificuldades com instanciação de objetos e chamadas de métodos
direto do código-fonte.
Ilustração 14: Instanciação de objeto e chamada de
método em código
Isso porque no BlueJ, a diferença entre a forma de manter objetos em variáveis e
chamar métodos destas variáveis (Ilustração 14) é muito diferente da forma como a
mesma ação é feita no BlueJ (Ilustração 15).
64 / 227
Ilustração 15: Objetos na bancada de objetos (em
vermelho) e chamada de método de um objeto
Outra crítica é a que métodos que possuem retorno são chamados da mesma
forma que métodos sem retorno. Esta questão causa confusão ao tentar passar para os
estudantes que métodos com retorno devem ser sempre atribuídos a uma variável.
Métodos com retorno, no BlueJ, imprimem o valor retornado na tela. Quando,
posteriormente o autor trabalhou métodos com retorno sem o uso do BlueJ, uma das
dúvidas apresentas foi questionando se, quando se retornava um valor, este valor não
deveria ser impresso na tela?
4.1.2.3.2 Ênfase em projetos existentes
Em função da utilização de projetos com uma boa quantidade de código pronto, a
dificuldade em iniciar projetos do zero se mostrou muito maior. Além disso, métodos get e
set, bem como construtores, são geralmente fornecidos pelos projetos e os alunos
raramente os implementam.
4.1.2.3.3 Ensino posterior do método main:
O ensino apenas no final do curso do método main exige que os alunos utilizem
apenas o BlueJ para testar código, potencializando as dificuldades comentadas no item 1.
4.1.2.4 Conclusão
Percebe-se que o BlueJ apesar de suas inúmeras qualidades, não pode ser visto
como a única solução, pois, em concordância com Xinogalos, “mais de uma ferramenta é
necessário para suportar as diferentes necessidades cognitivas no ensino de
65 / 227
programação”, de modo que esta metodologia apesar de sua qualidade, pode ser
complementada
com
atividades
e
práticas
em
ambientes
profissionais
de
desenvolvimento.
4.1.3 Bruno Feijó et al
A metodologia apresentada por Feijó visa segundo ele próprio “apresentar os
conceitos e os bons hábitos da arte de programar”. Seu material aborda não apenas a
programação orientada a objetos mas também a programação estruturada e brevemente
a programação guiada a eventos.
Apesar do foco não ser orientação a objetos, sua metodologia e o framework que o
acompanha serviram de base e inspiração para a metodologia descrita no capítulo três e
consequentemente, base e inspiração para o presente trabalho.
O livro-texto da metodologia apresenta 9 capítulos que segundo sugestão da
metodologia poderia ser trabalhado em uma disciplina de 64 h/aula em 16 aulas de 4
h/aula cada, conforme modelo abaixo:
•
Semana 1: apresentação e capítulo 1;
•
Semana 2: Capítulo 2;
•
Semana 3: Capítulo 3;
•
Semana 4 a 6: Capítulo 4;
•
Semana 7: Capítulo 5;
•
Semana 8: Capítulo 6;
•
Semanas 9 a 11: Capítulo 7;
•
Semanas 12 a 14: Capítulo 8;
•
Semanas 15 e 16: Capítulo 9;
Segue abaixo organização dos capítulos, exemplos e conteúdos apresentados.
66 / 227
Capítulo
Exemplos de Projetos Desenvolvidos
Capítulo 1
Computadores
Nenhum exemplo trabalhado;
Capítulo 2
• Pequenos exemplos didáticos demonstrando
Variáveis, Tipos os conceitos;
de Dados e
Expressões
Capítulo 3
Controles de
Fluxo por
comandos de
seleção
• Pequenos exemplos didáticos demonstrando
os conceitos;
Capítulo 4
Métodos e
Soluções
• Pequenos exemplos didáticos demonstrando
os conceitos;
Capítulo 5
• Pequenos exemplos didáticos demonstrando
Dados
os conceitos;
compostos como
vetores
Capítulo 6
Usando mais
objetos e classes
simples
• Jogo similar ao tradicional Pong;
Principais Conceitos
abordados
•
•
•
•
•
Comentários;
Variáveis;
Entrada de Dados;
Saída de Dados;
Expressões;
• estruturas de tomada de
decisão if-else e switch.
•
•
•
•
Métodos;
Métodos Estáticos;
Sobrecarga de métodos;
Loops.
• Vetores unidimensionais;
• Vetores bidimensionais;
• Classes;
• Strings;
• Leitura e gravação de
arquivos;
• Classes abstratas e
interfaces.
Capítulo 7
• Continuação do jogo similar ao tradicional
Classes, objetos, Pong;
herança
•
•
•
•
•
Capítulo 8
Programação
Gráfica
• Conceitos de jogos 2D;
Capítulo 9
Programação
guiada a eventos
• Jogo específico desenvolvido para o livro e
continuação do jogo similar ao tradicional pong;
• Jogo específico desenvolvido para o livro.
Classes e objetos;
Modificador static;
Encapsulamento;
Herança;
Classes abstratas.
• Captura de dados do
teclado e do mouse.
Tabela 7: Conteúdos e exemplos da metodologia de Feijó
67 / 227
4.1.3.1 Análise geral do método
A proposta é muito abrangente, segundo Feijó, pretende-se do capítulo 1 ao 6
trabalhar com programação estruturada, no 7 e no 8 orientação a objetos e no capítulo 9,
programação guiada a eventos.
Em função até mesmo deste grande conjunto de paradigmas, o livro não oferece
um bom suporte para os conceitos de orientação a objetos, os exemplos são poucos,
muito limitados e as explicações dos conceitos não acompanham boas referências
visuais.
Em contrapartida, oferece um rico material sobre como unir conceitos de jogos em
duas dimensões com técnicas de programação, tanto estruturada quanto orientada a
objetos.
Um grande mérito está no uso do framework para trabalhar classes abstratas e
interfaces, pois, para que o aluno possa criar uma fase, deve implementar uma interface e
para criar um objeto no jogo, deve estender uma classe abstrata que já fornece os
atributos de posicionamento de um objeto na tela.
4.1.4 Stelios Xinogalos
Ao fim de 4 anos de avaliações e modificações, Xinogalos chegou a uma
metodologia que utiliza três ambientes de programação: objectKarel (Satratzemi ), BlueJ e
JCreator (um ambiente profissional de programação simplificado). O material didático
utilizado é baseado no material que acompanha o objectKarel e na metodologia de
Barnes com o BlueJ, descrita na seção 2.4.2.
O curso estruturado por Xinogalos possui 12 lições de 4 horas aula semanais, duas
teóricas e duas em laboratório. As aulas são divididas na seguinte estrutura:
68 / 227
Aula Temas trabalhados
Ambiente
1
Objetos, classes, herança: objeto, construção e inicialização de um
objeto, mensagens/métodos, atributos e comportamentos de um
objeto, herança, superclasse, subclasse, hierarquia de herança,
diagrama de classe UML
objectKarel
2
Herança em vários níveis, polimorfismo e sobrescrita.
objectKarel
3
Definição de Classe: campos, construtores, métodos de acesso,
métodos modificadores, estrutura de retorno, parâmetros, escopo de
variáveis, estruturas condicionais.
BlueJ
4
Interação com objeto: abstração, modularização, objetos criando
objetos, múltiplos construtores, diagrama de classe, diagrama de
objetos, tipos primitivos, tipos de objetos, chamadas de métodos
internos e externos.
BlueJ
5
Métodos estáticos: métodos de instância vs métodos de classe, o
método main, execução sem o BlueJ, byte code, Java Virtual
Machine.
BlueJ, JCreator
6, 7
Agrupando objetos em coleções: Coleções de tamanho flexível
(ArrayList), coleções de tamanho fixo (arrays), classes genéricas,
iteradores, loops (while, for, for-each).
BlueJ, JCreator
8
Usando bibliotecas de classe: Classes padrão do Java, leitura de
BlueJ, JCreator
documentação, interface vs implementação de uma classe, explorando
e usando classes (HashMap, Random, HashSet), modificadores de
acesso (public, private), informações escondidas, variáveis de classe
(estáticas).
9
Projeto de Classes: acoplamento, coesão, encapsulamento, duplicação BlueJ, JCreator
de código, projeto dirigido à responsabilidade, reuso de código.
10
Melhorando a estrutura com herança: hierarquia de classes,
superclasse, subclasse, construtor da superclasse, “subtyping”,
substituição, “autoboxing”.
BlueJ, JCreator
11
Polimorfismo, sobrescrita: tipos dinâmicos e estáticos, busca
dinâmica de método, super, acesso protegido.
BlueJ, JCreator
12
Classes abstratas e Interface.
BlueJ, JCreator
Tabela 8: Conteúdos e ambiente de programação na metodologia de Xinogalos
4.1.4.1 O Uso de ambientes de programação
A escolha do ambiente de programação que será utilizado é difícil e importante.
Ambientes profissionais são inadequados para trabalhar aspectos introdutórios,
ambientes de micro-mundos como o objectKarel são interessantes para trabalhar
conceitos mas não uma linguagem específica, já ambientes educacionais são
interessantes para transferir os conceitos para uma determinada linguagem, porém, sem
a transição para uma IDE profissional os estudantes ficam condicionados às
características específicas das ferramentas educacionais.
69 / 227
A dinâmica de 4 anos no curso apresentado mostrou que mais de uma ferramenta é
necessária para que os diversos aspectos cognitivos possam ser trabalhados. Esta
dinâmica gerou as seguintes diretrizes sobre o uso de ambientes de programação:
•
Use um ambiente de micro-mundo para uma introdução curta dos principais
aspectos de programação orientada a objetos: o ambiente escolhido deve
suportar o ensino dos principais conceitos de OO sem preocupações com a
sintaxe. O conceito de objeto deixa de ser abstrato pois agora os objetos podem
ser manipulados, os estudantes também ganham confiança na sua capacidade de
programação;
•
Use um ambiente educacional para apresentar os conceitos vistos no micromundo para a sua implementação em Java: a transição para um ambiente
educacional é mais suave do que para um ambiente profissional pois ambientes
específicos para o ensino eliminam a complexidade permitindo que os estuantes
possam se dedicar a sintaxe dos conceitos fundamentais. É essencial que estes
ambientes tenham ferramentas de visualização e manipulação direta de classes e
objetos e permitam a invocação dinâmica de métodos. O tempo com o um
ambiente educacional não deve se estender muito para evitar falsas percepções,
principalmente sobre os aspectos dinâmicos da Orientação a Objetos.
•
Use um ambiente profissional para prepará-los para o futuro: É inevitável que
esta transição aconteça, a maior preocupação deve ser quando realizá-la. Neste
curso foi decidido realizar esta transição na quinta lição dando ênfase para as
características destes ambientes que poderiam ajudar os estudantes como 1)
Visão das classes em árvore; 2) Navegação rápida dentro de uma classe; 3) autocompletar de código; 4) o destaque de sintaxe. Ao realizar esta transição os
estudantes se sentem mais confiantes com o seu conhecimento.
4.1.4.2 Diretrizes para o Ensino das lições propostas
As lições são baseadas como já mencionado no livro-texto que acompanha o
BlueJ., seguindo suas principais diretrizes.
Concomitantemente, é utilizada a abordagem “modelo primeiro” de Bennedsen e
Caspersen (2004) conforme documentada na seção 4.1.5.
Abaixo, seguem as diretrizes relacionadas a cada lição trabalhada. As lições
utilizam projetos do livro-texto que acompanha o BlueJ.
70 / 227
4.1.4.2.1 Lição 1: Objetos, classes e herança no objectKarel
Na primeira lição, são apresentados os conceitos básicos de classe, objeto e
método. Os estudantes iniciam criando um novo objeto da classe “Robo” com a ajuda da
interface Gráfica (Ilustração 16), depois, devem utilizar os métodos do robô (como
“mover”, “virar para a esquerda”, etc) para realizar tarefas específicas como completar um
determinado percurso.
Ilustração 16: Instanciação de um objeto no objectKarel com a ajuda da interface gráfica
O programa vai sendo construído a partir de botões onde o estudante seleciona os
métodos que irá executar, criando uma sequencia que no objectKarel é chamada de
tarefa (Ilustração 17).
71 / 227
Ilustração 17: Criação de uma tarefa a partir dos métodos de um
robô
Após, podem executar o programa e observar qual o comportamento do robô para
cada método e o que isso significa na linguagem dos robôs (por exemplo, virar para a
esquerda significa mudar a frente do robô em 90 graus negativos.), estas informações são
fornecidas na forma de texto no rodapé do ambiente (Ilustração 18).
Ilustração 18: Execução de um programa. à direita a visualização do robô, à esquerda a lista de
tarefas e abaixo a descrição do que ocorre no interior do método em execução.
Em uma segunda atividade, problemas mais complexos são apresentados de modo
que é necessário utilizar herança para a criação de uma nova classe com métodos que
irão facilitar a realização da tarefa.
Xinogalos ressalta que é essencial durante o processo explicar que cada método
muda o estado interno do objeto (mesmo que os alunos não possam ver as variáveis de
72 / 227
instância). Também é importante utilizar exemplos que utilizem vários objetos da mesma
classe para evitar que os estudantes considerem os dois conceitos como a mesma coisa.
4.1.4.2.2 Lição 2: Herança em vários níveis, polimorfismo e sobrescrita.
A didática se mantém a mesma e agora os problemas apresentados exigem a
construção de uma hierarquia de classes. Também são utilizados exemplos que
trabalhem a necessidade da sobrescrita de métodos como por exemplo, robôs mais
velozes que no método “move”, andam mais rápido que os robôs utilizados nos exercícios
anteriores. O polimorfismo, também é trabalhado com cuidado por se uma das principais
dificuldades observadas nos estudantes.
4.1.4.2.3 Lição 3: Definição de classe
A definição de uma classe é apresentada aos alunos utilizando o exemplo de uma
máquina de vender bilhetes (TicketMachine no livro texto que acompanha o BlueJ). Os
estudantes criam instâncias desta classe, chamam seus métodos, observam a
implementação em Java da classe e por fim, tem a oportunidade de realizar pequenas
modificações nela.
No primeiro ano do curso foram identificadas as dificuldades mais comuns
referentes ao ensino do paradigma de POO, é importante que o instrutor esteja atento a
elas desde o início do ensino para reforçar o entendimento destes tópicos. Segue abaixo
as principais dificuldades encontradas:
•
A compreensão e uso de múltiplos construtores;
•
O uso do this é de difícil compreensão e em geral os estudantes o evitam;
•
A inicialização dos campos no construtor;
•
Costumam declarar o tipo de retorno de métodos “set”;
•
Tentam acessar valores de campos privados diretamente, sem o uso de métodos
get;
Outras dificuldades são atribuídas mais especificamente ao uso dos recursos do
BlueJ, são elas:
•
Não declaração do tipo das variáveis que armazenam os objetos. Isso pode
ser trabalhado dando ênfase na janela de instanciação de um objeto à variável
73 / 227
onde o objeto será armazenado e o tipo desta variável. O BlueJ já apresenta estas
informações, porém, comumente passam despercebidas.
•
Chamada de métodos. Frequentemente métodos com retorno são chamados da
mesma maneira que métodos void. No BlueJ, é possível chamar ambos os tipos de
métodos da mesma forma, de modo qque o resultado de métodos com retorno
frequentemente é interpretado como “impressão do valor na tela”;
Por fim, é essencial verificar se os conceitos aprendidos no objectKarel foram
efetivamente transportados para o Java. Isso pode ser feito solicitando que os estudantes
representem em Java os modelos dos robôs criados nas últimas duas lições.
4.1.4.2.4 Lição 4: Interação entre objetos
Estudantes são apresentados aos conceitos de modularização, abstração e
interação entre objetos utilizando o exemplo de um relógio digital com duas classes, uma
representando um relógio digital e outra que representa um mostrador de dois números. O
Relógio é composto por dois mostradores, um para as horas e outro para os minutos.
As dificuldades observadas nesta etapa foram:
•
Os estudantes não tem certeza onde devem inicializar os campos;
•
Não sabem como manipular este novo tipo;
•
Tem dificuldades com a notação de ponto.
Para estas dificuldades é recomendado o uso de diagramas de objetos e atividades
onde os estudantes identifiquem chamadas de método internas e externas;
4.1.4.2.5 Liçao 5: O método main
nesta aula é apresentado como executar código Java sem o BlueJ. Uma introdução
sobre uso de métodos estáticos versus métodos de instância é feita utilizando o BlueJ.
Após, os estudantes criam seu próprio método main no Jcreator para um projeto
que eles já tenham conhecimento como o TicketMachine.
Esta lição também é aproveitada para falar sobre compilação, “byte code” e
máquina virtual.
As principais dificuldades encontradas foram:
74 / 227
•
Uso de parâmetros formais da chamado do construtor (Ex: new Classe(Type param); );
•
O tipo das variáveis dos objetos são esquecidos;
•
Esquecem argumentos em chamadas de métodos;
•
Esquecem os parênteses em chamadas de métodos sem argumentos;
Para lidar com estas questões é sugerido:
•
Atividades que são de alguma forma “silenciadas” pelo BlueJ como o tipo das
variáveis que armazenam os objetos são demonstrados utilizando as caixas de
diálogo do BlueJ e seu paralelo em sintaxe Java;
•
Exemplos e tarefas são realizados em cima de projetos já conhecidos;
•
Um programa contendo erros comuns é apresentado e os estudantes são
ensinados a reconhecer os erros e tratá-los.
4.1.4.2.6 Lição 6: Agrupando objetos em um ArrayList
Uso de coleções em programação é comum e necessário mesmo em programas de
baixa complexidade. Alguns autores já colocam o uso de ArrayList como prioridade sobre
Arrays por ser uma estrutura mais adequada para representar listas continuas.
Durante os quatro anos de curso os autores identificaram diversas dificuldades
envolvendo o uso de ArrayList`s e chegaram às seguintes conclusões:
1. O uso dos diagramas de objetos são fundamentais desde o início do projeto. Os
estudantes são estimulados a criar um diagrama de objetos para um dado
programa e simular operações de remoção e inclusão no diagrama de objetos.
2. São oferecidos exercícios para com código incompleto para que os estudantes
preencham os espaços vazios com determinados comandos.
3. Após, são construídos programas do zero.
4.1.4.2.7 Lição 7: Agrupando objetos em coleções (ArrayList vs Array)
O uso de Arrays é apresentado e o mesmo projeto no qual foi trabalhado o uso de
ArrayList é agora modificado para funcionar com Arrays.
75 / 227
4.1.4.2.8 Lição 8: Utilizando bibliotecas de classe
Nesta aula os estudantes são apresentados à documentação das classes Java,
com ênfase nas classes String e HashMap. A aula também apresenta a estrutura de
pacotes.
4.1.4.2.9 Lição 9: Projeto de Classes
O projeto de classes é algo difícil de ser realizado e a simples exposição dos
principais conceitos teóricos para uma solução bem projetada não causa um grande
impacto no aprendizado. É importante que os estudantes entendam através de uma
aplicação os problemas de um mau projeto de classes.
A maior dificuldade encontrada foi a limitação do tempo que impossibilita o
desenvolvimento de uma solução completa, na qual, o entendimento dos principais
conceitos de um bom projeto de classes seria trabalhado.
4.1.4.2.10 Lição 10: Melhorando a estrutura com Herança
O projeto desta lição é uma biblioteca multimídia de CD's e DVD`s. A primeira
versão do projeto não usa herança, de modo que muito código acaba sendo duplicado.
Quando os alunos são perguntados sobre como resolver o problema, eles se
recordam da apresentação feita com o objectKarel e facilmente compreendem o uso de
herança.
A maior dificuldade percebida é a chamada do construtor da superclasse através da
subclasse. Uma sugestão é utilizar o debugger para ver a execução do código passo a
passo e os campos sendo preenchidos.
4.1.4.2.11 Lição 11: Polimorfismo e Sobrescrita
Através de uma continuação do exemplo visto anteriormente, é realizado um
exemplo onde cada subclasse sobrescreve o comportamento de um método na classe
pai.
4.1.4.2.12 Lição 12: Classes abstratas e Interface
Nesta aula o uso de classes abstratas e interface são utilizados para expandir a
simulação de um ambiente com raposas e coelhos para conter diversos tipos de animais.
Percebeu-se que não é difícil para os estudantes compreenderem o conceito e o
76 / 227
implementarem, porém, demonstram grande dificuldade em perceber quando uma classe
deve ser declarada como concreta, abstrata ou interface.
4.1.4.3 Análise Geral do método
As duas principais conclusões de Xinogalos são 1) a necessidade de avaliação
continua dos cursos de modo a validar as pesquisas e dar continuidade aos processos de
melhoria e que 2) mais de uma ferramenta é necessário para suportar as diferentes
necessidades cognitivas no ensino de programação.
O artigo também clarifica como integrar alguns dos diferentes tipos de ambientes
de ensino de programação desenvolvidos até o momento de modo a garantir um ensino
eficaz ao mesmo tempo em que prepara os estudantes para o mercado.
É muito rica a descrição detalhada de todas as aulas realizadas e das principais
dificuldades em cada tema, de modo que o instrutor, sabendo de antemão as dificuldades
mais comuns, pode atacá-las logo no início das atividades.
A partir do material apresentado não foi possível identificar pontos fracos na
metodologia proposta por Xinogalos, na medida em que copia os pontos fortes da
metodologia de Barnes e adiciona ela o aspecto de modelagem e uso de ferramentas
profissionais de programação.
4.1.5 Michael Caspersen
Caspersen propõe um método baseado muito no fornecimento aos estudantes do
modelo conceitual, antes de iniciar a codificação, bem como em um processo sistemático
de transformação de um modelo para código-fonte.
Segundo Caspersem, modelagem conceitual é a definição de características de
orientação a objetos e provê uma perspectiva unificada e uma aproximação pedagógica
com foco sobre o aspecto de modelagem da orientação a objetos.
Esta visão contempla um dos papéis da linguagens de programação segundo
Knudsen & Madsen (1988, citado por Caspersen) que é justamente o uso da linguagem
de programação para expressar conceitos e fenômenos.
Para que seja possível a sistematização do processo de desenvolvimento, foram
identificadas técnicas para a criação sistemática de programas orientado a objetos em 4
diferentes níveis de abstração:
77 / 227
•
Domínio do Problema → modelagem conceitual: Criar um diagrama de classes
UML do domínio do problema, focando nas classes e nas relações entre as
classes;
•
Domínio do problema → modelagem dinâmica: Criar um diagrama de estados
UML que captura a dinâmica do comportamento;
•
Modelagem conceitual e modelagem dinâmica → modelagem da especificação:
Propriedades específicas e distribuição das responsabilidades entre as classes;
•
Modelagem da especificação → implementação:
◦ Implementação das estruturas entre as classes: cria um esqueleto para o
programa utilizando padrões de código para as diferentes relações entre as
classes;
◦ Implementação da estrutura interna das classes: Cria estruturas de classe
descrevendo os elementos internos que tem de ser estabelecidos antes e
depois de cada chamada de método;
◦ Implementação dos métodos: Uso padrões de algoritmo para os problemas
tradicionais de algoritmo por exemplo varredura e busca.
Ilustração 19: Criação sistemática de um programa orientado a objetos
A modelagem do software pode ser vista em diferentes níveis de detalhes
caracterizados por diferentes degraus de formalidade:
•
um um modelo conceitual informal descrevendo os conceitos chave do domínio do
problema e suas relações;
78 / 227
•
um modelo de classes mais detalhado dando uma visão mais detalhada da
solução;
•
e a implementação em uma linguagem orientada a objetos.
Este foco na perspectiva da modelagem conceitual, enfatiza que orientação a
objetos não é meramente um conjunto de soluções e tecnologias, mas uma forma de
entender, descrever e comunicar sobre o domínio de um problema e uma implementação
concreta deste domínio.
4.1.5.1 As etapas da metodologias
Na primeira metade do curso, de forma grosseira, o foco é paralelamente sobre o
entendimento e uso de um modelo conceitual como um “blue print” para programação
real. Na segunda metade do curso o foco primário é na qualidade interna do software.
Codificar e entender o modelo o conceitual são feitos de mãos dadas, de forma que
o modelo sempre vem primeiro, trazendo o código-fonte. A Introdução às diferentes
construções da linguagem são subordinadas às necessidades da implementação de um
dado conceito do modelo conceitual.
4.1.5.2 O Framework conceitual
São trabalhados com ênfase três modelos conceituais básicos: 1) associação, 2)
composição e 3) especialização. O ponto de partida é uma classe, propriedades desta
classe e o relacionamento entre a classe e os objetos criados a partir dela. Uma das
propriedades
de
uma
classe
pode
ser
uma
associação
com
outra
classe;
consequentemente o próximo tópico é associação. Isto é correlacionado com o fato que
uma associação (referência) é o tipo mais comum de estrutura entre classes (objetos).
Composição é um caso especial de associação, sendo trabalhado logo em seguida
A última estrutura a ser coberta é especialização. Especialização faz a ponte com a
segunda metade do curso onde o foco é a qualidade do projeto onde especialização é
frequentemente utilizada como um modo de obter projetos mais flexíveis.
4.1.5.3 O início
Os estudantes iniciam por aprenderem os conceitos básicos de classes e objetos
bem como noções básicas de modelagem através de um diagrama de classes
semelhante ao diagrama da UML. Depois de terem usado classes e objetos, nós nos
79 / 227
voltamos para uma visão interna e começamos a escrever classes; nós fazemos isso
introduzindo o primeiro padrão de código: Implementação de uma classe.
4.1.5.4 Padrões de Código
Um padrão de código é uma descrição geral da implementação de um elemento do
framework conceitual.
Através de um número progressivo de exemplos nós mostramos que uma
associação é uma propriedade de uma classe, uma classe tem mais que uma associação
e é uma relação dinâmica.
O ensino inicia com associações recursivas de cardinalidade 1. Para poder
implementar estas associações, os estudantes precisam aprender sobre referências e o
valor null, bem como a chamada de métodos entre diferentes objetos.
A partir de diversos exemplos (1) e dos conceitos trabalhados é construída uma
abstração (2) que corresponde ao modelo conceitual trabalhado. Para esta abstração, é
apresentado um padrão de codificação (3) que permite transformá-la em código fonte
funcional.
Este mesmo processo é utilizado para composição e especialização, dando
confiança e instrumentos para que os estudantes passem a identificar e implementar os
mesmos conceitos em seus projetos
4.1.5.5 Outros elementos da metodologia
Nós usamos BlueJ como ferramenta de programação.
O foco é em um modo sistemático de programar. Isto implica em três coisas 2)
alguns exemplos são exibidos para os estudantes; 2) uso explícito da UML e 3) um foco
80 / 227
no processo de programação.
Uma vez que nós percebemos a importância do foco no processo de programação
e não apenas no produto final, nós passamos a usar muita codificação ao vivo. O
propósito disto é mostrar aos estudantes como um profissional de programação ataca os
problemas.
4.1.5.6 Análise Geral da Metodologia
As duas grades contribuições de Caspersen são o processo sistemático de
desenvolvimento de software e o framework conceitual e suas respectivas abstrações. Em
contrapartida, não é possível avaliar outros aspectos da metodologia apenas com o
material consultado.
4.2 Diretrizes para o Ensino de OO
A partir dos trabalhos acima, foram identificadas e definidas 10 diretrizes base para
guiar o presente trabalho, são elas:
4.2.1 Princípios baseados na prática com o BlueJ
A metodologia deve seguir todos os princípios e diretrizes que servem como base
para a metodologia de Barnes que são:
•
Abordagem iterativa;
•
Abordagem baseada em projetos;
•
Sequencia dos conceitos em vez de construções de linguagem;
•
Sem cobertura completa da linguagem.
Além destes quatro princípios, são norteadoras também as 8 diretrizes
apresentadas por KÖLLING e ROSENBERG, documentadas na seção 4.1.2.1
4.3.2 Representações visuais para todas as estruturas e conceitos
trabalhados
Todos os exemplos desenvolvidos e apresentados aos estudantes devem vir
acompanhados de suas respectivas visualizações. Estas visualizações podem utilizar a
UML como base ou alguma das visualizações propostas nas metodologias previamente
81 / 227
estudadas, por terem estas metodologias se mostrado eficientes no trabalho dos
respectivos autores.
4.3.3 Operações de abstração e framework conceitual
Sempre que um novo conceito de relação entre dois ou mais objetos for
apresentado, deve ser acompanhado de sua respectiva operação de abstração segundo
Boratti e do modelo conceitual conforme Caspersen. Estas representações devem ser
utilizadas com frequência de modo que os estudantes aprendam a enxergá-las nos
problemas com facilidade.
4.3.4 Ambiente educacional + Ambiente profissional
Por volta da metade do curso, os estudantes devem ser guiados do ambiente
educacional BlueJ para um ambiente de desenvolvimento profissional de preferência do
instrutor. É necessário entretanto, que algum tempo seja dedicado exclusivamente ao
uso do novo ambiente, com exercícios e práticas que demonstrem as vantagens e
recursos do novo ambiente.
4.3.5 Processo sistemático de desenvolvimento
Desde as primeiras aulas os estudantes devem ser guiados sobre as etapas do
processo de desenvolvimento de software, através de métodos sistemáticos de
desenvolvimento e também “live coding”, que corresponde ao professor resolver
problemas e tarefas de codificação ao vivo diante dos estudantes (Caspersen).
4.3.6 A partir do zero.
Tão logo os estudantes adquiram confiança com um determinado conjunto de
recursos e conceitos, estes devem ser colocados em situações de resolução de
problemas a partir de uma tela vazia ou de um projeto em branco. Inclusive o processo de
buscar classes de bibliotecas utilizadas em outros projetos é importante para o
desenvolvimento profissional.
4.3.7 Recursos computacionais devem ter acesso fácil
Frequentemente a maior dificuldade para que se desenvolvam jogos ou outros
softwares mais complexos ainda em fases iniciais é devido a dificuldade com operações
computacionais básicas como exibir algo na tela ou obter uma entrada de dados do
usuário.
82 / 227
Deve ser fácil para os estudantes acessarem estes recursos utilizando o mínimo de
conhecimento acerca dos conceitos de orientação a objetos. É interessante que ao final
do curso seja demonstrado aos alunos como realizar as mesmas funções fornecidas pelo
framework de forma “crua”, diretamente na linguagem de programação apresentada.
4.3.8 Estilo de código-fonte
Estudantes geralmente não se preocupam com nomes de classes e variáveis, bem
como edentação. É importante que desde o início o estilo do código seja padronizado pois
conforme observações do autor, os próprios estudantes acabam por se perder em códigos
mal formatados, com variáveis e classes sem diferenciação de maiúsculas e minúsculas e
com nomes de variáveis que não façam sentido com o contexto trabalhado.
4.3.9 Modelagens genéricas
Cada módulo do curso deve permitir a criação de um novo artefato de software,
mais
complexo
que
o
módulo
anterior.
É
extremamente
importante
para
o
desenvolvimento das faculdades de modelagem que o próprio aluno possa escolher o
tema do seu interesse e construir por si próprio a modelagem e o respectivo código do
seu projeto.
Para que isso seja possível, devem ser trabalhados exemplos de modelagem e o
respectivo código, seguindo modelo proposto por Carpensen e documentado na seção
4.1.5.4, de situações geralmente genéricas para muitos jogos como efeito da gravidade,
movimentação de personagens, lançamento de artefatos como tiros ou poderes especiais
e interação entre objetos para verificações de colisão.
Estas modelagens genéricas permitem fácil adaptação pelo estudante para as suas
necessidades, permitindo que este aprenda com bons exemplos e tenha um maior
número de material para poder desenvolver sua própria modelagem.
4.3.10 Códigos e documentação na língua materna
O autor observou que a grande maioria dos estudantes não tinha familiaridade com
inglês e tinham muita dificuldade com nomes de classes e métodos nesta linguagem.
Também ficou claro logo no início dos trabalhos que não seria viável usar fontes de
consulta em língua estrangeira.
Deste modo, todos os códigos deste TCC, bem como o framework proposto devem
83 / 227
estar na língua materna do estudante. Como é de conhecimento geral a necessidade do
inglês para o desenvolvimento de software é importante que os alunos sejam informados
sobre isto e recebam gradualmente pequenos desafios como decifrar classes nativas do
Java (naturalmente em inglês) com sua respectiva documentação.
O autor observou também que alguns alunos naturalmente começam a escrever
seus códigos em inglês. Os que assim desejarem devem ser estimulados a continuar.
84 / 227
5 Framework Java para Jogos 2D
Esta seção apresenta o “framework Aljava”, desenvolvido especialmente para este
trabalho com a missão de permitir que iniciantes em programação desenvolvam jogos de
duas dimensões.
Na maior parte da metodologia apenas algumas classes e recursos do “framework”
serão utilizados, sendo que o conceito de “framework” efetivamente, como o código que
determina o ciclo de vida do software só será visto ao final da metodologia. Até lá,
portanto, o “framework” será usado pelos estudantes e apresentado como uma biblioteca
de código.
O nome “Aljava” corresponde a cesta que os arqueiros utilizam para armazenar
suas flechas. A ideia é que o “Aljava” contenha diversos recursos, cada qual como uma
flecha na mão do estudante. É também possível usar o nome fazendo uma correlação
com “All Java”, indicando um uso maior da linguagem Java, digamos, “ao todo”.
5.1 Aquisição do Conhecimento de Domínio
Para realizar o estudo do domínio, serão utilizados os oito jogos produzidos na
primeira versão da disciplina conforme apresentado anteriormente. Os temas dos jogos
foram escolhidos livremente e classes foram desenvolvidas pelo professor para auxiliar o
desenvolvimento.
A primeira versão da disciplina já utilizava um “framework” base, oriundo da
metodologia de Feijó, de modo que muito se aprendeu sobre o domínio e as
necessidades de jogos 2D a partir do desenvolvimento dos exemplos e das necessidades
dos estudantes.
5.2 Modelagem do Framework:
Para a definição do “framework” foi utilizado parcialmente o processo conforme
demonstrado por Silva (2000) e brevemente resumido na seção 2.3.2.
85 / 227
5.2.1 Generalização
As principais generalidades dos projetos pesquisados foram identificadas e
agrupadas nos seguintes pacotes lógicos:
•
Pacote Entrada:
◦ Uso de informações de teclas pressionadas do teclado;
◦ Uso de informações do mouse;
◦ Captação de informações do usuário como nome, números, etc.
•
Pacote Saída:
◦ Desenho de formas geométricas e imagens na tela;
◦ Criação de animações a partir de uma sequencia de imagens;
◦ Execução e pausa de sons;
•
Pacote Jogo:
◦ Criação de cenários;
◦ Colisão com o cenário;
◦ Colisão com outros objetos;
◦ Troca de fases;
5.2.2 Flexibilização
De forma geral, existem os seguintes pontos de flexibilização nos jogos
pesquisados.
•
Fases: Os jogos apresentaram telas onde jogadores realizam uma luta, saltam
sobre objetos, atiram uns nos outros baseado em turnos e outros. O conceito de
fase também vale para mapas de navegação em um cenário e menus de opções.
•
Objetos do Jogo: Objetos de um jogo são todos os elementos que exercem
influência direta sobre o jogo, como inimigos, o próprio jogador, obstáculos na tela,
86 / 227
itens para recuperação de vida, força ou energia, pontos de chegada, tiros, golpes
especiais, etc.
•
Cenários: Muitos cenários apresentavam necessidades especificas como exibir ou
esconder determinados blocos como por exemplo para liberar uma passagem
secreta, plataformas móveis e outros. Estes cenários devem possuir sistema de
colisão e gerenciamento de diversos objetos
5.2.3 Modelagem das Classes
A versão final do “framework” Aljava contém 25 classes organizadas em 6 pacotes.
Destas 25, 15 classes podem vir a serem manipuladas pelos estudantes no decorrer da
metodologia. Segue abaixo a descrição de cada pacote e de cada uma das classes
desenvolvidas.
5.2.3.1 Pacote aljava
Contém classes gerais que fazem a maior parte da interface com o usuário do
“Aljava”.
•
Aljava: É a principal classe do “framework” contendo referência para os objetos de
entrada e saída e realizando operações de desenho na tela. É fortemente acoplada
aos pacotes aljava.entrada, aljava.saida e aljava.util. Esta classe não é manipulada
diretamente pelos estudantes na metodologia apresentada, porém, não haveria
problema caso o professor decidisse utilizá-la.
•
Alj: Classe contendo atalhos sob a forma de métodos estáticos para todos os
métodos públicos da classe Aljava. O objetivo desta classe é funcionar da mesma
forma que o tradicional comando “System.out.println(String s)”. Os métodos da
classe “Alj” são organizados em classes internas com métodos estáticos. Um
exemplo clássico é o método responsável por exibir a tela “Alj.tela.exibe()”.
5.2.3.2 Pacote aljava.entrada
Contém classes que capturam eventos de entrada como mouse e teclado. Estas
classes não são manipuladas diretamente pelo usuário da biblioteca. Quem faz a interface
com estas classes é a classe “Aljava”.
•
MouseObserver: Classe que implementa as interfaces necessárias para poder
observar os eventos de mouse de uma janela;
87 / 227
•
Mouse: Faz a interface entre a classe Aljava e a classe MouseObserver;
•
TecladoObserver: Classe que implementa as interfaces necessárias para poder
observar os eventos de teclado de uma janela;
•
Teclado: Faz a interface entre a classe Aljava e a classe TecladoObserver.
5.2.3.3 Pacote aljava.saida
Contém classes relacionadas a saída de dados e visualização de informações. No
futuro do “framework” este pacote poderia ter classes para fazer saída para arquivos ou
outros dispositivos.
•
Tela: Classe que estende a classe Java “JFrame” do java e representa a janela do
jogo. Esta classe não são manipuladas diretamente pelo usuário da biblioteca.
Quem faz a interface com ela é a classe “Aljava”.
5.2.3.4 Pacote aljava.midia
Contém classes para trabalhar com arquivos de mídia como imagens e sons. Todas
as classes deste pacote podem (e frequentemente são altamente requisitas) ser utilizadas
pelos estudantes. Futuramente, podem pertencer a este pacote classes para trabalhar
com vídeos, “sprites” e outros formatos de áudio.
•
Imagem: Representa uma imagem do disco rígido. Pode ser usada com imagens
“png”, “jpeg” e “gif”. Contém métodos para desenhar, mudar as dimensões da
imagem e invertê-la;
•
Animação: Representa um conjunto de imagens que são exibidas como quadros
de uma animação em função de um tempo informado pelo usuário. Tem funções
semelhantes ao Design Pattern “Composite” em relação às imagens;
•
Gif: Extensão da classe Imagem para que um gif deixe de ser desenhado após um
certo tempo. Recurso geralmente necessário para animações com explosões.
•
Som: permite executar, pausar e reiniciar sons com o formato “Wav”.
5.2.3.5 Pacote aljava.jogo
Contém classes essenciais para a construção de jogos 2D envolvendo colisão e
cenários bem como as classes base utilizadas como parte da estrutura do framework:
88 / 227
•
Retangulo: Principal classe do pacote, é a base de todos os objetos do jogo,
contendo quatro variáveis (x, y, largura e altura), métodos modificadores e de
acesso para todas, métodos que verificam colisão com um ponto ou com outros
retângulos e métodos auxiliares para recuperar pontos específicos do Retângulo,
como as laterais. É a classe base para verificação de colisão com o cenário;
•
RetanguloGravidade: extensão do retângulo, com aplicação de gravidade e
método que permite “pulo”;
•
Cena: Desenha um cenário utilizando a técnica “TileMap” e contém métodos que
permitem a movimentação do cenário em relação a tela, isso significa que o
cenário pode ser maior que a área visível da janela e é relativamente simples
controlar a movimentação do cenário em relação a janela. Esta classe atende ao
ponto de flexibilização de cenários junto com a classe “CenaComColisao”,
explicada abaixo;
•
CenaComColisao: Estende a classe Cena e implementa a colisão de objetos da
classe “Retangulo” com os Tiles. É a classe mais complexa do jogo e ainda
apresenta diversas possibilidades de melhoria no seu algoritmo;
•
Tile: Classe que representa cada “tile” de uma cena. Um “tile” corresponde a um
dos pequenos retângulos que formam o cenário completo;
•
TipoTile: Classe usada para cada tipo de bloco dentro de uma Cena, por exemplo,
“tiles” que representam o chão possuem como tipo um objeto “TipoTile” que é
sólido e usa uma imagem semelhante a um chão;
•
Camera: Realiza a movimentação do cenário a partir de um objeto da classe
Retangulo e um objeto da classe Cena;
•
Motor: Classe que controla a execução do loop principal do jogo utilizando as
interfaces “Fase” para o gerenciamento de fases;
•
MotorSingleton: Classe que implementa o padrão “Singleton” para acesso a um
único objeto da classe Motor. Importante para o ensino de “Design Pattern”.
•
Fase: Interface representando uma fase de um jogo, atendendo ao ponto de
flexibilização de fases;
•
ObjetoJogo: Classe abstrata representando objetos do jogo, atendendo ao ponto
89 / 227
de flexibilização de objetos do jogo. É uma subclasse do “RetanguloGravidade”.
5.2.3.6 Pacote aljava.util
Contém classes auxiliares diversas.
•
ContadorTempo: Permite contar o tempo passado em milissegundos. É uma das
classes com maior potencial de uso do framework;
•
CarregadorMidia: Classe interna do framework, essencial para o carregamento de
imagens;
•
Direcao: Enum utilizado no pacote “jogo” para controle de colisões. Pode também
ser usada na demonstração de ENUM`s, porém, este conceito não foi incluído na
metodologia por questões de escopo.
5.3 Validação
Como o “framework” foi sendo desenvolvido durante a aplicação dos módulos junto
aos estudantes, conforme os exemplos dos módulos eram criados e os alunos
desenvolviam seus próprios recursos, o “framework” foi sendo validado.
Pôde ser verificado que a única classe que não atendeu completamente as
necessidades dos estudantes foi a classe “CenarioComColisao” que apresenta eventuais
“bugs” conforme o tamanho dos objetos e tiles utilizados. As dificuldades decorrem da
complexidade do algoritmo usado para a verificação de colisões de um Retângulo com
diversos outros Retângulos usados para compor o cenário. Uma opção seria trabalhar
com bibliotecas que utilizam sistema de colisão baseado em medidas métricas como a
biblioteca JBox2D. Porém, realizar a abstração desta biblioteca sem ter que ensinar novos
conceitos aos estudantes é bastante complexo e não pode ser feito para o presente
trabalho.
Apesar das limitações, a classe “CenaComColisao” funciona bem em jogos onde o
tamanho dos objetos é semelhante ao tamanho dos “Tiles” que compõe o cenário e os
movimentos dos objetos são realizados com intervalos moderados de até 5 “pixels” por
rodada. Dessa forma, a grande maioria dos jogos propostos pelos estudantes consegue
rodar com a classe conforme modelada atualmente.
Outro problema observado é que no BlueJ, eventualmente ocorre um erro ao tentar
exibir uma janela em função de erros de acesso ao contexto gráfico. Para evitá-los, basta
90 / 227
reiniciar a máquina virtual sempre antes de executar um novo código.
5.4 Documentação
Conforme visto na seção 2.3.3 e documentado na tabela 2, existem 3 tipos básicos
de documentação para “frameworks”: 1) uma voltada para quem decide se vai ou não
utilizar o “framework” e quais recursos ele oferecer; 2) uma segunda descrevendo como
utilizar o “framework” (conhecida como Livro de Receitas) e 3) uma terceira detalhando os
métodos e classes disponíveis .
Este trabalho, para atender aos três tipos de documentação, propõe dois formatos:
1) o primeiro corresponde a um livro de receitas contendo na introdução uma descrição
dos recursos disponíveis e 2) O “JavaDoc” do “framework”. Este “JavaDoc” é voltado para
os estudantes e contém apenas a documentação para as classes utilizadas pelos
estudantes.
5.4.1 Livro de Receitas
O Livro de receitas foi escrito na linguagem de marcação “Markdown”, hospedado
no serviço GitHub e disponibilizado online em formato de leitura agradável pelo “site”
“DocumentUp”.
Em função da extensão (1000 linhas e 35.653 caracteres) o arquivo não foi
anexado
ao
documento,
porém,
encontra-se
disponível
na
URL
http://documentup.com/kaleucaminha/aljava e acompanha, em formato HTML, o CD,
entregue em conjunto com o presente trabalho.
Segue abaixo trecho inicial da documentação com uma breve descrição do que é o
Aljava.
Ilustração 20: Texto de introdução ao Aljava
O Livro de receitas está organizado em 8 seções: 1) Uma introdução sobre
instalação, download, etc 2) Seção descrevendo todos os comandos da classe Alj; 3)
Seção com exemplos completos dos comandos da classe Alj. 4) Classes de Mídia; 5)
Classes representando elementos do jogo; 6) Classes do framework; 7) Classes Extras e
91 / 227
8) Conclusão . Veja abaixo alguns exemplos dos submenus de navegação na
documentação.
Ilustração 21: Submenu da
seção sobre os comandos da
classe Alj
Ilustração 22: Submenu
com alguns exemplos
integrando diferentes
comandos da classe Alj
Ilustração 23: Outros
submenus da documentação
Todas as classes públicas foram comentadas com descrições e exemplos de uso.
Veja abaixo o exemplo da documentação do comando usado para desenhar um
Retângulo.
Ilustração 24: Documentação de como desenhar um Retângulo
Sempre que necessário exemplos mais completos foram fornecidos como no caso
dos recursos do mouse para saber se um determinado botão foi pressionado.
92 / 227
Ilustração 25: Exemplo de uso dos recursos de acesso ao Mouse.
5.4.2 JavaDoc
O “JavaDoc” é o formato mais tradicional das documentações de bibliotecas e
“frameworks” em Java. Com um JavaDoc é possível ver cada um dos métodos e variáveis
de uma determinada classe bem como todas as classes de um pacote. Tudo organizado
em arquivos HTML.
Para este projeto foi necessária realizar alterações no gerador de “JavaDoc” do
Java para que as principais palavras-chave estivessem em português, conforme a diretriz
10 informada na seção “4.3” do presente documento. Este processo está documentado na
URL https://github.com/kaleucaminha/javadoc-ptbr com os respectivos códigos.
Ilustração 26: Exemplo de detalhe da tradução do gerador de JavaDoc.
Seguem abaixo algumas telas do JavaDoc gerado demonstrando os diferentes
níveis de detalhe desta forma de documentação.
93 / 227
Ilustração 27: Visualização de diversas
classes do mesmo pacote
Abaixo, visualização dos métodos da classe Som.
Ilustração 28: Métodos da classe som
E por fim, a visualização detalhada de um determinado método, no caso, o método
“configTile” da classe “Cena”.
Ilustração 29: Detalhamento do método "configTile"
94 / 227
Em função da extensão dos arquivos, não foi possível adicioná-los como anexo
nem colocá-los por completo no corpo deste trabalho. Para acessá-los, basta fazer
download do arquivo compactado com todo o JavaDoc na URL http://goo.gl/Xz8HT.
5.5 Código Fonte
Assim como com o “JavaDoc” gerado, em função da grande quantidade de
arquivos o código fonte do framework está disponível para download através da URL
http://goo.gl/cQ9Z9.
95 / 227
6 Metodologia de Ensino
A Metodologia proposta é baseada em projetos. Os estudantes são guiados para
níveis cada vez mais complexos de conceitos OO em módulos distintos, seguindo o
padrão pedagógico “Espiral”, produzindo ao final de cada módulo um produto adequado
ao nível de complexidade trabalhado.
Toda a metodologia deve seguir os 10 princípios relatados na seção 4.2 e utilizar os
recursos do framework Aljava, conforme proposto na seção 5.
Cada módulo apresenta uma carga horária recomendada seguindo experiência de
aplicação parcial da metodologia durante o primeiro e segundo semestre de 2012 na
instituição SENAI São José. Além da carga horária, cada módulo apresenta as seguintes
informações:
•
Conceitos de orientação a objetos (COO);
•
Conceitos programação (CP);
•
Conceitos do Framework Aljava (CFA);
•
Ambiente de desenvolvimento sugerido;
•
Um exemplo didático de um projeto, acompanhado do seu respectivo processo de
desenvolvimento, incluindo definição do problema, modelagem conceitual,
modelagem das classes e processo de “live coding” comentado;
•
Desafios que podem ser fornecidos aos estudantes;
•
Uma seção de resultados da metodologia contendo exemplos de trabalhos
desenvolvidos por alunos durante a aplicação da metodologia;
96 / 227
6.1 Introdução
A primeira etapa da metodologia deve oferecer para os estudantes uma visão geral
da estrutura do curso com a apresentação de cada módulo e uma introdução ao que
significa programar orientado a objetos. Nesta introdução deve ser dada ênfase em:
•
Um programa orientado a objetos corresponde a um conjunto de classes
interligadas;
•
Uma classe representa um modelo a partir do qual podem ser gerados diversos
objetos;
•
Um objeto é uma entidade que possui características variáveis e pode realizar
ações.
A aula pode ser ministrada tendo como base o capítulo 1 do livro “Programação
Orientada a Objetos com Java” (Barnes). Este capítulo oferece uma visão clara da
criação de objetos a partir de classes e da execução de métodos a partir de objetos.
O fato de um programa orientado a objetos corresponder a um conjunto de classes
conectadas pode ser demonstrado através de qualquer software de conhecimento dos
alunos.
Por
exemplo,
pode
ser
usado
o
jogo
Space
Invaders
(disponível
em
http://www.freespaceinvaders.org/) para demonstrar os três tópicos citados:
Ilustração 30: Tela do Jogo Space Invaders
97 / 227
Neste exemplo um professor poderia identificar algumas classes nesta tela como por
exemplo:
•
Inimigo: Classe representando os alienígenas que aparecem em branco;
•
Tiro: Classe representando os tiros que percorrem a tela;
•
Personagem: Classe representando o jogador que se movimenta e atira para
salvar a terra dos alienígenas;
•
Barreira: Classe para os blocos em verde que protege o personagem dos tiros;
•
SpaceInvaders: Classe que representa o jogo completo e interliga as demais.
Demonstrar o número de objetos que existem de cada uma das classes:
•
Inimigo: 55 objetos;
•
Tiro: No momento em que a imagem foi capturada, apenas um. Porém, durante um
jogo podem surgir muitos outros objetos desta classe;
•
Personagem: 1 objeto;
•
Barreira: 3 objetos;
•
SpaceInvaders: 1 objeto.
Por fim, para demonstrar que cada objeto tem características e ações, é preciso dizer que
a classe é responsável por projetar quais são essas características, e então, que cada
objeto poderá ter um valor diferente para estas características.
Por exemplo, a classe Inimigo poderia ter as características de posição, as imagens do
inimigo e um indicador dizendo se ele está morto ou não.
98 / 227
Ilustração 31:
Representação de uma
classe do jogo
SpaceInvaders
A representação visual das classes pode ser feita com um diagrama de classes
simplificado (sem tipagem e sem preocupação com modificadores de acesso) conforme a
ilustração 21 e dos objetos como a representação sugerida por Boratti.
Ilustração 32: Representação visual de dois objetos criados a partir da classe
Inimigo
Este processo pode ser repetido quantas vezes for necessário para que a turma
compreenda o conceito de classes e objetos.
Para verificar o aprendizado pode ser solicitado aos estudantes modelarem as
classes de algum outro jogo amplamente conhecido como “Mario” ou “Asteroides” e
modelarem objetos criados a partir destas classes.
99 / 227
6.2 Módulo 1 – Animações computadorizadas
O principal objetivo do primeiro módulo é a construção de classes, tanto conceitual
quanto na sintaxe da linguagem Java. São essenciais os conceitos de método e variável
de objeto, bem como a capacidade de identificar as características e métodos de uma
classe. É neste módulo também que o conceito de coesão é brevemente apresentado
para a compreensão de que os métodos de uma classe agem sobre as variáveis de
objeto.
A escolha por criar animações foi feita pois elas permitem pensar em um grande
número de problemas onde existem características com valores variáveis e a
possibilidade de criar diversos métodos que criam animações trabalhando sobre estas
variáveis. Um ótimo exemplo criado por um dos alunos foi uma classe “Sapo” que tinha
características como tamanho e posição de cada olho, cor do sapo, etc. E tinha métodos
como “olhar para esquerda”, “olhar para a direita”, “ficar vesgo”, etc.
Para permitir o desenho dos objetos será iniciado o uso do framework Aljava, mas
somente dos métodos necessários para o desenho de formas geométricas e manipulação
básica da janela.
Carga horária teórica 10 horas/aula
Carga horária prática 6 horas/aula
Produto Final
Uma classe representando um objeto com métodos que executam
animações
através
da
alteração
dos
valores
de
certas
características destes objetos.
COO
Classe; Métodos modificadores; Variáveis e Tipos; Variável de
objeto; Objetos / Instâncias; Parâmetros; Construtores; Abstração;
CP
Estruturas condicionais (if, else e else if); Estrutura de repetição
“while”; Instrução de atribuição (=, +=, -=, etc);
CFA
Desenho de formas geométricas; Exibição e limpeza da tela de
desenho;
CLJ
Arquivo Jar; Tipo String;
Ambiente de
Programação
BlueJ
100 / 227
6.2.1 Modelagem – Classe Carro
O exemplo base deste módulo consiste na modelagem de um carro que será
animado para andar pra frente.
O início deste módulo é focado em trabalhar o conceito de abstração como uma
forma de extrair dos objetos do mundo real as características e ações adequados ao
objetivo do software. Portanto, ao modelar uma classe é necessário conhecer qual o
objetivo desta classe. Por exemplo, um carro para o site de uma concessionária é
diferente da classe de um carro para um jogo de corrida.
Isto pode ser demonstrado criando junto dos estudantes modelos no quadro de
classes “Carro” com diferentes objetivos.
Ilustração 33: Exemplo de Classes "Carro" com diferentes objetivos
Após a compreensão do processo de abstração, deve-se passar para os métodos
que essa classe pode ter, levando em conta, assim como nas características, qual o
objetivo do software para o qual a classe está sendo modelada.
Assim como na introdução, pode-se modelar alguns objetos de cada uma das
diversas classes “Carro” identificando o processo de abstração “Classificação /
Instanciação” conforme descrito por Boratti e apresentado aqui na seção 4.2.1.2.1.
Com a modelagem pronta, podem ser passados exercícios para os alunos
modelarem outras classes e objetos a partir delas.
6.2.2 Tipos Básicos
Para ser possível modelar uma classe em Java é preciso demonstrar que cada
variável de objeto (característica) deve possuir um tipo. Neste momento são abordados
101 / 227
quatro tipos primitivos básicos (int, double, boolean e char) e o tipo String.
Para tornar mais claro para os alunos esta questão é importante oferecer uma
breve visão de como o computador entende as informações e de como os tipos mais
comuns foram sendo criados. Isto pode ser feito com a seguinte sequencia de conceitos:
1. Qualquer variável em um programa de computador deve ter um valor que pode ser
compreendido computacionalmente. Por exemplo, como que o motor de um carro
poderia ser compreendido por um computador?
2. Os computadores funcionam com base em eletrônica, portanto, o tipo básico de
qualquer valor em um computador pode ser representado como ligado/desligado,
um/zero, verdadeiro/falso;
3. A partir disso, criou-se o tipo boolean que só pode armazenar dois valores, ou
verdadeiro (ligado, 1) ou falso (desligado, 0). Este tipo pode ser usado em variáveis
como o mecanismo de “pausar” um jogo, um indicador se o inimigo está vivo ou
morto, se o carro tem ar condicionado ou não, etc.
4. A partir dos valores binários foi criado um sistema numérico capaz de representar
qualquer número apenas utilizando valores 0 e 1 lado a lado. Por exemplo, o valor
0 corresponde ao próprio 0, o 1 corresponde ao valor 1, 00 corresponde ao valor 2,
01 ao 3, 11 ao 4, 000 ao 5 e assim sucessivamente.
5. Com este sistema foi possível aos computadores compreenderem números, no
Java, um tipo corresponde a um número inteiro é o int. Podem ser variáveis deste
tipo a velocidade de um carro, a posição na tela em pixels, o número de
competidores em uma pista de corrida, etc.
6. A partir da codificação de binário para inteiro, também foi possível representar
números reais (com casa decimal). Em Java este tipo corresponde ao double. São
exemplos de valores deste tipo o preço de um ítem em um comércio eletrônico, o
valor da gravidade ou o resultado de uma fórmula de alta precisão numérica.
7.
Com os números mapeados foram criadas formas de mapear cada letra de um
alfabeto para um número inteiro correspondente, assim, os computadores
passaram também a compreender caracteres. Um caracter em Java corresponde
ao tipo char. Pode-se usar este tipo para armazenar identificadores em forma de
letras, como por exemplo, o sexo de uma pessoa (m ou f) ou a alternativa de
102 / 227
resposta a um questionário (a, b, c, d, e, etc).
8. A partir do char foi possível criar sequencias de caracteres, que podem ser usadas
para representar palavras e frases. Este tipo em Java é o String.
9. A partir do conjunto de diversas variáveis diferentes é possível modelar Classes
que representam objetos mais complexos do mundo real.
10. Em orientação a objetos são estes os meios que podemos utilizar para que o
computador compreenda nossas abstrações. Para completar, um exemplo de algo
complexo como o motor citado no ítem 1, seria:
Ilustração 34: Exemplo de uma classe
motor com as características e os
respectivos tipos
6.2.3 Live Coding – Classe Carro
Para este processo deve ser utilizado o BlueJ. A ideia é que, com o modelo anterior
e o conhecimento sobre tipos, os alunos possam ver como construir na linguagem Java
cada um dos conceitos apresentados. Deste modo, eles já sabem parcialmente o que
precisa ser feito, só lhes falta aprender como.
Segue abaixo o processo de criação de uma classe Carro para a construção das
animações com a respectiva explicação dada aos alunos.
103 / 227
class Carro {
}
O primeiro passo é dizer para o Java que
estamos criando uma classe. fazemos isso
com a palavra-chave “class” seguida do nome
da classe.
O principal é perceber que tudo que diz
respeito a classe deve estar dentro das
chaves. O que estiver fora delas não será
reconhecido.
class Carro {
int posicaoX;
int posicaoY;
double quantGasolina;
boolean estaLigado;
}
Iniciamos colocando 4 variáveis de objeto, as
duas primeiras para poder posicionar nossos
carros na tela. Uma para saber como está o
combustível e outra para informar se o carro
está ligado ou não.
Repare que ao final de cada variável foi
colocado “;”. Em Java, é assim que dizemos
que uma instrução terminal.
class Carro {
int posicaoX;
int posicaoY;
double quantGasolina;
boolean estaLigado;
char tipoVeiculo;
String cor;
}
Agora foram adicionadas mais duas variáveis,
uma representando o tipo do veículo. O
objetivo é mostrar aos alunos que um char
pode ser usado para diversos fins desde que
seja previamente definido.
Por exemplo, o char tipoVeiculo irá armazenar
o valor “e” se o carro for esportivo, “c” se for
clássico ou “m” se for moderno. A variável
modelo deve armazenar a montadora do
veículo.
class Carro {
...
char tipoVeiculo;
String cor;
Agora iniciamos a construção do esqueleto dos
métodos da nossa classe carro.
O significado da palavra void antes do nome
void andaFrente(){
de cada método só poderá ser explicado
}
posteriormente, sendo neste momento dita
104 / 227
void andaTras(){
como necessária para a construção de um
}
método em Java.
}
Além disso os alunos devem ser orientados a
olhar
com
atenção
os
parênteses,
cuja
utilidade será explicada em breve e as chaves.
Todo o código correspondente ao método
deverá ficar dentro das chaves.
...
void andaFrente(){
posicaoX = posicaoX + 1;
}
void andaTras(){
posicaoX = posicaoX - 1;
}
void desliga(){
estaLigado = false;
}
...
O corpo dos métodos irá conter a lógica
necessária
para
a
ação
correspondente.
Iremos ao longo do curso ver diversas formas
de implementar métodos.
Uma das características mais presentes em
métodos é que eles alteram o valor das
variáveis do objeto.
Por exemplo, andar para frente em um jogo
pode ser o mesmo que movimentar a posição
do carro ao longo do eixo x da tela.
Neste momento o instrutor deve aproveitar
para explicar o operador de atribuição e o
uso de operações aritméticas como soma e
subtração.
Os alunos devem ser direcionados também
para reparar no uso do “;” ao final de cada
instrução.
...
char tipoVeiculo;
String marca;
Carro(){
posicaoX = 20;
posicaoY = 20;
quantGasolina = 40.00;
estaLigado = false;
tipoVeiculo = 'e';
cor = “vermelho”;
}
Além das variáveis de objeto e dos métodos
existe uma estrutura essencial para as classe
chamada Construtor.
Essa estrutura tem a função de inicializar os
valores das variáveis de objeto de modo que
quando um objeto for criado, ele já terá valores
105 / 227
void andaFrente(){
válidos para as suas diversas variáveis.
posicaoX = posicaoX + 1;
}
Cada tipo de variável tem uma forma de ser
...
inicializada. Neste momento o professor deve
explicar a sintaxe de cada uma delas
Tabela 9: "Live Coding" para a classe Carro
Com a classe base construída o BlueJ pode ser usado para construir objetos desta
classe e ver o valor das variáveis após a execução de cada método. Neste processo o
professor pode ir criando diversos métodos com os estudantes para alterar os valores das
variáveis de cada objeto, inclusive aumentando e mudando as variáveis apresentadas
nesta classe carro.
106 / 227
Ilustração 35: Exemplo de Classe Carro
Ilustração 36: Exemplos de objetos da classe
Carro ao lado após execução de alguns dos
métodos.
6.2.3 Live Coding – Desenhando
Neste momento, os estudantes geralmente compreendem a ideia de orientação a
objetos mas tem baixa motivação pois tudo o que veem são valores sendo alterados e
nada que se pareça realmente com um software.
Aqui entra a primeira função do Aljava que é permitir que os estudantes desenhem
os objetos da classe Carro conforme os valores informados.
107 / 227
Para esta tarefa o Aljava fornece métodos para desenho de formas geométricas e
uso de cores. Os métodos devem ser apresentados somente no contexto de construção
do desenho. Somente após os primeiros processos é que eles devem ter acesso a
documentação como apresentada na seção 5.
Como estaremos usando código externo ao Java puro os alunos devem ser
informados que:
•
Para realizar desenhos em Java puro seriam necessários muitos conceitos que só
serão vistos posteriormente no curso;
•
Portanto, foram desenvolvidos diversos códigos em Java que permitem a
realização de tarefas como desenho de forma fácil para iniciantes;
•
Esse conjunto de códigos corresponde a uma biblioteca chamada Aljava;
•
Em Java, bibliotecas de código são armazenadas em um arquivo com a extensão
“.jar”;
•
Sempre que se iniciar um novo projeto que use esta biblioteca o arquivo “.jar”
deverá ser adicionado;
•
Por fim, vale ressaltar que em qualquer software profissional o uso de bibliotecas
externas é absolutamente comum, de modo que faz parte do processo de
aprendizado usar bibliotecas externas.
Segue abaixo processo de “Live coding” do desenho dos carros.
108 / 227
class Carro {
...
void desenha() {
}
...
Uma das ações de um carro é poder desenhar a si
mesmo. O desenho é uma ação e portanto, deve ser
escrito
como
um
método.
}
Para os desenhos usaremos comandos específicos do Aljava. Tudo no Aljava está ligado
a uma tela de desenho. Portanto, existem métodos para desenhar nessa tela.
Um exemplo desse método serve para o desenho de um retângulo.
Todos os métodos de desenho são acessados com “Alj.desenha.comando()”.
O termo “comando” deve ser usado para os métodos estáticos acessados da classe Alj
para que os alunos não os confundam com os métodos que estamos trabalhando
(apesar de terem a mesma lógica) e não sejam ainda introduzidos ao conceito de
contexto estático.
void desenha() {
Alj.desenha.retangulo( 50, 50, 80, 40);
}
Alj.desenha.retangulo(
posicaoX,
posicaoY,
larguraDoRetangulo,
alturaDORetangulo
);
Grande parte dos comandos Aljava podem receber
parâmetros.
Parâmetros
são
valores
que
informamos
para que o comando possa ser
executado.
Por exemplo, para desenhar um retângulo é
essencial saber a largura e altura do retângulo, bem
como qual a posição em que ele será exibido na
tela.
Aqui também deve ser explicado aos estudantes o
modelo
cartesiano
de
desenho
utilizando
coordenadas x e y.
A ordem dos parâmetros é sempre definida por
quem escreveu o código do comando e os
parâmetros
devem
semrpe
ficar
dentro
dos
parênteses e serem separados com vírgula.
No Aljava também existem comandos para mudança de cores, sempre que uma cor é
109 / 227
alterada, todas as formas geométricas após ela são desenhadas com esta cor.
No exemplo abaixo, é desenhando um retângulo para o chassi do carro, na cor laranja e
as rodas na cor preta.
Ao final de um desenho, para que ele efetivamente apareça, deve ser usado o comando
específico “Alj.tela.exibe();”
void desenha(){
Alj.cor.nome("laranja");
Alj.desenha.retangulo(50, 50, 80, 40);
Alj.cor.nome("preto");
Alj.desenha.oval(60, 40, 20, 20);
Alj.desenha.oval(60, 80, 20, 20);
Alj.desenha.oval(100, 40, 20, 20);
Alj.desenha.oval(100, 80, 20, 20);
Alj.tela.exibe();
}
import aljava.*;
class Carro {
Para que o código funcione é preciso
realizar a importação do código do aljava
para esta classe específica.
...
Isso pode ser feito usando o comando
}
“import “acima da declaração da classe.
Tabela 10: "Live Coding"- Desenhando um carro
Geralmente o carro desenhado não chama muita atenção e os alunos podem ser
desafiados a fazerem algo melhor. Aqui deve ser apresentada a documentação de todos
os métodos de desenho, de mudança de cores e de uso de transparência.
Bem, mas como as variáveis de objeto se relacionam com o desenho do carro? O
próximo processo de “live coding” tem como foco demonstrar o uso das variáveis e como
o uso dos demais métodos definidos pelos estudantes afetam o desenho.
Agora nosso objetivo é fazer com que o desenho apareça mais a frente toda fez
que executarmos o método “andaFrente()”. Deve-se notar que a principal ação do método
“andarFrente()” é aumentar o valor da variável “posicaoX”.
110 / 227
Para conseguirmos o efeito do carro andando para frente é essencial que ao
desenharmos os retângulos, círculos de mais formas, o valor da variável “posicaoX” seja
levado em conta.
Fazemos isso inicialmente substituindo o valor “50” colocado manualmente no
desenho do retângulo pela variável.
Alj.desenha.retangulo( posicaoX , 50, 80, 40);
Ao fazer a mudança nota-se que as rodas não acompanharam o retângulo. O
processo deve aproveitar a oportunidade para explicar que as todas devem sempre ser
desenhadas relativamente ao carro. Por exemplo, a roda esquerda traseira sempre será
desenhada próxima ao valor X inicial, já a roda esquerda da frente terá um valor da
posição X maior do que o X original, porém, este valor é sempre fixo.
Ao realizar a mudança, será percebido que um desenho sobrescreve o outro, por
isso, sempre, antes de desenhar, a Tela deverá ser limpa com o comando
“Alj.tela.limpa()”. O resultado do método neste momento será:
void desenha(){
Alj.tela.limpa();
Alj.cor.nome("laranja");
Alj.desenha.retangulo(posicaoX, 50, 80, 40);
Alj.cor.nome("preto");
Alj.desenha.oval(posicaoX + 10, 40, 20, 20);
Alj.desenha.oval(posicaoX + 10, 80, 20, 20);
Alj.desenha.oval(posicaoX + 50, 40, 20, 20);
Alj.desenha.oval(posicaoX + 50, 80, 20, 20);
Alj.tela.exibe();
}
Deve ser pedido aos alunos executarem agora o método “andaFrente()” e em
seguida o método “desenha()” diversas vezes seguidas. Neste momento eles devem
compreender que:
•
Os métodos podem mudar os valores das variáveis;
•
Outros métodos podem usar os valores destas variáveis para fazer coisas como
desenhar.
111 / 227
•
A execução consecutiva destes métodos realizar uma impressão de movimento.
Alguns desafios que podem ser passados aos alunos agora são:
1) criar um
método “andaTras()”; 2) criar um método “andaDireita()” que muda o valor de uma nova
variável “posicaoY” ; 3) Usar a variável “cor” para a cor do carro; 4) Sugerir que os
estudantes criem suas próprias variáveis e formas de utilizá-la.
Também é interessante após os alunos realizarem o desafio usar uma variável
ângulo usada para rotacionar o carrinho antes de desenhá-lo. Um exemplo da classe
Carro completa após diversas interações e desafios com os alunos pode ser demonstrado
no Anexo I.
Como pode ser visto neste exemplo, é possível chegar rapidamente a uma classe
relativamente complexa. Os alunos nesse momento demonstram compreender os
conceitos mas ainda tem dificuldades com a sintaxe.
Aqui pode-se pedir que cada estudante desenvolva sua própria classe seguindo a
mesma ideia do carro. Pode ser um animal, um outro veículo, enfim, qualquer objeto que
eles julguem interessante para animar em um exercício posterior.
6.4.4 Live Coding – Animações
Chegamos ao objetivo do módulo. Ao terem feito o exercício com os métodos
“andaFrente()” e “desenha()” é possível demonstrar que uma animação de um carro em
movimento para frente seria algo como:
andaFrente();
desenha();
andaFrente();
desenha();
andaFrente();
desenha();
Fazemos isso criando um novo método “animacaoCarroAndando()” contendo o
código acima. Ao executar o código o resultado da animação não é visto pois o
processamento do computador é muito rápido. Deve então, ser usado o método
“Alj.util.espera(200);”
para
realizar
uma
pausa
de
alguns
milissegundos
no
processamento, e assim, o desenho pode ser observado. Com isso, o código final fica:
112 / 227
void animacaoCarroAndando(){
desenha();
Alj.util.espera(200);
andaFrente();
desenha();
Alj.util.espera(200);
andaFrente();
desenha();
Alj.util.espera(200);
andaFrente();
desenha();
Alj.util.espera(200);
}
Para fazer melhor, introduzimos o uso da estrutura de repetição “while”:
void animacaoCarroAndando(){
while( posicaoX < 200) {
andaFrente();
desenha();
Alj.util.espera(200);
}
}
Aqui deve ser explicado que todo o código dentro das chaves será executado
repetidas vezes, até que a “expressão booleana”, entre parênteses, seja falsa.
O conceito de “expressão booleana” e os quatro operadores básicos (maior, menor,
igual e diferente) devem ser explicados aqui.
A partir deste ponto diversos desafios podem ser propostos, indicando para os
alunos, como sugerido por Caspersen, um modelo genérico para a programação de
animações:
113 / 227
void metodoDaAnimacao(){
while( expressaoBooleana ) {
metodoQueAlteraValorDeVariavel() ;
metodoQueDesenha() ;
Alj.util.espera( tempoPausa );
}
}
Para aumentar o potencial das animações deve-se iniciar o uso de variáveis locais,
com um contador para contar os quadros da animação.
void animacaoCarroAndando(){
int contadorQuadros = 0;
while( contadorQuadros < 10) {
andaFrente();
desenha();
Alj.util.espera(200);
contadorQuadros = contadorQuadros + 1;
}
}
Com isso, encerra-se o conteúdo principal para execução de animações. Na
experiência do autor não são necessários mais exemplos. Os estudantes em geral tem
muita criatividade e conseguem encontrar diversos exemplos de animações utilizando o
mesmo estilo do apresentado.
A maior dificuldade fica por conta da sintaxe e do uso de operadores que tenham
sido apenas indicados mas que não constam no exemplo. Isso pode ser facilmente
resolvido com acompanhamento durante as atividades de desafio.
6.2.5 Live Coding – Parâmetros e estruturas condicionais
O objetivo desta seção é oferecer um número maior de recursos para os projetos
dos estudantes. Este “live coding” mostra primeiro como usar estruturas condicionais para
114 / 227
realizar coisas diferentes no sistema e posteriormente como passar informações de fora
para dentro da classe através dos parâmetros.
Bem no início da modelagem da classe Carro foi modelado um atributo do tipo
“char” que identificava o tipo do veículo. Este atributo poderia ter três valores diferente. A
ideia é que cada tipo de carro escolhido tenha um desenho específico:
•
'e' representa um carro esportivo, deve ser desenhado com um formato diferente,
que lembre um carro de corrida;
•
'c' representa um carro clássico, deve ser desenhado com retângulo;
•
'm' representa um carro moderno, deve ser desenhado com um formado
arredondado.
Aqui deve-se explicar para os estudantes que dependendo do valor de uma certa
variável o programa deve fazer ações diferentes. A principal estrutura condicional em
programação é conhecida como “if / else” e pode ser exemplificada com o código de
desenho abaixo:
if(tipoVeiculo == 'c') {
Alj.desenha.retangulo(posicaoX, posicaoY, 80, 40);
} else if (tipoVeiculo == 'm') {
Alj.desenha.oval(posicaoX, posicaoY, 80, 40);
} else {
Alj.desenha.retangulo(posicaoX + 15, posicaoY, 10, 40);
Alj.desenha.retangulo(posicaoX + 20, posicaoY+12, 65, 16);
Alj.desenha.retangulo(posicaoX + 55, posicaoY, 10, 40);
}
E para completar a demonstração clara do uso da estrutura:
115 / 227
if( expressaoBooleana ) {
codigo();
} else {
codigo();
}
//ou, quando existirem mais possibilidades
if( expressaoBooleana ) {
codigo();
} else if( e xpressaoBooleana ) {
codigo();
} eles {
codigo();
}
O exemplo funciona, mas para testar carros de diferentes tipos só mudando a
inicialização da variável no construtor. Deve ficar claro para a turma que o problema disso
é que obrigatoriamente todos os objetos da classe carro terão o mesmo valor para a
variável “tipoVeiculo”.
Deve ser mostrado agora que o valor do tipo do veiculo deve ser informado na hora
que um novo objeto da classe Carro for construído e que este valor deverá vir de fora, de
quem criar o objeto e para que valores de fora possam ser transmitidos para dentro de
uma classe são utilizados os parâmetros.
Qualquer método, inclusive o construtor, que é um método especial, podem receber
parâmetros. E é para isso que são utilizados os parênteses ao lado do nome dos
métodos.
Vamos iniciar a demonstração de como usar parâmetros pelo construtor. O objetivo
é que no momento em que formos criar um objeto da classe Carro seja obrigatório
informar qual o tipo do veículo.
Para iniciar, ressalta-se que todo parâmetro é uma variável é que toda variável em
java precisa obrigatoriamente ter um tipo. Portanto, a variável que usaremos para receber
um valor informado por quem criar a classe será do tipo “char” (o mesmo da variável
tipoVeiculo) e terá o nome “parametroTipoVeiculo”. Veja abaixo como é a sintaxe para
declarar um parâmetro obrigatório no método construtor.
116 / 227
Carro(char parametroTipoVeiculo){
//Código do construtor
}
A variável que estamos usando para armazenar o parâmetro enviado é uma
variável que só existirá durante a execução do construtor. Diferente das variáveis de
objeto que existem durante todo o tempo de vida de um objeto e podem ser acessadas de
qualquer método executado pelo objeto.
Precisamos agora usar esta variável, passando o seu valor, que conterá o valor
informado na criação do objeto, para a variável de objeto, que o manterá enquanto o
objeto existir.
int posicaoY;
int angulo;
String cor;
double quantGasolina;
boolean estaLigado;
char tipoVeiculo;
Carro(char parametroTipoVeiculo){
posicaoX = 20;
posicaoY = 50;
angulo = 0;
quantGasolina = 40.00;
estaLigado = false;
tipoVeiculo = parametroTipoVeiculo;
cor = "vermelho";
}
O BlueJ, sempre que executa um método que precisa de parâmetros exibe uma
janela solicitando que o estudante preencha o valor dos parâmetros solicitados. Esta
janela deve ser mostrada com cuidado pelo instrutor para que os estudantes leiam o que
ela apresenta para que posteriormente associem o que vem nesta janela com a execução
do método via código. Foi observado que sempre que os estudantes são apresentados a
janelas que solicitam dados ou realizam ações, muitas vezes eles tentam utilizar sem ler
as instruções ou informações apresentadas.
117 / 227
Ilustração 37: Exemplo de criação de objetos usando parâmetros pelo construtor
Outro exemplo é o método “andaFrente()”. Da forma como foi construído ele só
anda 10 pixels por execução, não sendo possível informar quanto o carro deve andar.
Uma forma de resolver este problema é usando um parâmetro no método “andaFrente()”,
do tipo inteiro, que informa quanto o carro deve andar. Isso pode ser feito facilmente da
seguinte forma:
void andaFrente(){
void andaFrente(int distancia){
posicaoX = posicaoX + 10;
posicaoX = posicaoX + distancia;
angulo = 0;
angulo = 0;
//se andou, perde gasolina
//se andou, perde gasolina
quantGasolina -= 0.1;
quantGasolina -= 0.1;
}
}
Método sem parâmetro.
Mesmo método com parâmetro.
Tabela 11: Demonstração comparativa para uso de parâmetros
Neste momento porém, ocorrerá um erro no método “animacaoCarroAndando()”,
pois dentro do método existe uma chamada para o método “andaFrente()”. Só que agora,
colocamos um parâmetro no método e todo parâmetro deve obrigatoriamente ser
informado quando o método é executado. A forma que temos para resolver isso é informar
manualmente o valor que queremos para que o carro ande. Para este exemplo, usarei o
valor 1, de modo que a animação ficará mais realista.
118 / 227
void animacaoCarroAndando(){
int contadorQuadros = 0;
while( contadorQuadros < 10) {
andaFrente(1);
desenha();
Alj.util.espera(200);
contadorQuadros = contadorQuadros + 1;
}
}
E aproveitando que estamos trabalhando no método “andaFrente()” podemos ver
mais um exemplo de uso de estruturas condicionais. Por exemplo, se o carro estiver sem
combustível, ele não pode andar para frente. Modificaremos este método para que se o
método for executado e não houver combustível, uma mensagem será exibida ao usuário.
void andaFrente(int distancia){
if(quantGasolina <= 0){
Alj.tela.exibeMensagem("Carro sem combustível. Abasteça");
return;
}
posicaoX = posicaoX + distancia;
angulo = 0;
...
Repare que dentro do bloco de código do “if”, após exibir a mensagem, foi usada a
instrução “return;”. Esta instrução finaliza a execução do método retornando a execução
para quem o executou.
Nosso único problema agora é que não conseguimos testar esta alteração porque o
valor inicial do combustível está em 40 litros. Podemos fazer com que o usuário informe,
na hora que está criando a classe, qual a quantidade de combustível do carro. Com isso,
podemos informar um valor baixo e testar o método “andaFrente()” até acabar o
combustível do veículo.
119 / 227
Carro(char parametroTipoVeiculo, double parametroGasolina){
posicaoX = 20;
posicaoY = 50;
angulo = 0;
quantGasolina = parametroGasolina;
estaLigado = false;
tipoVeiculo = parametroTipoVeiculo;
cor = "vermelho";
}
Agora que os estudantes já conhecem parâmetros e a estrutura condicional “if”,
eles podem ser desafiados a criar um método abastece que adiciona uma certa
quantidade de gasolina no tanque e adicionar verificações para que o carro não saia para
fora da tela em hipótese nenhuma.
6.4.6 Resultados
Este módulo foi trabalhado de forma similar a apresentada aqui na metodologia no
segundo semestre de 2012 para uma turma de Introdução a Orientação a Objetos. Nesta
primeira aplicação do método haviam as seguintes diferenças:
•
Comandos Aljava: Os comandos de desenho do Aljava eram fornecidos através
de um objeto da classe Aljava. Deste modo, os estudantes precisavam dentro do
código ter uma variável de instância para um objeto da classe Aljava, ter a
instanciação do objeto usando a palavra-chave “new” e execução de métodos
desse objeto. Foi verificado que esta estrutura era extremamente complexa para o
início e tão logo foi possível foi alterado para o uso de comandos (métodos
estáticos);
•
Parâmetros e Condicionais: O uso de parâmetros e estruturas condicionais eram
feitos antes de ensinar como fazer uma animação propriamente dita. Porém, o
conteúdo “parâmetros” se mostrou o mais complicado e muitos estudantes não
conseguiram fazer as animações usando parâmetros. Passando este conteúdo
para o final, o objetivo é poder ter uma tarefa adicional que é efetivamente
adicionar parâmetros para as animações depois de já as terem feito.
Conforme observado as principais dificuldades foram:
•
Parâmetros no construtor: Compreender o uso de parâmetros no construtor e
120 / 227
necessidade de declarar uma variável para receber o valor e então passar o valor
para a variável de objeto. Ficou evidente a necessidade de se frisar o escopo das
variáveis e que os parâmetros também são variáveis;
•
Rotaciona do Aljava: O método para rotacionar objetos do Aljava é de difícil
compreensão e somente alguns alunos conseguem de fato usá-lo;
•
Sintaxe Java: Mesmo com os diversos exemplos, a sintaxe de construção de
métodos, principalmente o uso dos parênteses e das chaves causa bastante
confusão. Foi percebido também que muitos estudantes eventualmente colocavam
algum código fora de um método e não conseguiam perceber o erro;
•
Menor cuidado com o nome das variáveis: Em diversos momentos durante as
explicações, perdeu-se o cuidado com o nome de certas variáveis. Isso se refletiu
no resultado dos alunos conforme será observado na análise dos resultados.
O trabalho foi feito em dupla em uma sala de 24 alunos de modo que resultou em
12 classes. Das 12, 8 tiveram um bom desempenho. Segue abaixo mais detalhes sobre 4
destas classes:
6.4.6.1 Classe Sapo
A Classe Sapo se destacou pela criatividade, pelo bom número de métodos e pelo
uso correto dos parâmetros.
Ilustração 38: Exemplo Classe Sapo desenvolvida por um aluno
121 / 227
Apesar do bom desempenho visual é importante ressaltar alguns pontos no código
da classe que poderiam ter sido melhor trabalhados. O primeiro é o nome dado às
variáveis de objeto, ilegíveis até que se compreenda todo o código.
Ilustração 39:
Variáveis na classe
Sapo
O método que desenha o sapo ficou com 130 linhas. A classe poderia ter ficado
muito mais clara se tivesse sido passada a ideia de dividir um método grande em outros
menores, facilitando o entendimento e modificação do código.
6.4.6.2 Classe BatmanLogo
Esta classe demonstra um talento fenomenal do estudante na criação do desenho
usando apenas o sistema de rotação e as formas geométricas básicas.
Ilustração 40: Classe BatmanLogo
122 / 227
Apesar da grande qualidade e do bom uso de parâmetros e dos demais conceitos,
este estudante se dedicou muito mais ao desenho do que para a Orientação a Objetos.
Este sem dúvida é um risco que se corre ao adotar a metodologia. Foi percebido porém,
que desde que não seja frequente, o ganho motivacional do estudante quando é permitido
que ele gaste tempo em funções como o desenho é muito alto. E é esta dedicação que
trará desafios de programação tanto para o professor quanto para os estudantes.
Um exemplo sobre esta questão é que assim que havia finalizado os métodos para
exibir e apagar a logo do Batman, o problema levantado pelo estudante foi sobre como
usar o mouse para ligar e desligar a luz. Isso foi passado ao estudante que já pode
implementar um recurso avançado antes mesmo deste ter sido explicado para a turma,
demonstrando que a facilidade de uso do Aljava permite também compreender diferentes
velocidades de aprendizado.
6.4.6.3 Classe Onibus
Esta classe demonstrou um uso perfeitamente adequado dos padrões de
codificação apresentados. Tendo aplicado as mesmas ideias em diferentes métodos, com
bastante precisão.
Ilustração 41: Classe Onibus
O código desta classe demonstra também um outro problema muito comum. a
edentação. Em muitos pontos o código fica desorganizado e foi frequente os estudantes
se confundindo com os seus códigos por causa de má formatação de código.
123 / 227
Ilustração 42: Exemplo de má formatação de
código na classe Onibus
6.4.6.4 Classe Carro
Esta classe apesar de possuir o mesmo nome da classe trabalhada no exemplo foi
desenvolvida de modo totalmente diferente pelo estudante. O principal destaque é a
demonstração clara de como o método de animação ensina corretamente o uso das
variáveis de objeto. Nos 6 métodos que possuem estrutura de repetição da classe foram
usadas corretamente variáveis de objeto para movimentar partes específicas do desenho
e fazer degradê de cores.
Ilustração 43: Exemplo Classe Carro
6.3 Módulo 2 – Mini Game
O objetivo deste módulo é demonstrar como utilizar os conteúdos aprendidos no
módulo 1 para efetivamente construir um jogo. Além dos recursos já vistos anteriormente,
serão trabalhados o conceito de matrizes com a respectiva construção em “arrays”,
métodos de acesso (com retorno) e interação com o mouse.
Carga horária teórica 10 horas/aula
Carga horária prática 6 horas/aula
Produto Final
Uma classe representando um pequeno jogo com interação com
o mouse.
124 / 227
COO
Fortalecimento dos recursos anteriores. Uso de métodos com
retorno do framework Aljava.
CP
Estrutura de repetição “for”; expressão booleana com mais de
uma condição. Matrizes.
CFA
Acesso ao mouse.
CLJ
Arrays.
Ambiente de
Programação
BlueJ.
O jogo escolhido para demonstração é o Jogo da Velha. E, seguindo o princípio de
sempre modelar antes de codificar, deve ser lançada a seguinte pergunta aos estudantes
“como modelar um jogo da velha de modo que o computador o compreenda?”.
Esta etapa é particularmente difícil e pode ser iniciada por dados simples como o
nome dos jogadores e um contador de vitórias. Caso nenhum aluno se manifeste sobre o
tabuleiro do jogo da velha, o professor deve iniciar desenhando o tabuleiro no quadro é
questionando sobre o que é variável no tabuleiro.
Normalmente se percebe que existem 9 casas e que cada uma destas casas pode
apresentar três situações distintas: 1) estar livre; 2) estar ocupada pelo jogador 1 ou estar
ocupada pelo jogador 2. A próxima pergunta é “como representar cada casa usando
variáveis de objeto?”. Na experiência do autor o tipo preferido pelos estudantes é o “char”
neste caso. Sem dúvida é uma escolha interessante, porém, vale incentivá-los a usar
inteiros para que se inicie a percepção de que o programador pode dar significado
também aos números, usando-os para além de operações matemáticas. Deste modo,
pode-se construir uma modelagem conforme demonstrada abaixo, com nove casas do
tipo inteiro.
class JogoDaVelha {
String nomeJogador1;
String nomeJogador2;
int casa1;
int casa2;
int casa3;
int casa4;
...
}
125 / 227
Em breve iremos transformar estas nove casinhas em um “array”, só que antes de
demonstrar isso aos estudantes é importante que eles comecem a ver qual a vantagem
de usar esta estrutura ao invés de variáveis separadas. Para isso, iremos usar a seguinte
estratégia: o tabuleiro a ser desenhado deve usar a cor preta para casas livres, azul para
casas ocupadas pelo jogador 1 e vermelho para as casas ocupadas pelo jogador 2.
Para conseguir desenhar as nove casas, os estudantes são obrigados a repetir a
mesma estrutura condicional nove vezes. Para demonstrar será criado um construtor que
inicializa os valores das nove casas com dados aleatórios e os nomes dos dois jogadores.
O método de desenho do cenário já desenha também os nomes dos jogadores.
JogoDaVelha(){
Alj.inicializa(302, 352);
nomeJogador1 = "Kaléu";
nomeJogador2 = "Olavo";
casa1 = 0;
casa2 = 1;
casa3 = 1;
casa4 = 0;
casa5 = 0;
casa6 = 2;
casa7 = 0;
casa8 = 0;
casa9 = 2;
}
void desenha(){
Alj.desenha.texto(20, 25, "Jogador 1: "+nomeJogador1);
Alj.desenha.texto(170, 25, "Jogador 2: "+nomeJogador2);
Alj.desenha.linha(0, 48, 302, 48);
desenhaCasinhas();
Alj.tela.exibe();
}
void desenhaCasinhas(){ }
Repare que somente na preparação para o jogo da velha, devem ser
apresentados dois novos conceitos: 1) o primeiro é a concatenação de Strings no
126 / 227
desenho do nome do jogador e 2) o segundo é o uso de um método interno
“desenhaCasinhas” ao invés de colocar todo o código dentro de um único método. Isto
deve ser orientado como uma boa prática para manter o código organizado e de fácil
compreensão.
Agora, segue exemplo de código para desenho das casinhas, repetido somente
para as duas primeiras, mas que deve, pelo professor e pelos alunos, ser repetido até a
nona casa.
//Desenha casinha 1
if(casa1 == 2){
Alj.cor.nome("vermelho");
} else if(casa1 == 1) {
Alj.cor.nome("azul");
} else {
Alj.cor.nome("preto");
}
Alj.desenha.retangulo(0, 50, 100, 100);
//Desenha casinha 2
if(casa2 == 2){
Alj.cor.nome("vermelho");
} else if(casa2 == 1) {
Alj.cor.nome("azul");
} else {
Alj.cor.nome("preto");
}
Alj.desenha.retangulo(101, 50, 100, 100);
O código completo é de quase 100 linhas e além disso, os estudantes devem ser
levados a ver que, caso eles decidam mudar o desenho das casinhas para acrescentar
uma determinada imagem, terão que fazer a alteração em todas as nove casas.
Neste
momento
deve-se
apresentar
a
matriz
como
uma
estrutura
de
armazenamento de dados que pode ser percorrida computacionalmente. Ou seja, ao
invés de nove casas em variáveis separadas, colocaremos as nove casas em uma matriz
que será percorrida para realizar o desenho das nove casas. A estrutura de matriz pode
ser representada da forma como sugerida por Boratti. Auxilia muito a compreensão dos
127 / 227
estudantes se eles puderem aqui ser apresentados ao fato de que quando declaramos
uma variável, um espaço no memória do Java é reservado. Assim, quando declararmos
nossa matriz, iremos reservar um certo número de espaços na memória, todos ligados a
uma só variável. A representação visual disso, em contraste com o modelo anterior seria:
Ilustração 44: Representação visual do uso de matriz
A seguir, transformamos as variáveis em uma matriz e inicializamos os valores da
matriz demonstrando: 1) a sintaxe de declaração de “arrays”; 2) a sintaxe de inicialização
de arrays; 3) o acesso a cada posição do array. Ajuda deixar claro que uma matriz nada
mais é do que um conjunto de variáveis organizadas de modo que cada uma corresponda
a uma determinada posição.
int casas[];
JogoDaVelha(){
...
casas = new int[9];
casas[0] = 0
casas[1] = 1;
casas[2] = 1;
...
casas[7] = 0;
casas[8] = 2;
}
128 / 227
A compreensão dos estudantes fica mais clara quando o professor demonstra a
execução do código descrito aqui construindo a representação visual da matriz a
correspondente a cada linha, durante esse processo deve ser explicado que em
computação, a primeira posição de um “array” é o 0 ao invés do 1, dando destaque claro
para o fato de o número “9” na inicialização da matriz corresponder ao número total de
casas na matriz, mas que a última casa sempre estará na posição igual ao número de
casas menos um, nesse caso, oito.
Até aqui ainda não tivemos nenhum ganho real com o uso de “arrays”. Fazemos
isso agora no método “desenhaCasinhas” através da estrutura de repetição “for”. Sobre
esta estrutura deve ficar claro que:
•
Esta estrutura é adequada para repetições que envolvam números, e que devam
ser executadas um número fixo de vezes, diferente da estrutura “while” que deve
ser usada quando a condição de saída da estrutura não é previamente conhecida.
•
Na declaração do “for”, existem três partes: 1) a declaração de uma variável de
controle; 2) a condição para que o “loop” seja executado e 3) Uma instrução que
altera o valor da variável de controle para que o “loop” avançe.
É útil que em paralelo ao uso do for para o desenho das casinhas, o professor
apresente também exemplos como “executar um código com um número de 1 até 100” e
“Somente os números pares do 1000 ao 100”.
Para o desenho das casinhas, iniciamos simplesmente colocando um “loop” for que
irá executar um certo código nove vezes, com a variável de controle indo de 0 até oito, ou
seja, uma vez para cada posição da matriz. Segue processo que pode ser usado com os
estudantes:
129 / 227
void desenhaCasinhas(){
for(int i = 0; i <= 8; i = i + 1 ){
if(casa1 == 2){
Alj.cor.nome("vermelho");
} else if(casa1 == 1) {
Alj.cor.nome("azul");
} else {
Na primeira etapa o foco é
explicar as três partes do “for” e
como elas são necessárias para
que o código entre as chaves
seja executado o número exato
de vezes.
Alj.cor.nome("preto");
}
Alj.desenha.retangulo(0, 50, 100, 100);
}
}
for(int i = 0; i <= 8; i = i + 1 ){
if(casas[i] == 2){
Alj.cor.nome("vermelho");
} else if(casas[i] == 1) {
Alj.cor.nome("azul");
} else {
Alj.cor.nome("preto");
}
Neste passo existe uma certa
demora na compreensão de
que
é
possível
usar
uma
variável no lugar onde antes
havia um número.
Para melhor percepção disto
vale que o professor se aproprie
Alj.desenha.retangulo(0, 50, 100, 100);
}
do tradicional “teste de mesa” e
demonstre ele mesmo o que
está acontecendo na execução
do código (em geral na quarta
rodada
do
“loop”
eles
já
compreenderam).
int linha = i / 3;
Apesar de ter sido diminuído o
int coluna = i % 3;
número de linhas do código,
int posX = coluna * 101;
será
necessário
adicionar
a
int posY = (linha * 101) + 50;
complexidade de saber em qual
Alj.desenha.retangulo(posX, posY, 100, 100);
posição X e Y o retângulo
deverá ser desenhado, tendo
como variável apenas a posição
da casa no array.
Nesta
tarefa
é
necessário
130 / 227
apresentar o operador módulo
(resto da divisão) e demonstrar
como o conhecimento básico de
matemática é importante na
resolução
de
problemas
computacionais.
Também vale ressaltar neste
exemplo o uso das variáveis
locais
para
auxiliar
o
desenvolvimento de uma tarefa.
Tabela 12: "Live Coding" para desenho das casas do Jogo da Velha
Aqui temos um jogo da velha, que, apesar de desenhado, não funciona. Para
avançar, primeiro fazemos a modelagem do jogo junto aos estudantes tendando identificar
quais métodos podem ser úteis ao jogo da velha. Nesta seção, apresenta-se que todo
jogo possui um “loop” principal que tem como função: 1) Pegar informações dos
dispositivos de entrada; 2) Processar e 3) Desenhar.
Com este conhecimento podemos modelar nossa classe JogoDaVelha com os
seguintes métodos:
Ilustração 45:
Métodos classe
JogoDaVelha
Segue abaixo processo de “live coding” usado para finalizar o jogo.
131 / 227
void loop(){
while(true){
Alj.tela.limpa();
processaMouse();
desenha();
Iniciamos pelo método “loop”. Todo jogo
tem um “loop” central que só termina
quando o jogo termina.
O
“loop”
métodos
deve
que
chamar
compõe
jogo
na
sequencia
verificaEmpate();
método verifica vitória deve estar antes
}
por
o
demais
verificaVitoria();
}
correta,
os
exemplo,
o
do verifica empate para que alguém
possa ter chance de ganhar na última
rodada.
void processaMouse(){
if( Alj.mouse.clickE() ){
int xMouse = Alj.mouse.x();
int yMouse = Alj.mouse.y();
int coluna = xMouse / 101;
O método que faz o processamento do
mouse possui 4 partes, A primeira,
correspondente às três primeiras linhas
simplesmente verifica se o mouse está
sendo
pressionado
e
em
seguida
int linha = (yMouse - 50) / 101; armazena em variáveis locais o valor da
posição X e Y do mouse. Aqui é o
int pos = (linha * 3) + coluna;
if(casas[pos] != 0){
primeiro caso em que um método está
presente
onde
deveria
booleana.
Isto
existir
deve
uma
//A casa já está ocupada.
expressão
ser
return;
ressaltado e informado aos alunos que
os três métodos usados para pegar a
}
posição
if(vezJogador1){
casas[pos] = 1;
vezJogador1 = false;
} else {
casas[pos] = 2;
vezJogador1 = true;
}
do
mouse
tem
uma
característica em comum. Todos tem
retorno. O “clickE()” retorna verdadeiro
ou falso e os métodos “x()” e “y()”
retornam um valor inteiro.
Na segunda parte os valores X e Y são
transformados na posição da matriz
}
}
correspondente à casa. A operação é a
inversa da que foi feita no “loop for” que
desenhou as casas.
Na terceira parte, verifica-se se a casa já
132 / 227
está ocupada e em caso positivo, para a
execução do método.
Na última parte, a casinha é marcada
para o jogador correspondente à sua
vez. Para controlar de qual jogador é a
vez, foi usada uma variável booleana
como variável de objeto.
void verificaVitoria(){
//verifica linha horizontal 1...
if(casas[0] == 1 && casas[1] == 1 && casas[2] == 1){
//jogador 1 venceu
}
if(casas[0] == 2 && casas[1] == 2 && casas[2] == 2){
//jogador 2 venceu
}
}
O método verifica vitória precisa verificar 8 combinações de três casas preenchidas para
cada jogador. Ou seja, são dezesseis verificações de vencedor.
Construir todas essas verificações manualmente, além de ser cansativo, aumenta a
probabilidade de erro pois é difícil verificar se todas as combinações foram informadas
corretamente em função da sobrecarga de elementos de sintaxe na instrução
condicional.
Uma das formas de lidar com este problema é construindo um método que verifica a
vitória dos dois jogadores para três determinadas casas que podem ser passadas por
parâmetro. Se tivermos esse método, o código do “verificaVitoria” ficaria mais simples.
void verificaVitoria(){
//Horizontais
verificaVitoria3Casas(0, 1, 2);
verificaVitoria3Casas(3, 4, 5);
verificaVitoria3Casas(6, 7, 8);
É fácil perceber que o código aqui
ficou muito mais limpo. Agora o novo
método que foi criado só precisa de duas
estruturas condicionais, uma para cada
Atenção especial deve ser dada para: 1)
//Verticais
uso do operador “&&” na expressão
verificaVitoria3Casas(0, 3, 6);
booleana e 2) uso das variáveis para
verificaVitoria3Casas(1, 4, 7);
acessar
um
valor
no
“array”
e
a
133 / 227
verificaVitoria3Casas(2, 5, 8);
//Diagonais
consecutiva comparação desse valor
com “1” ou “2”.
verificaVitoria3Casas(0, 4, 8);
verificaVitoria3Casas(2, 4, 6);
}
void verificaVitoria3Casas(int c1, int c2, int c3){
if(casas[c1] == 1 && casas[c2] == 1 && casas[c3] == 1){
Alj.tela.exibeMensagem("Jogador "+nomeJogador1+" venceu.");
reinicia();
}
if(casas[c1] == 2 && casas[c2] == 2 && casas[c3] == 2){
Alj.tela.exibeMensagem("Jogador "+nomeJogador2+" venceu.");
reinicia();
}
}
void reinicia(){
for(int i = 0; i <= 8; i++){
casas[i] = 0;
}
}
O método “reinicia” altera o valor das
casas para “livre”, permitindo que o jogo
continue.
Pode-se
aproveitar
para
explicar o uso de “i++” no lugar de “i = i +
1;”;
void verificaEmpate(){
for(int i = 0; i <= 8; i++){
if( casas[i] == 0){
return;
}
}
Por fim, para verificar se ocorreu empate
da maneira mais correta teríamos que
ver
se
não
existe
mais
nenhuma
possibilidade de vitória. Isto é complexo
e para este jogo será adotado um
mecanismo mais simples. Se todas as 9
Alj.tela.exibeMensagem("Empate."); casas
reinicia();
}
jogador
estiverem
1
ou
considerado
“verificaVitoria”
ocupadas
pelo
empate.
foi
ou
jogador
pelo
2,
Como
é
o
executado
anteriormente, não existe risco de um
cenário em que todas as casas estão
ocupadas e existe um vencedor. Nestas
condições, sempre que as nove casas
chegarem neste método como ocupadas,
134 / 227
haverá empate.
Ao invés de usar um “if” muito extenso,
abordou-se a técnica de detectar se
alguma casa está livre, em caso positivo,
não há empate. Se nenhuma livre for
encontrada, então, empatou e o jogo
deve ser reiniciado.
Tabela 13: "Live Coding" para finalização do jogo da velha
E assim finaliza-se o primeiro jogo desenvolvido com a metodologia. O foco aqui
foi ganhar maior autonomia e demonstrar como resolver problemas complexos utilizando
muitos recursos semelhantes aos vistos no primeiro capítulo.
Como desafio poderia ser passado aos estudantes:
1. Adicionar um contador de vitória para cada jogador;
2. Adicionar uma animação na casinha quando fosse preenchida;
3. Desenvolver um novo jogo utilizando recursos do mouse e matrizes. Um exemplo
em potencial é a criação de um jogo da memória usando matrizes com duas
dimensões.
6.5.1 Resultados
O material apresentado foi oferecido aos estudantes a título de exemplo e nenhuma
atividade extra foi cobrada. Observa-se que seria interessante solicitar que em pequenos
grupos os estudantes pensassem e desenvolvessem pequenos jogos usando apenas o
mouse e o desenho de formas geométricas. São exemplos de projetos que poderiam ser
desenvolvidos:
1. Jogo de perguntas para crianças do tipo: “Clique não azul” e a tela apresenta
blocos de diferentes cores.
2. Jogo em que são desenhados na tela diversos números e uma conta matemática é
apresentada, e assim, a criança precisa clicar na resposta correta. Uma variação
seria os valores ficarem mudando de posição em intervalos de tempo regulares.
3. Jogo para destreza com o mouse onde retângulos coloridos vão sendo exibidos de
135 / 227
tempos em tempos e cada retângulo acertado rende uma certa pontuação.
Para estes jogos ou outros podem ser apresentados os recursos do Aljava para
sortear números aleatórios e os recursos do próprio Java para controle de tempo.
6.4 Módulo 3 – Um Jogo, Muitos Objetos
Neste momento os estudantes apenas desenvolveram classes individuais, o
módulo três tem como desafio demonstrar como objetos de classes diferentes podem
interagir através dos seus métodos. Toda a interação entre os objetos ocorre via métodos
(mensagens) de modo que de forma alguma são usadas variáveis públicas. Outro ponto
deste módulo é o uso de herança da classe Retangulo do Alava, usada essencialmente
para facilitar o trabalho com colisões e movimentação dos objetos. E para ampliar
consideravelmente as possibilidades do jogo é demonstrado o uso da classe ArrayList do
Java.
Carga horária teórica 12 horas / aula
Carga horária prática 12 horas / aula
Produto Final
Um pequeno jogo com 4 classes, colisão entre objetos e uso de
listas.
COO
Métodos com retorno; Herança; Associação / Composição;
CP
Estrutura de repetição “foreach”;
CFA
Acesso ao teclado; uso de imagens e sons; Classe Retangulo.
CLJ
sintaxe dos métodos com retorno.
Ambiente de
Programação
BlueJ
6.4.1 Modelagem Básica
Inicia-se apresentando para os estudantes o desafio de construir um jogo
simulando uma guerra espacial, o jogo deve ser pequeno neste momento para que possase estudar os conceitos básicos, portanto, o jogo terá as seguintes funcionalidades:
•
O jogador controlará uma nave que poderá se mover em todas as direções;
136 / 227
•
A nave poderá lançar tiros que se moverão de baixo para cima;
•
Asteroides descerão da tela;
•
Se um asteroide acertar a nave, o jogador perde o jogo;
•
Se um tiro da nave acertar um asteroide, destrói o asteroide;
•
Quando todos os asteroides estiverem destruídos, o jogador 1 venceu o jogo.
A modelagem deve iniciar pelas três classes base: “Nave”, “Tiro” e “Asteroide”, pois
já é familiar a eles a modelagem de classes como estas. Com as três classes prontas
demonstra-se a modelagem de uma classe que irá representar todo o jogo e que ficará
responsável pelas ações de interação entre objetos diferentes. Neste ponto é importante
ficar claro:
•
Cada objeto conhece somente as suas variáveis de objeto. Deste modo, um objeto
da classe Nave não pode conhecer o valor de uma variável da classe Asteróide;
•
A classe “GuerraEspacial” que representa o jogo contém como variáveis, um objeto
da classe “Nave”, alguns objetos da classe “Asteroide” e diversos objetos da classe
“Tiro”;
•
Somente a “GuerraEspacial” pode realizar operações onde mais de um objeto
estão envolvidos porque somente ela conhece estes objetos. Por exemplo, uma
colisão entre asteroide e nave só poderá ser feita nesta classe.
Segue abaixo um exemplo da modelagem deste jogo apropriada para os conteúdos
deste módulo. Lembrando que inicialmente a Herança não é apresentada, de modo que
todos os objetos das classes base possuem “x”, “y”, “largura” e “altura”.
137 / 227
Ilustração 46: Modelagem básica do jogo Guerra Espacial
A seguir, as três classes base devem ser modeladas. Todas são bastante simples,
segue abaixo o código de cada uma delas e os respectivos comentários do que pode ser
dado destaque para os estudantes.
import aljava.*;
Na declaração das variáveis, nenhuma
class Nave
novidade. Apenas é sugerido voltar a
{
int x;
destacar que aqui as variáveis são
int y;
apenas declaradas, de modo que o
int largura;
“Java” pode reservar um espaço na
int altura;
memória
para
os
valores
destas
variáveis, porém, os valores ainda não
int velocidade;
String nomeJogador;
Nave(){
x = 140;
y = 320;
largura = 40;
altura = 60;
foram inicializados.
No construtor é onde inicializamos os
valores. Destaque para o método
“solicitaTexto” do Aljava que permite
que os estudantes peguem um valor
informado pelo usuário.
velocidade = 5;
nomeJogador =
Alj.tela.solicitaTexto("Nome:");
void movimenta(){
if(Alj.tecla.press("esquerda")){
x -= velocidade;
O movimento do teclado ocorre com o
uso do método “Alj.tecla.press”, como
138 / 227
}
parâmetro este método pode receber
if(Alj.tecla.press("direita")){
x += velocidade;
}
if(Alj.tecla.press("cima")){
y -= velocidade;
qualquer letra do teclado e algumas
teclas
especiais
como
“enter”
e
“espaco”.
Na atribuição da velocidade para o
valor de “x” ou de “y” é extremamente
importante demosntrar que poderíamos
}
ter colocado manualmente o valor “5”
if(Alj.tecla.press("baixo")){
y += velocidade;
}
por exemplo. Mas que dessa forma, se
quiséssemos alterar este valor caso a
nave pegasse um ítem especial, isso
}
não seria possível. Como está em uma
variável, durante o jogo, bastaria um
método que altera a velocidade da
nave.
void desenha() {
Desenha a nave como um triângulo.
Alj.cor.nome("vermelho");
Alj.desenha.texto(
x, y+altura+10, nomeJogador );
Alj.desenha.triangulo(
x, y, largura, altura );
}
void atira(){
//Precisaremos de novos recursos
para este método...
O método atira por hora serve como
um lembrete de que a nave poderá
atirar, sua implementação porém, será
}
completamente diferente como será
visto posteriormente.
}
Fim da classe
Segue abaixo agora a modelagem da classe Asteroide.
import aljava.*;
Declaração de variáveis da classe
class Asteroide {
Asteróide.
int x;
139 / 227
int y;
int largura;
int altura;
int velocidade;
Asteroide(){
Inicialização dos valores das variáveis
x = Alj.util.sorteia(0, 360);
y = Alj.util.sorteia(-400, -50);
largura = Alj.util.sorteia(30, 50);
altura = Alj.util.sorteia(30, 50);
usando
um
método
que
sorteia
números aleatórios entre um mínimo e
um máximo informado pelo usuário.
velocidade = Alj.util.sorteia(2, 8);
}
void movimenta(){
O movimento do asteroide corresponde
y += velocidade;
a ele cair (aumentar o y) até que
chegue ao limite inferior da tela. Neste
if(y > 400){
x = Alj.util.sorteia(0, 360);
momento uma nova posição para ele é
y = Alj.util.sorteia(-400, -50);
sorteada e ele reaparece no topo.
}
}
void desenha() {
Desenha o asteroide como um círculo.
Alj.cor.rgb(120, 120, 120);
Alj.desenha.oval(
x, y, largura, altura
);
}
}
Fim da classe
Por fim, segue abaixo a classe Tiro.
import aljava.*;
Declaração de variáveis da classe Tiro. Deve-
class Tiro {
se dar destaque que são os mesmos atributos
int x;
int y;
do Asteroide e quase os mesmos da classe
int largura;
Nave. Isso mostra que em programação é
int altura;
comum encontrarmos padrões que se repetem,
e com a prática e conhecimento destes
int velocidade;
padrões o desenvolvimento passar a ser muito
140 / 227
mais rápido.
Tiro(int _x, int _y){
x = _x;
y = _y;
largura = 2;
altura = 4;
Inicialização dos valores das variáveis. A única
diferença para os demais é que tanto o “x”
como o “y” deverão vir de fora, pois um tiro
será lançado a partir de um determinado ponto
do cenário, que só será conhecido no momento
velocidade = 10;
da execução.
}
void movimenta(){
y -= velocidade;
}
O movimento do tiro é sempre de baixo para
cima. Mais tarde pode ser demonstrado pelo
professor como lidar com estes tiros que já
saíram do cenário para que eles não ocupem
muito espaço na memória do computador.
void desenha() {
Alj.cor.rgb(255, 255, 255);
Alj.desenha.retangulo(
Desenha o asteroide como um pequeno
retângulo.
x-1, y-2, largura, altura);
}
}
Fim da classe
6.4.2 Lógica do Jogo
Apesar das três classes terem sido trabalhadas, ainda não existe um local onde os
objetos destas classes podem interagir, este local é a classe “GuerraEspacial”. É neste
ponto que demonstramos que uma variável pode conter um objeto de qualquer classe, e
não apenas os cinco tipos básicos demonstrados até o momento.
Os estudantes também já sabem que todo jogo possui um “loop” que realiza as
funções de processamento e desenho em um jogo. Iniciamos por demonstrar o esqueleto
da classe, apenas com a declaração das variáveis de objeto;
141 / 227
import aljava.*
public class GuerraEspacial {
Nave jogador;
Asteroide a1;
Asteroide a2;
Asteroide a3;
//Lista<Tiro> tiros -> próximas seções
GuerraEspacial(){ }
void loop() { }
void desenha() { }
}
Até este momento a única forma usada para criar objetos foi com o BlueJ. Portanto,
iremos relacionar a janela de criação de um objeto do BlueJ com o código usado quando
precisamos criar um objeto diretamente no código. Sobre a criação de objetos e a
respectiva relação com o BlueJ o professor pode ressaltar que:
•
Em Java ou qualquer outra linguagem de programação, a criação de objetos é
sempre feita via código. O recurso usado do BlueJ é puramente didático e ajudou a
compreender o conceito;
•
Sempre que um novo objeto é criado, fica reservado um espaço na memória do
computador para este objeto. As variáveis apenas apontam para este espaço na
memória;
•
Durante um jogo ou outro software diversos objetos são criados e destruídos a
medida que são necessários. Um editor de texto por exemplo, pode usar um objeto
de uma classe Letra para cada letra digitada, um jogo, um objeto para cada tiro
lançado, enfim, softwares de grande porte podem trabalhar com dezenas de
milhares de objetos usando diversas classes diferentes. Vale ressaltar que projetos
podem chegar na casa das centenas de classes com certa frequencia.
E no construtor da GuerraEspacial, inicializam-se os objetos:
142 / 227
GuerraEspacial(){
jogador = new Nave();
a1 = new Asteroide();
a2 = new Asteroide();
a3 = new Asteroide();
}
Para tornar a explicação mais clara pode-se associar a criação de objetos com a
chamada do construtor da classe ao mesmo em que o professor vai preenchendo a
visualização do objeto com os valores do construtor. Se este processo for repetido para a
criação de algo em torno de três objetos, fica claro para os alunos que 1) ao criar um
objeto, ele ganha um espaço na memória com as variáveis projetadas na classe; 2) o
construtor é executado. A imagem abaixo pode ser usada para ajudar os estudantes a
relembrar a sintaxe de construção de objetos, pois conforme experiência do autor, para
certas regras de sintaxe, é interessante este tipo de elucidação do nome de cada
elemento.
Ilustração 47: Sintaxe de Construção de objetos
A próxima novidade é que, assim como os objetos são criados via código, os
métodos também são chamados utilizando a linguagem de programação. O recurso do
BlueJ é meramente para fins didáticos, para que fosse possível aprender a escrever
métodos antes de aprender a chamá-los.
Para chamar métodos utiliza-se uma sintaxe conhecida como notação de ponto,
143 / 227
onde usa-se o ponto como indicador de que será acessado um elemento pertencente a
um objeto.
A execução dos métodos é facilmente demonstrada com a chamada dos métodos
de processamento e de desenho de cada um dos objetos criados.
void loop() {
void desenha() {
while(true){
jogador.desenha();
Alj.tela.limpa();
a1.desenha();
a2.desenha();
jogador.movimenta();
a1.movimenta();
a3.desenha();
}
a2.movimenta();
a3.movimenta();
desenha();
Alj.tela.exibe();
Alj.util.espera(50);
}
}
Pode ser ressaltado do código acima o uso do ponto para informar que um método
será chamado de um objeto, o uso do método espera do Aljava para que o jogo fique em
uma velocidade agradável ao olho humano e que a partir de agora, o desenvolvimento
consiste em 1) pensar quais métodos são adequados para as tarefas que desejamos
realizar; 2) construir estes métodos e 3) executar estes métodos.
O momento de execução agora é muito interessante para os estudantes porque
demonstra bastante movimento, e com frequência, somente aqui é que eles percebem
como poderão construir um jogo conforme os seus interesses.
Antes de avançar é sugerido a demonstração de execução do programa utilizando
as representações visuais de objetos já demonstradas aqui e como a cada execução do
“loop” os valores vão sendo alterados dentro dos diferentes objetos.
144 / 227
Ilustração 48: Telas da implementação parcial do jogo GuerraEspacial
6.4.3 Herança
Para este exemplo, fica evidente a necessidade de fazer colisões funcionarem
entre retângulos para podermos criar mais interações. O autor optou por um caminho em
que os estudantes não devem ser exigidos em questões matemáticas mais complexas.
Essa escolhe ocorreu por dois motivos:
•
Porque o foco é orientação a objetos e não matemática;
•
Porque este é um fator que desmotiva muitos dos estudantes antes mesmo de
terem tido a oportunidade de sentir satisfação em programar.
Portanto, a colisão precisa ser fornecida pelo professor. Este problema ofereceu
uma excelente oportunidade para o uso de herança. Com as três classes que
representam objetos possuem os mesmos quatro parâmetros (x, y, largura e altura) e
todas precisarão de métodos de colisão, foi modelada uma classe “Retangulo”, que
servirá de base para qualquer objeto que possa ser apresentado visualmente e precisa de
colisão.
Inicialmente é importante que eles conheçam a classe “Retangulo” e para tal, a
classe deve ser apresentada para os estudantes conforme apresentado na seção de
documentação, inclusive com exemplos e se possível, com exercícios práticos. Deve ficar
muito claro antes de avançarmos para herança que a classe “Retangulo”:
•
Tem quatro variáveis inteiras, x, y, largura e altura;
•
Tem dois construtores, um vazio que inicializa tudo como zero e um que recebe
145 / 227
quatro parâmetros inteiros (x, y, largura e altura);
•
Possui os métodos:
◦
◦
◦
◦
◦
◦
◦
◦
moveX(int distancia);
moveY(int distancia);
alteraX(int novoX);
alteraY(int novoY);
alteraLargura(int novaLargura);
alteraAltura(int novaAltura);
toca(Retangulo outro);
desenha();
Uma das formas de demonstrar o uso da classe é usar objetos da classe Retangulo
para representar outros asteroides.
import aljava.*;
import aljava.jogo.Retangulo;
public class GuerraEspacial {
...
Retangulo r1;
GuerraEspacial(){
...
r1 = new Retangulo(130, 200, 40, 40);
}
void loop() {
...
r1.moveY(4);
if(r1.pegaY() > 400){
r1.alteraY( Alj.util.sorteia(-400, 0) );
}
...
}
void desenha() {
...
r1.desenha();
}
}
O uso da Herança pode ser apresentado agora como recurso para aumentar o
146 / 227
reuso de código. Pode-se apresentar em conjunto a operação de abstração
“generalização e especialização” e o uso do termo “é um”, demonstrando que existe uma
boa oportunidade de herança quando podermos dizer que um objeto de uma classe é
também um objeto de outra classe, por exemplo, “um objeto da classe Asteroide também
é um Retangulo”. Segue abaixo comparação da classe Asteroide com e sem herança.
import aljava.*;
import aljava.*;
class Asteroide
import aljava.jogo.Retangulo;
{
class Asteroide extends Retangulo
int x;
{
int y;
int largura;
int velocidade;
...
int altura;
int velocidade;
...
Tabela 14: Comparação com e sem uso da herança
Neste momento, mostra-se que como a classe “Retangulo” já declara as variáveis
x, y, largura e altura, estas podem ser removidas da classe Asteroide, mas mesmo assim,
podem ser utilizadas nos demais métodos. Além disso, agora qualquer objeto da classe
Asteroide tem disponível, além dos métodos dele, todos os métodos da classe
“Retangulo”. Entre eles, o método “toca(Retangulo outro)” que será usado agora para
fazer colisão dos asteroides com as naves.
O método “toca(Retangulo outro)” tem dois conceitos de destaque, ele é um
método com retorno e recebe como parâmetro um objeto da classe “Retangulo”. Isso
pode ser demonstrado aos alunos através da própria assinatura do método.
boolean toca(Retangulo outro)
Agora, no lugar do termo “void” existe boolean, mostrando que sempre que um
método tiver um retorno, o tipo do retorno estará no lugar de “void”, que significa apenas
que o método não retorna nenhum valor.
Como o método retorna um valor booleano ele pode ser usado dentro de uma
estrutura condicional como “if/else”. Os métodos que verificam se algum botão do mouse
ou tecla do teclado estão pressionados também são métodos que retornam valores
booleanos. Já os métodos que retornam o valor do x e do y do mouse são métodos que
147 / 227
retornam valores inteiros.
O segundo ponto é o uso de um objeto como parâmetro. Isto pode fortalecer o
entendimento de que parâmetros também são variáveis, assim como as variáveis de
objeto ou as variáveis locais, e que, toda variável tem um tipo e este tipo pode ser um dos
5 primitivos apresentados ou um objeto de alguma classe.
Segue exemplo de uso do método que verifica se um asteroide colide com uma
nave. Este código é adicionado dentro do “loop”, antes do método “desenha”.
if( a1.toca(jogador) ){
Alj.tela.exibeMensagem("Você perdeu");
Alj.tela.finaliza();
}
Seguindo o padrão pedagógico “Mistake” documentado na seção 2.4.10, solicita-se
que os alunos compilem este código. Assim, eles serão apresentados ao erro: “cannot
find symbol - method toca(Nave); maybe you meant: toca(Retangulo)”. Em geral, mesmo
os alunos que conhecem inglês não conseguem compreender nada da mensagem, de
modo que sugere-se uma explicação parte a parte:
•
“cannot find symbol” - Significa que foi utilizada alguma variável ou método que o
Java não reconheceu como válido. Isso acontece quando erramos a digitação, o
escopo ou o tipo dos parâmetros (no caso de métodos);
•
“method toca(Nave)” - O símbolo não encontrado foi o método “toca(Nave)”. Ele
está informando que não existe nenhum método toca que recebe uma nave como
parâmetro.
•
“maybe you meant: toca(Retangulo)” - O BlueJ já ajuda com a dica e pergunta se
não estava-se querendo dizer um método toca que recebe um retangulo como
parâmetro.
Assim, basta perguntar se da forma como o nosso código está programado, objetos
da classe nave são ou não retângulos. Após a discussão os estudantes devem corrigir o
erro e colocar herança também na classe Tiro para podemos usá-la no próximo capítulo.
148 / 227
Para fortalecer o conteúdo pode ser solicitado que os estudantes criem uma classe
“Bonus” e criassem objetos desta classe para que quando a nave tocasse em um deles,
adquirisse maior velocidade. Devem ser adicionados pelo menos dois objetos desta
classe ao Jogo para fortalecer o conteúdo.
6.4.4 Listas
Os asteroides foram colocados em variáveis separadas, para se verificar a colisão
de cada asteroide com a nave é necessário três “if`s” no “loop” principal. Este é o mesmo
problema do desenho das “casinhas” no jogo da velha e provavelmente os estudantes
sugerirão o uso de matrizes para resolver esta questão. De modo a demonstrar que
matrizes são ótimas para coleções de tamanho fixo, mas não são adequadas para listas
variáveis pode ser usado o exemplo de que o jogo, de tempos em tempos poderá
aumentar o número de asteroides, aumentando a dificuldade.
Podemos armazenar quantos objetos forem necessários em uma lista. Em Java, já
existem algumas classes que implementam o conceito de listas, dentre elas “ArrayList” e
“LinkedList”. Durante a aplicação da metodologia, verificou-se que o conceito de uma
classe que armazena diversos objetos ficou abstrato demais e os estudantes não
conseguiam compreendê-lo. Uma sugestão seria demonstrar, usando as representações
visuais já citadas, como funcionam as classes “ArrayList” e “LinkedList”.
Para o nosso curso usaremos a classe “ArrayList” por ser a mais comum. O uso da
classe “ArrayList” segue o mesmo princípio das demais classes, podem ser criados
objetos e cada objeto tem acesso a certos métodos como “add(Object o)” ou
“remove(Object o)”. A única grande diferença é a sintaxe usada pelo Java para
informarmos para a lista, qual o tipo dos objetos que a lista conterá. Conceitualmente é
fácil explicar isso aos alunos questionando: “Uma lista de que?”. No nosso caso será uma
lista de asteroides, portanto, a declaração da variável que conterá o objeto da lista e
arespectiva inicialização desta variável podem ser feitas da seguinte forma:
ArrayList<Asteroide> asteroides;
Costrutor(){
asteroides = new ArrayList<Asteroide>();
}
149 / 227
Agora que já temos uma lista, ela esta vazia. Demonstramos a inclusão de novos
asteroides dentro dela com o seguinte código:
asteroides.add( new Asteroide() );
asteroides.add( new Asteroide() );
asteroides.add( new Asteroide() );
Este trecho de código precisa ser acompanhado da respectiva construção visual
dada a dificuldade de abstração de termos objetos dentro de outro objeto. A
representação visual usada pode ser a seguinte:
Ilustração 49: Representação Visual da Lista
Esta mesma representação pode ser utilizada como auxiliar para a demonstração
do funcionamento da estrutura de repetição “foreach”, a forma mais fácil de se percorrer
uma lista. Segue código para processar a colisão de todos os asteroides com a nave:
for(Asteroide a : asteroides) {
a.movimenta();
if( a.toca(jogador) ){
Alj.tela.exibeMensagem("Você perdeu");
Alj.tela.finaliza();
}
}
Em geral os alunos tem muita dificuldade com a variável temporária usada no “loop
foreach”, é de difícil percepção o fato de que a cada rodada do “loop” aquela variável
estará apontando para um objeto diferente da lista. Isso pode ser demonstrado com o
150 / 227
auxílio da representação abaixo e com a execução do tradicional “teste de mesa”.
for( int i = 0; i < asteroides.size(); i++) {
Asteroide a = asteroides.get( i );
a.desenha();
}
Se for percebido que os estudantes continuam sem compreender pode ser usado o
mesmo método utilizado com os “Arrays”, ou seja, com o for tradicional. Uma terceira
opção é usar também o “loop” “while” e assim, fortalecer ao máximo que existem diversas
formas de se percorrer uma coleção, sendo importante sabermos escolher qual delas
iremos querer usar.
Ilustração 50: Representação visual para o "loop foreach"
6.4.5 Tiros e Métodos com Retorno
Agora faremos os tiros da nave. O primeiro passo é criar a lista de tiros da mesma
forma que fizemos com os asteroides, sendo que a principal diferença está no fato desta
lista iniciar vazia. Nota-se aqui que a lista, mesmo iniciando vazia, deve ser percorrida
para que os tiros sejam processados e desenhados para que, no momento que a lista
receber o primeiro objeto, ele já seja automaticamente desenhado.
Havia sido modelado na classe “Nave” um método “atira”, pois atirar é uma função
da nave. Porém, a ação de tirar consiste em adicionar um objeto da classe “Tiro” dentro
151 / 227
da lista, logo, esta ação precisa ser feito dentro da classe “GuerraEspacial” que é onde
está a variável que contém a lista de tiros. Mesmo assim, o objeto “jogador” da classe
“Nave” ainda terá um papel importante pois o tiro deve sair posicionado inicialmente em
relação a posição da nave.
Para a inclusão de tiros no cenário, pode ser modelado com os alunos o seguinte
algoritmo:
1. Verifica quando o jogador pressionou espaço.
2. Pega o x e o y iniciais do Tiro. Inicialmente, iremos posicionar o tiro inicialmente no
mesmo x e no mesmo y da nave, mais tarde ajustaremos estes valores;
3. Cria um objeto da classe Tiro;
4. Adiciona o objeto na lista.
//Passo 1
if( Alj.tecla.press("espaco") ){
//Passo 2
int xTiro = jogador.pegaX();
int yTiro = jogador.pegaY();
//Passo 3
Tiro umTiro = new Tiro(xTiro, yTiro);
//Passo 4
tiros.add( umTiro );
}
Cada passo do algoritmo deve ser cuidadosamente explicado. Os métodos
“pegaX()” e “pegaY()” devem ser apresentados como métodos que retornam valores
inteiros e possuem a seguinte implementação na classe “Retangulo”:
152 / 227
int pegaX() {
return x;
}
int pegaY() {
return y;
}
A instrução “return” é apresentada como responsável por fazer com que um valor
seja enviado de dentro do método para o local onde ele foi chamado, neste caso, para
dentro das variáveis “xTiro” e “yTiro”.
Na inicialização do objeto da classe “Tiro” pode ser relembrada a assinatura e o
código do respectivo construtor, para melhor assimilação do uso de parâmetros.
Agora, nota-se que os tiros são lançados do canto superior esquerdo da nave,
obviamente. Para corrigir, é preciso fazer com que o “x” do tiro inicie no equivalente à
ponta do triangulo. Para esta tarefa é sugerida a criação de um método na classe Nave,
que, ao invés de simplesmente retornar o valor de “x”, retorna o valor exato de onde o tiro
deve ser lançado. Este método é o primeiro método com retorno que os estudantes
escrevem de modo que todas as mudanças em relação aos métodos de acesso, escritos
até então, sejam clarificadas.
int pegaXTiro(){
int xDoTiro = x + (largura/2);
return xDoTiro;
}
Com isso os estudantes podem fazer com que o tiro seja lançado de qualquer
posição do triângulo. E ainda mais, se desejarem, podem fazer com que a cada vez que o
espaço for pressionado, dois tiros sejam incluídos no cenário, um da direita da nave e um
da esquerda. Para ampliar o nível dos desafios, a nave poderia lançar tiros para lados
diferentes ou ainda usar teclas do teclado distintas para lançar tiros de posições
diferentes da nave. Com estes desafios os estudantes tem a oportunidade de treinar o
uso de métodos com retorno e a modelagem de classes com a possibilidade dos tiros em
diferentes direções.
153 / 227
6.4.6 Colisões entre listas e finalização do jogo
Com os tiros no cenário, podemos trabalhar na colisão deles com os asteroides.
Podem ser feitas diversas ações diferentes quando um tiro acertar um asteroide. A opção
escolhida para este exemplo foi diminuir o tamanho dos asteroides até que atinjam uma
largura menor do que 20, a partir de onde, não seriam mais desenhados. É criado então,
um método “foiAtingido()” na classe asteroide que diminui em um, os valores da largura e
da altura do asteroide. Além disso, no método desenha, se a largura for menor do que 20,
o asteroide não é mais desenhado.
A colisão entre asteroides e tiros envolve duas listas, cada tiro precisa verificar a
colisão com cada um dos asteroides. Fazemos isso percorrendo cada tiro com um
“foreach” e para cada um dos tiros, um outro “loop foreach” para percorrer cada um dos
tiros. Como já existe um “loop” que processa o movimento de cada tiro, o código de
colisão com os asteroides foi feito dentro deste “loop”.
for(Tiro t : tiros) {
t.movimenta();
for(Asteroide a : asteroides){
if(t.toca(a)){
a.foiAtingido();
}
}
}
Mais uma vez, o teste de mesa demonstrando as variáveis “t” e “a” apontando para
cada objeto durante a execução dos dois “loops” é de grande auxílio.
Neste momento do código, o método “loop” da classe “GuerraEspacial” já está
tomando proporções grandes e ficará cada vez mais difícil realizar alterações nele. Para
melhorar o código, os alunos podem ser ensinados sobre a importância de dividir códigos
grandes em unidades menores. Para este exemplo, cada bloco do método “loop” foi
dividido para um método dentro da própria classe “GuerraEspacial” de modo que após
esta mudança o código ficou muito mais limpo:
154 / 227
void loop() {
while(true){
Alj.tela.limpa();
jogador.movimenta();
processaAsteroides();
processaTiros();
lancaTiros();
desenha();
Alj.tela.exibe();
Alj.util.espera(50);
}
}
Ao executar o jogo, percebe-se um grande problema, os asteroides considerados
“mortos”, continuam colidindo com o jogador. Pode aqui ser solicitado que os alunos
tendem descobrir o que aconteceu de errado. Após descoberto o problema existem duas
soluções possíveis:
1. Realizar um procedimento que a cada rodada, remove da lista de asteroides os
que estão com largura menor do que 20.
2. Antes de verificar a colisão com o personagem verificar se o asteroide tem largura
adequada, em caso negativo, não verifica a colisão com o jogador.
Pode-se aproveitar esta escolha para mostrar o problema de performance que seria
ter um grande número de asteroides que não estão sendo nem desenhados e nem
verificados na colisão dentro das listas. Por exemplo, se houvessem 20 asteroides na
lista, mas somente três visíveis e 100 tiros, haveria o processamento de 2000 colisões
entre asteroides e tiros para rodada do jogo. Isso é muito e poderia ser facilmente
diminuída para 300, se os asteroides já destruídos não estivessem na lista.
Para remover os asteroides não mais utilizados o melhor algoritmo encontrado foi o
que percorre a lista de traz pra frente e vai removendo os que já estiverem destruídos.
Usar o “foreach” não é possível pois toda operação de inclusão ou remoção de itens em
uma lista que está sendo percorrida lançarão uma exceção. Este algoritmo é complexo e
não é sugerido cobrar que os alunos consigam implementá-los em uma prova por
155 / 227
exemplo. Porém, como são necessários para a performance do jogo, é importante que
sejam apresentados.
void removeObjetosNaoUtilizados(){
int max = asteroides.size() - 1;
for(int i = max; i >= 0; i--){
Asteroide a = asteroides.get(i);
if(a.estaDestruido()){
asteroides.remove(a);
}
}
int maxTiros = tiros.size() - 1;
for(int i = maxTiros; i >= 0; i--){
Tiro t = tiros.get(i);
if(t.estaForaDaTela()){
tiros.remove(t);
}
}
}
Para que o algoritmo acima pudesse ser construído foram necessários mais dois
métodos com retorno, um que informa se o asteroide foi destruído e outro se o tiro está
fora da tela. Estes métodos tem retorno booleano e são mais uma ótima forma de
exercitar o uso de métodos com retorno.
A finalização do jogo depende agora de só mais uma regra, quando a lista de
asteroides ficar fazia, o jogo pode ser encerrado com a vitória do jogador.
if(asteroides.size() == 0){
Alj.tela.exibeMensagem("Parabéns, voce venceu");
Alj.tela.finaliza();
}
Aqui fechamos o jogo conforme o exemplo, existe ainda muito potencial de
funcionalidades como pontuação, contagem de tempo, mais inimigos, bônus, etc. O
professor neste momento deve decidir para quais desafios direcionar a turma.
156 / 227
6.4.7 Classe ContadorTempo
Sempre surgem necessidades de uso de tempo durante os jogos, como por
exemplo, após a nave lançar um tiro, aguardar uma certa quantidade de milissegundos
para poder lançar outro. Esse tipo de ação pode ser feito com o uso da classe
“ContadorTempo”, de modo que o professor deve apresentar a documentação desta
classe.
6.4.8 Pacote de Mídia
Para tornar ainda maior o interesse dos estudantes, é possível usar as classes do
pacote mídia para criar animações, usar imagens e executar sons. E sugerido que isso só
seja explicado após os jogos erem sido iniciados usando formas geométricas básicas,
para que eles percebam que por trás de cada objeto, sempre existirá uma forma
geométrica (no nosso caso, um Retângulo). Este material também pode ser demonstrado
via documentação.
6.4.9 Resultados
Assim como o módulo um, este módulo foi aplicado a uma turma de 25 estudantes
com as seguintes diferenças:
•
Classe java.awt.Rectangle: Na primeira aplicação, herança ainda não era vista
(era assunto do módulo 4), então, para as colisões, foi usada a classe “Rectangle”
da própria plataforma Java. O problema era que para verificar a colisão entre
objetos, cada classe tinha que ter um método que retornava um retângulo. Assim, a
colisão se torna muito complexa e foi verificado que os estudantes só conseguiam
utilizá-la através de “cópia”, sem compreensão clara do seu significado;
•
Herança: Foi percebido durante a aplicação do módulo quatro (posterior a este)
que a compreensão de herança foi bastante fácil, dessa forma, optou-se por trazêla para o módulo anterior;
•
Sem aprofundamento no foreach: O autor considerou o “loop foreach” tão óbvio
que não se teve cuidado em demonstrar com clareza o que acontecia por trás dele,
bem como não foram utilizadas outras estruturas de repetiçao para percorrer uma
lista. Mais tarde, surgiam diversas duvidas dos alunos quanto a esta estrutura.
Foi proposto como tarefa final do módulo a construção parcial de um jogo, que
deveriam ter pelo menos uma lista e realizar interações diversas entre os objetos.
157 / 227
Ao todo foram desenvolvidos 12 produtos que chamaram atenção pela criatividade
e diversidade das propostas. dos 12 trabalhos, apenas 2 não demonstraram não ter
compreendido o conteúdo apresentado. Seguem alguns exemplos de trabalhos
desenvolvidos.
6.4.9.1 A Ponte
Este jogo apresenta dois personagens que podem ser movimentados pelo teclado
lançando flechas em “zumbis”. Se os zumbis atingem os personagens, eles perdem
pontos de vida.
Ilustração 51: Exemplo de tela do jogo "A
Ponte"
Nota-se que o jogo utiliza exatamente a mesma lógica que o Guerra Espacial, como
se os personagens fossem objetos da classe “Nave”, os “zumbis”, personagens da classe
“Asteroide” e as flechas personagens da classe “Tiro”. Este jogo, pois, não apresenta
nenhum recurso computacional novo, mas aplica com fidelidade os recursos
apresentados.
6.4.9.2 Pacman
Este jogo ficou apenas parcialmente desenvolvido e apresenta o personagem
“Pacman” comendo as tradicionais bolinhas.
158 / 227
Ilustração 52: Tela do jogo Pacman
O destaque foi o interesse do aluno em construir o cenário do Pacman. como já
havia sido trabalhado o conteúdo de matrizes ele foi apresentado à técnica de uso de
matrizes bidimensionais para a construção de cenários. Ao final também conseguimos
adicionar parcialmente colisão do Pacman com o cenário.
6.4.9.3 Ken vs Akuma
Mais um “remake” dos jogos tradicionais, este jogo simula uma batalha entre dois
conhecidos jogos de StreetFighter.
Ilustração 53: Tela do jogo Ryu vs Akuma
Um dos destaques do jogo foi uma classe usada para verificar se o jogador
pressionou uma certa sequencia de botões. Em caso positivo, o personagem lança golpes
especiais.
159 / 227
6.4.9.4 Mundo de Molland
Este jogo apresenta um personagem que precisa pular e fugir das “cabeçadas” de
ovelhas.
Ilustração 54: Tela do jogo Mundo de Molland
Assim como o primeiro jogo demonstrado, este utiliza praticamente a mesma lógica
da “GuerraEspacial”. Seu destaque está no fato de que todas as imagens usadas no jogo
foram produzidas pelos próprios estudantes, demonstrando o potencial do método usado
mesmo com alunos cujo maior foco e interesse é o artístico.
6.5 Módulo 4 – Pequeno mundo virtual
O objetivo do módulo 4 é demonstrar que usando padrões de codificação simples é
possível construir uma estrutura escalável para o software, ou seja, que permita o
crescimento do mesmo. Esta seção deve oferecer uma visão inicial sobre arquitetura de
um software. Como projeto deste módulo é produzido um pequeno mundo, chamado de
“Mundo dos Quadrados” que é percorrido por um personagem em uma tela de seleção,
duas fases e um “chefão”.
Neste módulo também, passamos a usar um ambiente de desenvolvimento
profissional como o NetBeans ou Eclipse. Para este projeto foi escolhido o ambiente
NetBeans.
Carga horária teórica 8 horas/aula
Carga horária prática 12 horas/aula
160 / 227
Produto Final
Um jogo com pelo menos 8 classes distribuídas em fases, objetos
do jogo e classes auxiliares.
COO
Sobrescrita de método; Modificador static: contantes de classe /
métodos estáticos;
CP
nenhum novo.
CFA
Classes Para manipulação do Cenário
CLJ
nenhum novo.
Ambiente de
Programação
NetBeans
6.5.1 Modelando um jogo escalável
Jogos tradicionalmente possuem muitos objetos e fases. Em software é comum a
identificação de certos padrões. Estes padrões, quando percebidos e identificados
agilizam muito o desenvolvimento de software.
Já percebemos por exemplo que todo objeto que aparece na tela do jogo pode ser
representado através de uma forma geométrica ou mais especificamente, de um
Retângulo. Percebemos também que frequentemente estes objetos possuem um método
para processar a lógica interna deles e outro para o desenho do mesmo.
Dessa forma, a equipe de desenvolvimento pode acordar que todos os objetos do
jogo serão uma especialização da classe “Retangulo” e terão dois métodos, um chamado
“processa()” para a lógica interna e um chamado “desenha()” para, obviamente, o
desenho.
Da mesma forma, uma fase, conforme vimos até aqui, possui um método “loop()”
para o loop central do jogo e um método “desenha()” para desenhar todos os elementos
daquela fase. Além destes dois, poderíamos ter um terceiro método que direciona o
jogador para alguma outra fase, chamaremos este terceiro método de “”proximaFase(int
numFase)”.
Apesar de ser claro que estes dois casos são evidentemente casos dignos de uso
de classes abstratas (no caso dos objetos do jogo) e interfaces (no caso das fases), estes
dois conceitos serão abordados no módulo 5. Primeiro, é importante perceber o conceito
de um padrão, e somente depois, de como formalizá-lo com recursos de programação
161 / 227
orientada a objetos.
Com estes dois padrões definidos, podemos ter uma visão da arquitetura do jogo
como no modelo abaixo:
Ilustração 55: Representação Visual dos padrões
Com esta arquitetura em mente, pode-se partir para a construção dos objetos e das
fases do jogo. É importante que os estudantes percebam que inicialmente, o importante é
ter o padrão porque ele facilita tanto o entendimento dos códigos quanto aumenta a
velocidade de escrita de novos códigos, fica mais claro por onde começar.
Para demonstrar o uso dos padrões considera-se o jogo “A Aventura do Quadrado”
a ser desenvolvido neste módulo. O jogo possui quatro telas, sendo a primeira a tela de
seleção de um personagem, duas fases e uma fase final contendo um personagem
“Chefão”. O jogo também conta com 4 personagens (objetos de jogo), 1) o “SenhorQ”, um
quadrado que pode saltar e se mover pela tela e que precisa atravessar as fases; 2)
“InimigoQuadradao”, um grande quadrado que fica parado na tela e sempre que o
“SenhorQ” encosta nele, perde parte da vida; 3) “InimigoTic”, um quadrado que fica
pulando sem parar, no qual o “SenhorQ” não deve tocar e 4) “SuperQuadradao”, o inimigo
final do jogo que é um grande quadrado que lança tiros.
O código das classes dos objetos são bastante simples e seguem os padrões já
vistos nos demais módulos, o código completo de cada um dos quatro personagens pode
ser visto no anexo 2. Os únicos destaques que devem ser considerados são 1) uso de
sobrescrita de método nos métodos “desenha” e “processa” em alguns dos personagens
2) a chamada do construtor “Retangulo” com quatro parâmetros para informar os valores
162 / 227
“x”, “y”, ”largura” e “altura” de todos os personagens.
public class SenhorQ extends RetanguloGravidade {
...
int velocidade;
public SenhorQ(){
super(40, 200, 32, 32);
...
velocidade = 4;
}
...
@Override
public void processa(){
processaMovimento();
super.processa();
}
...
@Override
public void desenha(){
Alj.cor.hexadecimal("#4512AE");
int novoY = y + (altura - vida);
Alj.desenha.retangulo(x, novoY, largura, vida);
super.desenha();
}
}
Texto 1: Novo recurso de sobrescrita de métodos e chamada de métodos da superclasse
As fases seguem praticamente os mesmos conceitos trabalhados na classe
“GuerraEspacial” com três exceções:
•
O método “proximaFase” utiliza métodos estáticos e conversão explícita para
realizar a troca de fases, esta parte será explicada na seção 6.5.6;
•
A classe “TelaInicial” utiliza uma classe “TelaSelecao” para auxiliar a escolha de um
personagem do usuário. A classe “TelaSelecao” foi produzida junto dos estudantes
e está documentada no anexo 3;
163 / 227
•
As classes usam objetos da classe “CenaComColisao”. Esta classe é mais
complexa que as demais e deve ser explicada aos alunos em detalhes com o
auxílio da documentação da seção 5 deste documento.
Todos os códigos das fases estão disponíveis no anexo 4.
Outro ponto agora é que se tomarmos como exemplo jogos como o tradicional
“Super Mario” o número de fases e de personagens é muito alto. Para organizar um
grande número de classes em projetos de grande porte, pode-se usar o recurso de
“pacotes” para organizar as classes. Este recurso é importante também para que, caso
sejam incluídas bibliotecas externas ao projeto, os nomes das classes não entrarão em
conflito pois estão em pacotes diferentes.
Ilustração 56: Organização de Pacotes
do Jogo "A Aventura do Quadrado"
O uso de pacotes traz a necessidade de que os métodos que devem ser públicos
sejam declarados como tal. Este momento pode ser utilizado para apresentar o conceito
de encapsulamento e os modificadores de acesso “public”, “protected” e “private”.
6.5.2 Ambiente de Desenvolvimento Profissional
Todo o processo de demonstração das classes e da aplicação deve ser feito já
dentro do NetBeans com as respectivas explicações sobre cada uma das janelas do
164 / 227
software e dos principais recursos do editor de texto como por exemplo:
•
Minimizar e maximizar métodos;
•
Autocompletar de código;
•
Refatoração de variáveis e nomes de classes;
•
Busca pelo uso de métodos e variáveis;
Um exemplo deste processo é o uso da maximização e minimização de código para
demonstrar e navegar em uma classe:
Ilustração 57: Classe Fase1 com os métodos
minimizados
A medida que o código cresce, sem exceção, os alunos passam a se confundir
com mais frequência e demorar muito mais tempo para localizar um código. A
demonstração clara dos recursos do ambiente de desenvolvimento é essencial. Os alunos
geralmente não se dedicam a explorar a ferramenta para descobrir os recursos que ela
apresenta, porém, geralmente estes recursos são muito úteis.
6.5.3 Compartilhamento de Objetos e o método Main
Até agora os projetos foram executados através da criação direta de objetos pelo
BlueJ e a respectiva execução dos seus métodos. Os alunos devem ser infromados que
165 / 227
este recurso do BlueJ é puramente didático e que para iniciar um software orientado a
objetos, é preciso construir o código que cria os objetos iniciais e executa os métodos
necessários para a execução do programa.
Em Java, existe um método especial para iniciar a execução do software,
conhecido como “método main”. Este método pode estar dentro de qualquer classe do
programa, mas para fins de organização, comumente usa-se uma classe a parte somente
para este método. geralmente chamada de “Main” ou “Principal”.
Neste ponto, os estudantes já tem conhecimento necessário para compreender
quase que integralmente, de modo que cada palavra na sintaxe do método pode ter seu
significado explicado:
•
public: significa que o método é público e pode ser executado de fora da classe;
•
static: significa que o método pertence à classe e não a um objeto dessa classe.
Isso será visto brevemente no próximo capítulo.
•
void: significa que o método não retorna nenhum valor;
•
main: é o nome do método padronizado pela linguagem Java;
•
String[] args: O método pode receber uma matriz de Strings como parâmetro. Isto
é útil apenas para programas que são executados via linha de comando. Em
programas, quando se executa um programa na linha de comando, podem ser
informados diversos textos como parâmetros.
O jogo consiste basicamente em criar um objeto da classe TelaInicial e executar o
respectivo método “loop”. Deste modo, um exemplo de método “main” inicial seria:
public class Principal {
public static void main(String[] args) {
TelaInicial t = new TelaInicial( );
t.loop();
}
}
166 / 227
Precisa-se agora, organizar a arquitetura de tal forma que todas as fases do jogo
apontem para o mesmo objeto da classe “SenhorQ”. Isso é importante para que o estado
do jogador se mantenha entre as fases. Se por exemplo, durante a fase 1 o jogador
perdeu 20 pontos de vida, na fase 2 ele não pode iniciar com vida total. Isso aconteceria
se criássemos um novo objeto “SenhorQ” dentro de cada fase. Uma abordagem que pode
ser utilizada é fazer com que o “SenhorQ” seja criado antes de cada uma das fases e
enviado para elas via parâmetro.
SenhorQ senhorq = new SenhorQ();
Fase1 f = new Fase1( senhorq );
TelaInicial t = new TelaInicial( senhorq );
Fase2 f2 = new Fase2( senhorq );
FaseChefao c = new FaseChefao( senhorq );
Assim, cada fase tem uma variável que faz uma referência para o objeto do
“SenhorQ”. É muito importante a percepção de que as variáveis de cada fase apenas
“apontam” para um objeto na memória do java. Isso pode ser representado visualmente
com o seguinte diagrama:
Ilustração 58: Exemplo de visualização de "referência"
167 / 227
Agora, ainda temos um problema que é fazer com que uma fase possa executar o
método “loop” de outra sem precisar criar um novo objeto da fase. Uma forma d e fazer
isso é usando a mesma solução do caso do “SenhorQ”. O problema desta abordagem
está 1) no uso de grande número de parâmetros caso uma fase tenha muitas saídas e 2)
na inclusão e remoção de novas fases, pois afetariam o código do construtor de todas as
fases que podem levar a ela. Uma solução alternativa é vista no próximo capítulo, tendo
como novo conceito o modificador static.
6.5.4 Variáveis e Métodos Estáticos
As fases precisam ser acessadas a partir de qualquer outra fase. Este problema
pode ser facilmente resolvido com uso de variáveis estáticas para armazenamento das
fases e seu posterior acesso.
De modo a construir algo que pudesse atender ao crescimento do software e
suportasse a arquitetura de fases e objetos propostas foi construída a classe
“GerenciadorFases” que contém uma única variável estática do tipo “HashMap” para
armazenar os objetos e dois métodos, um para inclusão e outro para recuperação de
fases do “HashMap”.
package aaventuradoquadrado;
import java.util.HashMap;
public class GerenciadorFases {
public static HashMap<String, Object> fases
= new HashMap<String, Object>();
public static void adicionaFase(String chave, Object fase){
fases.put(chave, fase);
}
public static Object pegaFase(String chave){
return fases.get(chave);
}
}
O ensino de métodos e variáveis estáticos é, segundo opinião do autor, muito difícil,
168 / 227
pois não possui nenhuma relação com Orientação a Objetos. Não há objetos envolvidos.
Funciona muito mais como uma forma de construir variáveis e métodos “globais”,
semelhante ao que é feito na programação estruturada.
Por isto, é dada muito pouca ênfase a este recurso, de modo que os estudantes
precisam conhecê-lo para sua posterior experiência profissional, mas não precisam em
nenhum momento da metodologia, escrever métodos ou variáveis estáticas.
Outro ponto importante deste exemplo é o uso da classe “HashMap”, muito comum
em softwares Java. Na experiência do autor, os alunos precisam de uma atenção especial
para esta classe e com o conceito de “chave => valor” usado pela estrutura para
armazenar objetos.
Antes de avançarmos para o uso da classe deve estar claro para os estudantes
que:
•
Métodos e variáveis estáticos são identificados com o modificador “static”
imediatamente antes do tipo de retorno;
•
Métodos e variáveis estáticas, pertencem à classe, isso significa que a
criação de objetos não afeta estes métodos e que um objeto não pode
executar um método estático, somente a referência para a própria classe, é
que pode executar estes métodos;
•
Métodos e variáveis estáticas podem estar presentes em qualquer classe;
•
“HashMap” é uma estrutura que pode armazenar coleções de objetos da
mesma forma que a “ArrayList”. A grande diferença é que a classe
“HashMap” permite que seja informado um objeto de qualquer classe para
servir como “chave” de um objeto. No nosso caso usaremos como chave
objetos da classe String para armazenar qualquer tipo de objeto.
O primeiro passo é colocar cada objeto que representa uma fase dentro do
“HashMap” da classe “GerenciadorFases” através do método “adiciona()”. Isso pode ser
feito no método “main”, após a inicaalização de cada fase.
169 / 227
GerenciadorFases.adicionaFase("telaInicial", t);
GerenciadorFases.adicionaFase("fase1", f);
GerenciadorFases.adicionaFase("fase2", f2);
GerenciadorFases.adicionaFase("chefao", c);
Agora, podemos observar o método “vaiParaFase1()” dentro da classe “TelaInicial”
como exemplo de como recuperar um dos objetos que representam uma fase, convertê-lo
para o seu tipo (classe) correspondente e executar o método “loop()” da fase.
private void vaiParaFase1() {
Fase1 fase = (Fase1)GerenciadorFases.pegaFase("fase1");
fase.loop();
}
Ressalta-se apenas que o método “pegaFase()” pode retornar qualquer objeto de
qualquer classe. Desse modo, precisamos informar ao Java através da conversão
explícita que o objeto retornado pertence à classe Fase1. Após, basta executar o método
“loop()” da fase.
Desse modo, encerra-se o módulo 4 demonstrando que é possível manipular as
fases de muitas formas, como por exemplo, fazendo com que um usuário precise ir até
uma fase específica para liberar um recurso de outra fase. O uso da arquitetura proposta
permite um número infinito de fases, tendo cada fase seus próprios desafios.
Como desafio do módulo, pode ser pedido que os etsudantes criem uma nova fase
e um novo personagem. Com isso, terão acesso aos dois padrões usados e maior
percepção de como fazer com que o jogo “cresça” usando a arquitetura definida.
6.5.5 Resultados
As atividades finais deste módulo estão sendo desenvolvidas no momento da
escrita deste trabalho e só estarão disponíveis a partir do dia 12 de Dezembro.
Entretanto, seguem alguns dos resultados e dificuldades da metodologia
observados até o momento:
170 / 227
•
Passagem para o NetBeans: Pelo menos 5 estudantes de uma turma de 24
comentaram que estavam perdidos com o NetBeans e achavam mais fácil o BlueJ.
A percepção do autor é que a facilidade do BlueJ está na organização espacial das
classes ao invés de uma lista no canto esquerdo da tela. Outro comentário de dois
alunos foi que sentiram falta dos “blocos coloridos” que o BlueJ usa para separar
cada nível do código. Por exemplo, todo o bloco de um método tem uma cor, se
dentro existe um bloco “if” ou “while”, este bloco contém uma cor específica.
•
Dificuldade com a classe “CenaComColisao”: Por ser um pouco mais complexa
e existir pouca documentação disponível, vários alunos precisaram de orientação
para usar a classe “CenaComColisao”, mais complexa que as demais;
•
Colisão com animação: Os alunos frequentemente queria saber se era possível
ver se uma animação possuía colisão com outra, sem perceber que para colisões,
precisariam usar uma animação como variável de uma classe “Retangulo”. A
estratégia de uso de animações com Retângulos por trás para simular as colisões
precisou ser explicada;
•
Bugs Aljava: A classe “CenaComColisao” contém a maior complexidade do Aljava
pois realiza a colisão de um grande número de objetos como cenário. Esta classe
apresentou alguns problemas conforme a complexidade dos trabalhos dos
estudantes estão aumentando. Ficou claro que os estudantes não se importam
muito se existirem limitações no uso das classes, mas é muito importante que as
limitações estejam claras, como por exemplo, qual o tamanho máximo de um
“Retângulo” para que seja verificada colisão deste com o cenário.
O resultado conforme o trabalho dos estudantes só estará disponível a partir
de 12 de dezembro, quando este documento será ampliado.
6.6 Módulo 5 – Frameworks
Todas as experiências profissionais do autor deste trabalho envolveram o uso de
“frameworks”, fosse para internet ou “desktop”. O desenvolvimento nos dias atuais é
fortemente baseado no uso de “frameworks” e de padrões formalizados através de
classes abstratas. Esta seção apresenta o conceito de “frameworks” e o respectivo uso de
classes abstratas e interfaces para que o estudante se familiarize com esta realidade.
Carga horária teórica 8 horas/aula
171 / 227
Carga horária prática 12 horas/aula
Produto Final
Um jogo com pelo menos 12 classes distribuídas em fases,
objetos do jogo e classes auxiliares utilizando como base o
framework oferecido.
COO
Interfaces;
Classes
abstratas;
Polimorfismo:
Variáveis
polimórficas / Polimorfismo de método;
CP
Fortalecimento anteriores;
CFA
Classes base para o framework.
CLJ
Fortalecimento anteriores;
Ambiente de
Programação
NetBeans
6.6.1 Frameworks
“Frameworks” constituem uma abordagem de desenvolvimento que visa maximizar
o reuso de software (Silva), portanto, uma empresa que desenvolve jogos para a internet
pode ter um “framework” específico para o desenvolvimento de jogos para a internet, e o
mesmo ocorre para “sites”, sistemas web, dispositivos Android, etc.
Em Orientação a Objetos um “framework” consiste em em conjunto de classes que
incorpora um projeto abstrato que soluciona uma família de problemas relacionados.
Até agora, usamos as classes do Aljava como se fossem classes de biblioteca.
Para que um conjunto de classes seja considerado um “framework” efetivamente, deve
incorporar um “projeto abstrato”, ou seja, indica parcialmente como deve estar organizada
a arquitetura base de um código.
Foi construído no módulo quatro um padrão para o desenvolvimento de jogos com
várias fases e objetos. Neste módulo iremos formalizar o padrão anterior com recursos
específicos de Orientação a Objetos e usar uma classe “Motor” que se encarregará das
trocas de fases e da execução do “loop” do jogo.
6.6.2 Classe Motor e Ciclo de Vida
Quando trabalhamos com “frameworks”, colocamos o controle do ciclo de execução
geral da aplicação aos cuidados deste “framework”. No módulo quatro, todo o código que
172 / 227
controlava o fluxo da aplicação foi construído. Isso pode ser visto nos métodos que
implementam o “loop” do jogo. Cada fase tem a sua própria estrutura de repetição e o
respectivo código necessário para interromper o “loop” e poder chamar uma próxima fase.
Para facilitar este trabalho, foi construída uma classe “Motor” que tem como
responsabilidade controlar o fluxo principal de um jogo. Isto envolve 1) Guardar as fases
disponíveis (antigo papel da classe GerenciadorFases do módulo 4); 2) executar o “loop”
principal do jogo e 3) Controlar o número de quadros por segundo de exibição do jogo.
O fluxo de controle da classe “Motor” está contido no método “executa()” e possui a
seguinte estrutura:
1. Verifica se existe uma fase atual definida
1. Em caso negativo, exibe uma mensagem de erro;
2. Executa o método “inicia()” da fase atual;
2. Inicia o “loop” do jogo;
3. Verifica se passou tempo suficiente para a execução do jogo e em caso
negativo, passa para a próxima iteração do “loop” (passo 2);
4. Executa em sequencia: 1) o método “processa()” da fase atual; 2) o método
“desenha()” da fase atual e 3) exibe o desenho com o método
“Alj.tela.exibe()”;
5. Verifica se existe uma próxima fase:
1. Em caso positivo, executa o método “inicia()” da próxima fase, passa a
próxima fase como referência para a a variável que armazena a fase
atual e por fim, passa a variável que aponta para a próxima fase para
“null”, de modo a prosseguir na execução do ciclo de vida do jogo;
2. Em caso negativo, apenas segue novamente para o passo dois e segue
a execução do “loop” do jogo.
Este ciclo de vida pode ser mostrado aos estudantes utilizando o próprio código da
classe “Motor” que foi preparado justamente para que os alunos tenham algum
entendimento sobre o que significa e como age uma classe que detém o controle da
aplicação.
173 / 227
Esta demonstração é importante também como preparação para a explicação de
classes interfaces já que o tipo das variáveis “faseAtual” e “proximaFase” são do tipo
“Fase”, uma interface desenvolvida especificamente para dar suporte ao motor do jogo.
public void executa() {
//Passo 1
if(faseAtual == null) {
Alj.tela.exibeMensagem("Fase atual não definida no Motor.");
Alj.tela.finaliza();
}
faseAtual.inicia();
//Passo 2
motorEmExecucao = true;
while(motorEmExecucao) {
//Passo 3
if(!podeExecutarProximoFrame()){
continue;
}
//Passo 4
faseAtual.processa();
faseAtual.desenha();
Alj.tela.exibe();
//Passo 5
if(proximaFase != null) {
proximaFase.inicia();
faseAtual = proximaFase;
proximaFase = null;
}
}
}
Em cursos onde os estudantes tenham também conhecimento sobre outros focos
como “software desktop” ou “softwares web” pode ser dada uma breve explicação sobre
como funcionam “frameworks” dessa área.
6.6.2 Classes Interfaces
Conforme visto no capítulo anterior, o ciclo de vida do “framework” exige que cada
174 / 227
fase tenha três métodos distintos:
1. processa(): Que executa a lógica de processamento de um quadro da fase;
2. desenha(): Que desenha todos os objetos de um quadro da fase;
3. inicia(): Que é executado sempre antes do primeiro quadro da fase ser executado.
Isso representa um problema, é preciso garantir que todas as fases tenham estes
três métodos e estes três métodos devem ser reconhecidos por um tipo, afinal, as
variáveis que representam fases dentro da classe “Motor” precisam de um tipo.
Não é possível dizer que as variáveis “faseAtual” e “proximaFase” serão do tipo
“Object” pois a classe “Object” não possui nenhum dos três métodos informados. Nem
podemos dizer que são do tipo “Fase1” pois isso não garantiria que objetos da classe
“Fase2” teriam os mesmos métodos.
Uma das formas de resolver este problema é criando uma classe Fase com estes
três métodos vazios e usando-a como superclasse para cada fase do jogo como no
exemplo das ilustrações abaixo :
Ilustração 60: Exemplo de sobrescrita do
método inicia da classe Fase
Ilustração 59: Exemplo de classe
Fase com os três métodos vazios
Esta técnica funciona para o problema apresentado, porém, pode levar o
programador a erros, como por exemplo: 1) criar objetos da casse Fase e 2) esquecer de
implementar algum dos métodos definidos na interface.
Nenhum dos dois problemas apresentados resultariam em erros no software,
175 / 227
porém, existe uma estrutura mais apropriada para estes casos chamada “Interface”. Em
Java, uma interface é uma especificação de um tipo na forma de um nome e um
conjunto de métodos que não define nenhuma implementação para os métodos (Barnes).
Isso significa que o uso de Interfaces é excelente quando é preciso definir um tipo
para usar em nossos projetos, sem precisar implementar qualquer um dos métodos.
Quando usamos interface deixamos claro para quem for criar objetos deste tipo que ele
deverá implementar um determinado conjunto de métodos.
Criar Interfaces é simples, basta usar a palavra-chave “interface” no lugar de “class”
e omitir o corpo dos métodos, apenas finalizando-os com um “;”.
public interface Fase {
public void processa();
public void desenha();
public void inicia();
}
Agora, quando uma classe quiser usar uma interface, dizemos que esta classe
“implementa” uma determinada interface e não mais “estende”. Outra das vantagens de
uma interface é que qualquer ferramenta computacional pode inferir que uma classe que
implementa uma certa interface deve obrigatoriamente implementar os métodos definidos
nesta interface, com isso, ambientes de desenvolvimento como o NetBeans auxiliam o
trabalho de implementação destes métodos exibindo mensagens de erro e operações de
atalho, conforme pode ser observado nas ilustrações abaixo.
Ilustração 61: NetBeans sugerindo implementar os
métodos abstratos
Métodos sem implementação são chamados de métodos “abstratos”. Métodos com
implementação são chamados de métodos “concretos”.
176 / 227
Ilustração 62: Métodos criados pelo NetBeans após clicar na sugestão de implementar os
métodos abstratos
Agora que já conhecemos a interface “Fase” podemos implementá-la nas fases do
jogo “A Aventura do Quadrado”. É essencial que os estudantes agora percebam que a
arquitetura mudou e que a responsabilidade agora pelo “loop” principal do jogo pertence
ao objeto da classe “Motor”.
As principais mudanças que ocorrem com a implementação da interface fase são:
•
método desenha passa para público ao invés de privado;
•
as operações executadas antes de iniciar a estrutura de repetição “while”
dentro do método “loop” migram para o método “inicia()”;
•
o método “loop” pode ser renomeado para “processa” e a estrutura de
repetição “while” pode ser removida bem como o código posterior que guia
para uma próxima fase;
•
O método “proximaFase” pode continuar existindo normalmente e pode
passar a ser chamado de qualquer lugar do método processa().
Segue abaixo um exemplo destes três métodos implementados para a fase 1 (o
método desenha não foi exibido pois não sofre nenhuma alteração).
177 / 227
public void inicia(){
//Garante que a tela, nesta fase, tenha sempre este tamanho
Alj.inicializa(288, 288);
//Garante que o personagem
//começará no início da fase
q.alteraX(40);
q.alteraY(40);
}
public void processa(){
q.processaMovimento();
q.processa();
saltitador.processa();
fase1.processa();
camera.processa();
processaColisoes();
//processaVitoria
if(q.pegaX() >= 288){
Alj.tela.exibeMensagem("Você venceu. Boa sorte no próximo
estágio.");
proximaFase( 0 );
}
//processaDerrota
if(q.estaMorto()){
Alj.tela.exibeMensagem("Você perdeu. Tente de novo.");
proximaFase( 1 );
}
}
O processo de transformação das classes do modo anterior para com a interface
implementada pode ser feito em paralelo com eles realizando o mesmo processo. O
professor pode neste momento ressaltar como o código novo ficou muito mais simples e
falar da importância de planejar uma boa arquitetura antes de iniciar o desenvolvimento. E
que justamente este é um dos motivos para o uso de “frameworks”, pois eles definem
uma arquitetura geralmente testada e utilizada amplamente.
178 / 227
Antes de avançar, ressalta-se que para fortalecer a explicação, pode ser
demonstrado o funcionamento da classe “MouseObserver” que implementa diversas
interfaces para capturar os movimentos do mouse. Se for um objetivo do curso, neste
ponto os estudantes já tem condições de serem apresentados ao padrão “observer” e ao
uso de “Jframe” com classes que implementam interfaces para mouse e teclado.
Com o conceito de interface explicado e as classes reorganizadas, podemos
demonstrar agora com mais clareza como ficará o método “main” utilizando o “framework”
e o quanto as mudanças feitas afetarão o método de troca de fases.
6.6.3 Troca de fases e o método “main”
Aproveitando que neste momento estamos trabalhando nas classes das fases,
vamos começar pela troca de fases. Antes fazíamos esta tarefa executando o método
“loop()” de uma fase. Agora, esta responsabilidade é do “framework”, sendo necessário
apenas informar qual a próxima fase.
No nosso “framework”, o responsável pela lógica central do jogo é um objeto da
classe “Motor” e assim como colocado no problema de compartilhamento de objetos no
módulo 4, deve existir apenas um único objeto desta classe em todo o software.
Uma das formas de fazermos isso seria, assim como feito com o objeto da classe
“SenhorQ”, passá-lo como parâmetro para cada uma das fases. Como é somente um
objeto esta seria uma solução possível. Porém, aproveitaremos este problema para
demosntrar uma forma de resolvê-lo amplamente utilizada na computação e conhecido
como “Design Pattern Singleton”.
Um “design pattern”, ou simplesmente “padrão de projeto” é uma forma de resolver
um problema de projeto, no nosso caso, projeto de software. Neste caso o problema é “ter
acesso a um único objeto de uma classe em qualquer ponto da aplicação”.
Este padrão usa uma variável e um método estático. A variável estática armazena o
objeto e o método estático retorna este objeto sempre que executado. A implemantação
deste padrão pode ser observada na classe “MotorSingleton” do aljava.
179 / 227
public class MotorSingleton {
private static Motor instancia = null;
public static Motor pegaInstancia() {
if(instancia == null) {
instancia = new Motor();
}
return instancia;
}
}
Agora, sempre que for necessário recuperar o objeto motor basta executar
“MotorSingleton.pegaInstancia()”. Podemos ver isso no método “main” onde recuperamos
o objeto, adicionamos todas as quatro fases, informamos a fase inicial e executamos o
motor.
public static void main(String[] args) {
...
//Passo 1 – Recupera objeto motor
Motor motorJogo = MotorSingleton.pegaInstancia();
//Passo 2 - Adiciona as fases existentes,
//todas implementando a interface Fase
motorJogo.adicionaFase("telaInicial", t);
motorJogo.adicionaFase("fase1", f);
motorJogo.adicionaFase("fase2", f2);
motorJogo.adicionaFase("faseChefao", c);
//Passo 3 - Define fase inicial através da chave
motorJogo.defineFaseInicial("telaInicial");
//Passo 4 - Executa o motor
motorJogo.executa();
}
180 / 227
Para mudar de fase, basta chamar o método “defineProximaFase(String chave)” do
objeto motor informando a chave da fase que deve ser executada em seguida. Como já
foi visto como recuperar um objeto da classe motor, pode ser demonstrado o código que
realiza a troca de fase:
Motor motorJogo = MotorSingleton.pegaInstancia();
motorJogo.defineProximaFase("fase2");
Esta é uma boa situação para demonstrar também o “uso da notação” para
chamada de métodos de forma encadeada.
MotorSingleton.pegaInstancia().defineProximaFase("telaInicial");
Esta última demonstração em geral causa surpresa aos estudantes e portanto, é
importante demonstrar que ao executar o método “pegaInstancia()” ele retornou um a
referência para um objeto da classe Fase, e que podemos tanto guardar essa referência
em uma variável quanto executar imediatamente algum código do objeto para o qual a
referência aponta. Com isto fechamos a transformação do “A Aventura do Quadrado” para
o uso da nova arquitetura.
6.6.4 Classes Abstratas
Outro padrão que foi documento foram os objetos de jogo, que continham dois
métodos, um para desenhar e outro para processar a lógica interna. Este padrão também
poderia ser formalizado com uma “interface”. Uma das vantagens desta formalização é
que poderíamos ter em cada fase uma lista de objetos de jogo, e, para desenhar os
objetos, apenas executaríamos o método desenha de cada objeto da lista. A vantagem
desta abordagem é que ao adicionar novos objetos ao jogo, poderíamos somente
adicioná-los na lista. Veja nas ilustrações abaixo este exemplo aplicado para a fase 2.
181 / 227
Ilustração 64: Implementação da Interface
"ObjetoJogo" por um dos objetos do jogo
Ilustração 63: Exemplo de uso de
uma interface ObjetoJogo
Repare no exemplo que uma classe pode estender uma classe e implementar uma
outra interface, aliás, uma classe pode implementar quantas interfaces desejar.
Esta abordagem é correta, porém, em muitos casos, como este, temos um padrão
que contém métodos abstratos (que devem ser implementados pelas classes filha) mas
que também poderia conter outros métodos que serviriam para todos que estendessem a
classe.
Com este próprio exemplo, a classe “ObjetoJogo” poderia ter métodos que
informassem se o objeto está “vivo”, ou seja, se ele se mantém aparecendo na tela.
Dessa forma, precisaríamos que a classe “ObjetoJogo” contivesse métodos tanto
abstratos (desenha e processa) quanto concretos (estaMorto, morre).
Em Orientação a Objetos isto é possível e pode ser implementado com o uso de
classes abstratas. Uma classe Abstrata é uma classe que não foi concebida para criar
instâncias. Seu propósito é servir como superclasse para outras classes. As classes
abstratas podem conter método abstratos (Barnes) e concretos. Criar uma classe abstrata
é simples e exige apenas o uso da palavra “abstract” logo antes da palavra-chave “class”.
Ao definir uma classe como abstrata o efeito imediato é que nenhuma instância poderá
ser criada e ela só poderá ser usada via herança.
Repare na ilustração 55 que uma classe abstrata pode conter qualquer elemento de
classes concretas e também métodos abstratos. Para que outra classe possa utilizar esta
classe ela deverá fazer herança. O problema com isto é nossos objetos já estendem a
classe “Retangulo” ou “RetanguloGravidade” e em Java, não é possível a realização de
herança múltipla, ou seja, de mais de uma classe.
182 / 227
Ilustração 65: Exemplo da classe abstrata
"ObjetoJogo"
Esta questão pode ser resolvida dizendo que a classe “ObjetoJogo” estende a
classe “Retangulo”, isto faz sentido pois como já vimos no módulo quatro, um objeto de
jogo sempre pode ser representado na tela por um retângulo. Esta técnica traria o
problema de que as classes que estendem “RetanguloGravidade” não poderiam ser
objetos da classe “ObjetoJogo”, como “RetanguloGravidade” também é um “Retangulo”,
a classe “ObjetoJogo” pode estender a classe “RetanguloJogo”.
Ilustração 66: Classe abstrata "ObjetoJogo" estendendo a classe
"RetanguloGravidade"
Esta abordagem tem a vantagem de nos permitir adicionar diversos
183 / 227
comportamentos aos objetos do jogo, mas garantindo que a classe só será usada como
superclasse.
Da forma como fizemos até agora, tanto o método “processa()” da classe
“RetanguloGravidade()” como o método “desenha()” da classe “Retangulo()” são perdidos.
Uma forma de mantê-los é criar outros métodos que os encapsulam e os disponibilizam
sobre outros nomes, como demonstrado na ilustração abaixo:
Ilustração 67: Métodos que encapsulam
os métodos "processa" e "desenha" da
superclasse
Agora, basta fazer com esta classe seja estendida pelos objetos do jogo e realizar
as modificações necessárias, que consistem basicamente em chamar os dois métodos
apresentados na ilustração acima quando necessário.
Esta seção apresentou o uso de classes abstratas com um exemplo bastante
complexo que utiliza estas classes em conjunto com herança. De modo a fortalecê-lo,
veremos este conceito novamente na seção abaixo, junto com o conceito de polimorfismo.
6.6.5 Polimorfismo
Polimorfismo é a capacidade de um objeto poder ser referenciado de várias formas.
Isso significa que um objeto pode em um determinado momento ser referenciado como
pertencente ao tipo “Retangulo” ou “ObjetoJogo”. Isso é possível porque um objeto pode,
em função da hierarquia de herança e das interfaces que implementa, ser um
representante válido de diversos tipos.
Consideremos um objeto da classe “SenhorQ”, poderíamos armazenar objetos
desta classe em variáveis do tipo: “SenhorQ”, “ObjetoJogo”, “RetanguloGravidade” e
“Retangulo”. Porém, se armazenássemos um objeto desta classe em uma variável do tipo
“Retangulo” poderíamos executar apenas os métodos da classe “Retangulo”, e assim com
todas as demais.
184 / 227
Ilustração 68: Exemplo
de Hierarquia de
Herança na classe
"SenhorQ"
Porém, se tivermos diversas classes que fazem extensão do mesmo tipo, podemos
usar este tipo para fazer uma lista de objetos desta classe. Para verificar este exemplo,
usaremos a ideia de ter itens especiais no Jogo que, quando pegos pelo “SenhorQ”
realizam alguma ação como aumentar o seu tamanho, recuperar a vida ou a forca do
pulo.
Primeiro, temos um padrão para o ítem, existe um método abstrato que deverá ser
executado toda vez que um ítem colidir com o “SenhorQ”. Segue abaixo o código da
classe abstrata representando ítens.
185 / 227
public abstract class Item extends ObjetoJogo {
public Item(){
x = Alj.util.sorteia(100, 500);
y = Alj.util.sorteia(100, 300);
largura = 32;
altura = 32;
}
public abstract void executaAcao(SenhorQ q);
public void processa() {
if(!estaVivo()){
ressucita();
//Sorteia uma nova posição para o objeto
alteraX( Alj.util.sorteia(100, 500) );
alteraY( Alj.util.sorteia(100, 300) );
}
}
}
E para a demonstração, criaremos dois itens, um com efeito de recuperar a vida do
jogador e outro que deixa o pulo mais fraco. segue código de ambas as classes.
Ilustração 69: Classe que representa um item de
cura
Ilustração 70: Classe que representa um item
que diminui a forca do Pulo
Estes itens serão incluídos na fase final. Se não pudéssemos utilizar polimorfismo
teríamos que fazer uma lista para os itens de cura e uma lista separada para os itens que
fazem com que o personagem perca força do pulo.
Usando polimorfismo, podemos colocar ambos os tipos de itens em uma lista de
186 / 227
objetos do tipo Item e percorrer esta lista para executar os métodos de processamento,
desenho que realizam uma ação quando entram em colisão com o “SenhorQ”.
Observem que o método “toca” da classe “Retangulo” só aceita outros retângulos
como parâmetro, portanto, nós já utilizamos polimorfismo desde o módulo três.
public class FaseChefao implements Fase {
...
ArrayList<Item> itens;
public FaseChefao(SenhorQ senhorq){
...
itens = new ArrayList<Item>();
itens.add( new Remedio() );
itens.add( new Remedio() );
itens.add( new PerdePulo() );
itens.add( new PerdePulo() );
for(Item i : itens){
cenario.moveComCenario(i);
}
}
...
public void processa(){
...
for(Item i : itens){
i.processa();
if(i.toca(q)){
i.executaAcao(q);
}
}
...
}
...
Conforme pode ser visto na execução da fase, os itens demonstrados aqui não são
muito interessantes, de modo que este módulo pode ser encerrado com o desafio da
criação de diversos itens diferentes e inclusão destes itens nas diferentes fases.
187 / 227
Ilustração 71: Exemplo da fase final contendo os itens
implementados
Outro potencial para o uso de polimorfismo e classes abstratas é fazer uma classe
abstrata Inimigo da qual todos os inimigos estendem, e, assim como com os itens, criar
listas de Inimigos nas fases.
Tanto os itens quanto os inimigos abrem a possibilidade para que se crie uma
classe fase que já processa e desenha todos os inimigos, diminuindo ainda mais a
complexidade das fases das classes filha e demonstrando como a arquitetura do software
pode ir se transformando com ele e permitindo a criação ainda mais rápida de fases e
objetos mais complexos.
Vale deixar claro que este é um dos maiores desafios da programação orientada a
objetos, planejar arquiteturas de software escaláveis e de fácil compreensão pelos
programadores, a fim de facilitar a posterior manutenção de código.
O código completo de todas as classes do jogo “A Aventura do Quadrado” é muito
extenso para ser disponibilizado no corpo deste documento ou mesmo nos anexos. Deste
modo, foi disponibilizado para download através da URL http://goo.gl/2rlpc.
6.6.6 Resultados
Este módulo foi baseado na versão do curso aplicada no primeiro semestre de
2012 e documentada no capítulo 3 deste documento.
De forma geral observou-se que os estudantes compreendiam os conceitos de
classes abstratas e interfaces, conseguindo bons resultados em avaliações teóricas e
conseguindo utilizar com facilidade as classes do “framework”. Entretanto, tiveram muita
dificuldade em identificar nos seus projetos possibilidades para a criação de novas
classes abstratas e interfaces.
188 / 227
Apesar do código do projeto final deste módulo ser relativamente complexo,
percebeu-se que grande parte dos estudantes conseguiram desenvolver bons projetos e
replicar as técnicas utilizadas com sucesso.
6.7 Limitações da Metodologia Apresentada
Alguns tópicos não foram tratados nos módulos apresentados em função da
restrição de prazo para este trabalho, mas que poderiam estar perfeitamente incluídos a
partir de mais exercícios dentro dos módulos existentes ou mesmo de novos módulos.
As duas principais restrições foram as estruturas Enum e o Tratamento de Exceção.
Ambos porém, foram trabalhados na primeira versão do curso de Orientação a Objetos
baseada em jogos conforme documentada na seção 3 deste documento.
A linguagem Java também teve baixa cobertura por não ser este o foco do presente
trabalho.
189 / 227
7 Conclusão
Nada é tão fácil a ponto de ser óbvio nem tão difícil a ponto de ser impossível.
Programar usando o paradigma orientado a objetos é sem sombra de dúvida altamente
complexo. Foi surpreendente perceber que questões aparentemente óbvias para o autor
deste trabalho levavam dias para serem compreendidas por alguns estudantes.
A capacidade de pensamento abstrato e de construção de modelos mentais, tão
necessárias para a programação neste paradigma não são naturais do ser humano, ou
pelo menos não são habilidades naturalmente desenvolvidas. É certo que alguns
estudantes simplesmente se saem muito melhor do que outros, mas mesmo estes,
precisam de orientação total quanto aos conceitos e respectivas implementações. Em
nenhum momento encontrei estudantes que simplesmente conseguiam inferir o uso dos
recursos. Os que se saiam melhor, em geral, praticavam mais programação fora do
horário de aula. Os alunos excepcionais, tinham no mínimo, uma ou duas horas de
programação por dia, por vontade própria, em casa.
O apelo de que programação orientada a objetos é mais semelhante a forma como
pensamos, parece ao autor deste trabalho, um equívoco. Sendo o tipo de pensamento
usado nesta arte uma habilidade que precisa ser adquirida, assim como qualquer técnica.
Por não ser natural é essencial que o professor instrutor dessa área não caia na
tentação de querer que os estudantes aprendam simplesmente “observando” como um
código funciona. É preciso ir além, construir conexões na mente do estudante dos
conceitos vistos com elementos já bem estabelecidos no seu aprendizado de
vida(metáfora consistente), usar representações visuais sempre que houver a explicação
de questões abstratas e apresentar ao menos parcialmente como que o computador
funciona para que alguns recursos pareçam minimamente mais concretos, como por
exemplo, o armazenamento de objetos na memória do Java.
A partir destas observações destaca-se que para um aprendizado de alta qualidade
é essencial a preocupação do instrutor com 1) Motivação dos estudantes; 2) Método de
190 / 227
Ensino e 3) Elementos pedagógicos de apoio.
A motivação é essencial pois a fixação das regras de sintaxe e dos conceitos de
Orientação a Objetos exigem repetição. Com frequência os alunos esqueciam conceitos
menos de duas semanas após os termos utilizado. Parte disso é a causa da alta
exigência de carga horária prática em sala de aula com o uso desta metodologia. O
estudante precisa programar o máximo possível, e para isso, ele realmente precisa estar
motivado.
O método se torna cada vez mais necessário na medida que o número de
conceitos que são trabalhados é absolutamente alto. Foi percebido com a aplicação da
metodologia que ao mesmo tempo são transmitidos aos estudantes conceitos de
modelagem, de orientação a objetos, de lógica de programação e da linguagem Java.
Sem um método claramente definido e documentado, é altamente provável que o
professor se perca, não conseguindo realizar as conexões necessárias entre os
conteúdos e muito menos a elaboração de materiais didáticos de apoio e reforço.
Estes elementos pedagógicos se mostraram altamente essenciais. Por elementos
pedagógicos entende-se exercícios de fixação, avaliações, tabelas de resumo dos
conteúdos, atividades lúdicas para associação dos conceitos, etc. Estes elementos só
podem ser preparados com qualidade se existe um método bem definido no qual eles
estejam apoiados. Poderiam também, serem pensados elementos de apoio pedagógico
específicos para o ensino de computação e do “pensamento computacional”.
Verificou-se que o presente trabalho conseguiu atingir plenamente a questão da
motivação, trazendo para o mundo da programação alunos com baixo interesse na
disciplina. Quanto o método, ainda seriam necessários diversos ajustes para incluir alguns
conceitos e melhorar alguns dos exemplos propostos. Porém, quanto aos elementos
pedagógicos, este trabalho só os atendeu muito brevemente, fornecendo a documentação
do aljava. O autor considera que seria essencial o uso de mais elementos avaliativos,
assim como documentado na seção 3 e mais elementos de apoio aos estudantes como
resumos e atividades extras de fixação.
Para melhor detalhamento das conclusões deste trabalho são revisados os
objetivos propostos inicialmente, a influência de cada uma das dez diretrizes na
metodologia final e finalmente, descritos os aprendizados gerais proporcionados pela
excepcional experiência de construir softwares com adolescentes.
191 / 227
7.1 Revisão dos Objetivos propostos
Verifica-se que claramente o objetivo principal foi atingido, a metodologia proposta
está altamente detalhada, trabalha essencialmente com conceitos de Orientação a
Objetos e utiliza como elemento para os exemplos, o desenvolvimento de jogos.
Agora, segue análise de cada um dos objetivos específicos.
•
Objetivo específico 1: Apresentar e analisar algumas das principais metodologias
de ensino de programação orientada a objetos ressaltando seus pontos fortes e
fracos segundo a experiência do autor;
Sem dúvida a análise das cinco metodologias descritas na seção 4 atendem a este
objetivo. Vale ressaltar que cada autor contribui com alguma questão fundamental do
método usado, de forma resumida.
Boratti é excelente no uso de representações visuais conectadas com a memória
do computador para auxiliar o entendimento dos conceitos, com simplicidade, mas sem
ser simplista, suas representações vão ficando marcadas na memória e ajudam a difícil
meta de “enxergar os objetos”. Lembra-se que o autor do seu TCC teve o primeiro contato
com esta disciplina através das aulas de Boratti e recorda até hoje diversos aprendizados
obtidos. Como ponto negativo havia o início pelo método “main” que foi solucionando com
o uso do BlueJ.
Barnes e Köling são impecáveis ao transformar as aulas de Orientação a Objetos
em verdadeiras aulas de desenvolvimento de software. A apresentação de conceitos a
medida que os problemas surgem foi um dos principais guias deste trabalho, assim como
o ganho de poder começar a ensinar falando de objetos, através do software BlueJ. Como
ponto negativo, estava o uso excessivo do BlueJ, modificado neste método por uma
passagem para o NetBeans a partir do módulo 3.
Feijó é o responsável por fazer crer ser possível iniciar um curso utilizando um
“framework” de apoio. Após a aplicação de sua metodologia, ficou claro que o uso de
bibliotecas e “frameworks” são fatores essenciais para aumentar a motivação e quando
usados com a devida atenção e orientação, não causam mais dificuldades aos
programadores novatos. O ponto negativo do que trazia era apenas a falta deum método
mais detalhado, também resolvido nesta proposta.
Xinogalos ensinou a arte de detalhar, de revisar um método até encontrar um
192 / 227
modelo perfeito. Além disso, trouxe uma excelente organização dos ambientes de
desenvolvimento e a sugestão de transição para um ambiente profissional o quanto antes.
Em função de quatro anos de revisão e reformulação do seu curso, não foram
encontrados pontos fracos no seu método.
Por fim, Caspersen, com a metodologia mais recente de todas, fala de aprender e
programar orientado ao modelo do projeto. Pensar antes, projetar antes de codificar, e a
partir dos projetos, perceber os padrões que se repetem. Por fim, contribui também de
forma excelente com a ideia de trazer aos estudantes métodos sistemáticos de
programação. Com a documentação oferecida, também não foi possível encontrar pontos
fracos.
•
Objetivo específico 2: Definir diretrizes para o desenvolvimento da metodologia a
partir das metodologias estudadas e da experiência anterior do autor;
Este objetivo também foi atendido conforme documentado na seção 4.2. Na seção
posterior cada diretriz é avaliada individualmente.
•
Objetivo específico 3: Elencar elementos pedagógicos que auxiliem a construção
da metodologia;
Aqui o método sem sombra de dúvida deixou a desejar. Apesar dos “Padrões
pedagógicos” terem sido amplamente utilizados, eles não são suficientes para grantir um
aprendizado adequado. É essencial o uso de mais recursos, principalmente materiais de
consulta, resumo e exercícios de fixação.
•
Objetivo Específico 4: Construir um “framework” Orientado a Objetos que atenda
as principais características de jogos 2D e esteja de acordo com as diretrizes
definidas;
Uma das grandes questões é como construir códigos que executam algoritmos
complexos e troná-los simples de usar por estudantes novatos. Acredita-se que o trabalho
também atendeu a esta expectativa somente em função da experiência do autor com
técnicas de “Código Limpo”, na qual o código é escrito para ser o mais legível possível por
humanos. Esta técnicas não foram apresentadas no presente trabalho por limitação de
escopo.
•
Objetivo específico 5: Documentar uma metodologia que atenda a um curso
introdutório de programação orientada a objetos de 72 horas aula de modo a ser
193 / 227
facilmente replicada por qualquer professor de orientação a objetos;
Até o módulo 4, são 74 horas/aula sugeridas. Muito próximo ao valor desejado
inicialmente. Incluindo o módulo 5 alcança-se um total de 94 horas/aula. É importante
observar que a medida que os módulos ficam mais complexos é reservado um tempo
maior para carga horária prática da disciplina.
Os maiores aprendizados ocorriam, durante a aplicação da metodologia, não
quando os conceitos eram apresentados, mas quando os estudantes, no desejo de
criarem seus próprios jogos, conseguiam colocá-los em prática. E isto, para que o
estudante não desista facilmente, exige a presença constante do professor ou de colegas
que já tenham compreendido os mesmos conceitos.
A carga horária pode ser ajustada segundo diversos critérios. Em turmas de
graduação por exemplo, o tempo de atividades práticas pode ser reduzido pois os
estudantes tendem a ter maior iniciativa pessoal. Já em cursos técnicos de nível médio,
sugere-se aplicar menos módulos, mas usar muito tempo de programação com orientaçào
do professor.
7.2 As 10 diretrizes
Na seção 4.2 são sugeridas 10 diretrizes base usadas para a metodologia. Este
capítulo avalia o uso e a influência de cada uma delas.
7.2.1 Princípios baseados na prática com o BlueJ
Qualquer um que conheça o método de ensino usando o BlueJ verificará
imediatamente a mesma estrutura nos métodos do presente trabalho. O método guiado a
problemas e realizado em espiral apresenta os conceitos somente quando eles são
necessários e fazem sentido, e isto é essencial no ensino. Quando o estudante não vê
sentido em algo, não há aprendizado.
Ressalta-se apenas que exercícios repetitivos tradicionais, orientados à sintaxe,
poderiam contribuir muito para o aprendizado pois auxiliam a fixação de certas regras de
sintaxe, como o uso do “loop for”.
4.3.2 Representações visuais para todas as estruturas e conceitos
trabalhados
Pensar orientado a objetos não é natural, os estudantes precisam sim de
194 / 227
representações visuais para todos os novos conceitos. Quando mais consistentes e
diversas as representações visuais, maiores as chances do conceito ser assimilado e
gravado pelo estudante.
4.3.3 Operações de abstração e “framework” conceitual
Em muitos casos onde existiam possibilidades de uso destas duas questões, elas
foram muito pouco aproveitadas. Acredita-se que esta diretriz pode ser muito melhor
usada, principalmente nos módulos 4 e 5 quando a modelagem dos problemas ganha
complexidade.
4.3.4 Ambiente educacional + Ambiente profissional
Sem dúvida esta passagem é fundamental, mas precisa ser melhor estudada e
guiada. Também foi surpreendente notar a dificuldade da maioria dos estudantes com o
“NetBeans” após terem usado o “BlueJ”. A representação das classes como uma simples
lista os deixava bastante perdidos inicialmente. Além disso, eles não conseguem perceber
as vantagens de um ambiente profissional imediatamente, precisam ser apresentados a
eles.
A apresentação posterior do método mais também se mostrou relativamente
tranquila e ais fácil do que o processo oposto que é passar para classes após ter
trabalhado inicialmente no “main”.
4.3.5 Processo sistemático de desenvolvimento
O processo didático mais adotado em todo o método foi o “live coding”. Não só por
permitir bastante flexibilidade, este método vai, lentamente, dando confiança aos
estudantes por já terem visto, diversas vezes, como se começa a atacar um problema. O
uso do processo de modelagem antes de cada atividade também foi fundamental.
4.3.6 A partir do zero.
Apesar de quase sempre ao final de um métodos os estudantes serem desafiados
a construir seu próprio jogo. Praticamente todos iniciavam modificando os códigos
passados por exemplo. Essa diretriz não conseguiu ser plenamente atendida. Iniciar com
um projeto completamente em branco se mostrou complexo para todos os estudantes.
195 / 227
4.3.7 Recursos computacionais devem ter acesso fácil
O uso do framework “Aljava” atendeu este requisito plenamente. Alguns alunos se
interessavam em saber como que as mesmas coisas poderiam ser feitas em Java puro.
Recomenda-se que, existindo tempo para isso, seja demonstrado como realizar algumas
das operações do “framework” em Java puro.
4.3.8 Estilo de código-fonte
Do início ao fim da aplicação do método os estudantes ainda apresentavam
códigos com má identação apesar dos diversos avisos do professor e de todos os códigos
apresentados estarem bem formatados. Não foi possível identificar a causa disto.
4.3.9 Modelagens genéricas
Julgando pela diversidade dos projetos apresentados, sim, esta diretriz conseguiu
ser plenamente atendida.
4.3.10 Códigos e documentação na língua materna
Conforme elucidado, é realmente distante o acesso ao inglês para alguns
estudantes de 15 e 16 anos. Eventualmente, alguns começavam, por vontade própria a
construir seus códigos em inglês. Isso sempre foi motivado e incentivado, mas a cobrança
era por códigos em português. Seria necessário domínio fluente em inglês para o
processo de modelagem não ficasse prejudicado.
7.3 Outros Aprendizados
Além do observado nas seções anteriores, seguem alguns tópicos específicos de
aprendizados obtidos durante os três semestres de desenvolvimento deste trabalho.
7.3.1 Aplicações conectadas com a realidade do educando
Apesar do uso de jogos ter funcionado perfeitamente bem como elemento de
motivação. Muitos estudantes perguntavam como fazer softwares “de verdade”, como
sistemas para biblioteca. Outro pedido frequente era o desenvolvimento para dispositivos
móveis.
Isso levou a percepção de que o mais importante não eram os jogos, mas sim, que
os estudantes estavam trabalhando em algo que eles conheciam, que fazia parte da sua
196 / 227
realidade. Além disso, a turma demonstrava grande satisfação em poder gerar o
executável do jogo. Alguns chegaram a distribuir as suas criações para os amigos. Com
isso, ressaltam-se dois fatores para a escolha do tema usado no ensino de Orientação a
Objetos:
•
O tema deve fazer parte do cotidiano dos estudantes;
•
Deve ser possível desenvolver produtos completos, que efetivamente possam ser
utilizados.
7.3.2 Frameworks e bibliotecas como apoio ao desenvolvimento mesmo em
etapas iniciais
Linguagens de programação profissionais geralmente exigem um grande número
de conceitos para realizar operações simples como desenhar uma imagem na tela.
Verificou-se com este trabalho que o uso de bibliotecas de métodos e classes não
prejudicam em nada o aprendizado de orientação a objetos.
E “frameworks” apesar de não recomendados antes que se conheçam os conceitos
de lasse e herança, são excelentes em fases posteriores para aumentar a percepção da
necessidade de padrões, introduzir à arquitetura de software de demais recursos
avançados.
7.3.3 Modelagem é essencial
Conseguir transformar ideias em classes com seus respectivos métodos e variáveis
de objeto é uma tarefa de altíssima complexidade que precisa ser praticada
constantemente. Iniciar qualquer desenvolvimento sem uma breve atividade de análise é,
na experiência do autor, um grande equívoco que trará sem dúvida, prejuízos posteriores
ao software.
Ainda é preciso, porém, aumentar a qualidade do ensino de modelagem pois a
maioria dos estudantes não conseguia ao final da metodologia ir além dos exemplos
apresentados, e acabavam por desenvolver jogos com modelos semelhantes aos
exemplos.
7.4 Trabalhos Futuros
Após a identificação e elucidação de diversos pontos de metodologia, seguem
algumas possibilidades de trabalho futuro, ordenadas, segundo visão do autor, das mais
197 / 227
relevantes para as menos relevantes.
7.4.1 Compreensão do Pensamento Computacional e Abstrato
Foi perceptível que alguns estudantes simplesmente aprendiam muito mais rápido
do que os outros e foi incrível que, para alguns estudantes, parecia existir um momento
específico em que algo acontecia no seu entendimento e que a partir daquele dia, era
como se o estudante houvesse compreendido algo essencial que o fazia ser melhor em
todas as atividades.
Não foi possível sequer perceber que fatores eram estes que pareciam despertar
no estudante um entendimento superior e que abriam portas para diversos novos
conceitos.
Uma proposta de trabalho futuro é estudar em detalhes o processo de pensamento
abstrato e quais os fatores cognitivos que influenciam tão positivamente no processo de
aprendizado de programação.
7.4.2 Conexão com a pedagogia e produção de REA `s– Recursos
Educacionais Abertos
A partir de um método claramente definido e considerado pela sociedade de
qualidade, pode-se iniciar um processo de ampliação do método para incluir outros
elementos do processo de ensino-aprendizagem, e, a respectiva transformação destes
recursos em recursos educacionais abertos.
Outra possibilidade é que considerando o avanço dos cursos realizados a distância,
que a metodologia pudesse ser transformada para um formato de replicação em formato
de curso digital, inclusive nas formas de avaliação para as quais poderiam ser
desenvolvidos pequenos aplicativos ou mesmo plugins para o ambiente moodle,
específicos para o ensino de programação.
7.4.3 Uso abrangente da UML
Uma das ideias que surgiram durante o projeto foi o uso abrangente da UML para
as representações visuais das classes, objetos e suas relações. Após a finalização do
trabalho foi percebido pelo autor que os diagramas UML poderiam ser utilizados em
muitos contextos como forma de explicar certos conceitos aos estudantes. Isso é
interessante pois não haveria necessidade por exemplo, de uma aula sobre o que é um
“Diagrama de Atividades”, ele estaria presente na demonstração do ciclo de vida da
198 / 227
classe Motor, de modo que seu aprendizado seria absolutamente natural dentro do
contexto de um projeto de software. Outros exemplos poderiam ser:
•
Diagrama de Classes: Uso mais amplo de recursos como composição e
Agregação bem como o uso da sintaxe já correspondente ao definido na
UML;
•
Diagrama de Sequência: Demonstração da troca de mensagens entre
objetos no “loop” de uma determinada fase;
•
Diagrama de Máquina de Estados: Para explicação do uso dos métodos
para modificar o estado dos objetos e programar as regras de negócio para
realizar mudanças de estado consistentes.
7.4.4 Técnicas de documentação de software para estudantes novatos
Existem hoje, disponíveis em formato de código aberto, um grande número de
“frameworks” e bibliotecas que poderiam aumentar o potencial dos softwares
desenvolvidos em fases iniciais.
Estes recursos frequentemente ficam inacessíveis para jovens programadores em
função da precariedade da sua documentação;
Um possível trabalho seria o estudo de técnicas para documentação de bibliotecas
e “frameworks” que os tornassem compreensíveis para novatos em programação.
7.4.5 Ensino de POO Avançada com Android;
Muitos estudantes tinham alto interesse em desenvolver softwares para aplicativos
mobile. O autor considera que este tópico seria o auge da motivação para os estudantes.
Após um breve estudo do SDK Android, foi percebido que ele é inacessível em
fases iniciais, mas tem grande potencial para o ensino de recursos avançados como
arquitetura de software, classes abstratas e interfaces.
199 / 227
7.5 Considerações Finais
O presente trabalho trouxe diversos desafios. Mas o maior de todos e também o
mais recompensador é jamais desistir de ensinar.
Muitos estudantes apresentavam grande dificuldade e após diversos meses
conseguiam bons resultados. Muitos foram os momentos em que foi preciso repetir
individualmente os conteúdos apresentados.
Percebe-se que todo o esforço no sentido de clarear um conceito, de produzir uma
representação visual adequada, uma metáfora consistente ou um material de resumo, é
válido e auxilia muito o grupo de alunos que a princípio, não tem a habilidade natural para
a programação.
Neste sentido, em que todo o esforço é válido na tarefa de ensinar, acreditando
sempre no potencial de cada aluno, este trabalho teve amplo sucesso. Foram pelo menos
20 jogos produzidos nos dois semestres de desenvolvimento do método e mais dezenas
de classes, cada qual, com o jeito e um pouco do estilo de quem a criou.
Ver ideias ganhando vida, ver que com esforço, a inteligência e o talento de cada
estudante eram incorporados aos produtos desenvolvidos fez com que os três semestres
de desenvolvimento do presente trabalho, valessem toda a dedicação.
200 / 227
8 Bibliografia
8.1 Livros
Feijó, Bruno e Clua, Esteban. Introdução à ciência da computação com jogos: aprendendo a programar
com entretenimento. Rio de Janeiro. Elsevier, 2010.
BARNES, David J.; KOLLING, Michael. Programação Orientada a Objetos com Java: Uma introdução
prática usando o BlueJ. São Paulo: Pearson Prentice Hall, 2004. 368 pg.
KÖLLING, Michael. Introduction to Programming with Greenfoot: Object-Oriented Programming in Java
With Games and Simulations. Upper Saddle River, New Jersey: Prentice Hall, 2010. 190 p.
BORATTI, Isaias Camilo. Programação Orientada a Objetos com Java. Florianópolis: Visual Books, 2007.
308 p.
8.2 Artigos e Documentos acadêmicos
KAY, Alan. Dr. Alan Kay on the Meaning of “Object-Oriented Programming”. Email de 23 de julho de
2003. Disponível em: <http://www.purl.org/stefan_ram/pub/doc_kay_oop_en>. Acesso em: 24 jun. 2012.
PROULX, Viera K.(2010). Music in Introductory Object Oriented Programming: Music and sound library
for a novice Java programmer.. Constructionism 2010. Disponível em:
<http://www.ccs.neu.edu/home/vkp/Papers/Music-Constructionism2010.pdf>. Acesso em: 20 jun. 2012.
PROULX, Viera K. (2009).The Pedagogy of Program Design: Design Recipe throughout BOOTSTRAP,
TeachScheme!, ReachJava.. DIDINFO 2009. Disponível em:
<http://www.ccs.neu.edu/home/vkp/Papers/PPD-didinfo2009.pdf>. Acesso em: 20 jun. 2012.
PROULX, Viera K.(2003). Objects From the Beginning - With GUIs: Interactive GUI-based labs for
introducing objects first.. ITiCSE 2003. Disponível em: <http://www.ccs.neu.edu/home/vkp/Papers/GUIsiticse2002.pdf>. Acesso em: 20 jun. 2012.
CASPERSEN, M.E. e Christensen, H.B. (2008): CS1: Getting Started: Reflections on the Teaching of
Programming, LNCS 4821, Springer-Verlag, 2008, pp. 130-141.
BENNEDSEN, J.B. e Caspersen, M.E. (2008): Model-Driven Programming: Reflections on the Teaching of
Programming, LNCS 4821, Springer-Verlag, 2008, pp. 116-129.
201 / 227
KÖLLING, Michael e ROSENBERG, John. 2001. Guidelines for teaching object orientation with Java. In
Proceedings of the 6th annual conference on Innovation and technology in computer science education
(ITiCSE '01). ACM, New York, NY, USA, 33-36. DOI=10.1145/377435.377461
http://doi.acm.org/10.1145/377435.377461
XINOGALOS, Stelios (2009). Guidelines for Designing and Teaching an Effective Object-Oriented
Design and Programming Course, Advanced Learning, Raquel Hijn-Neira (Ed.), ISBN: 978-953-307-010-0,
InTech, Disponível em: http://www.intechopen.com/books/advanced-learning/guidelines-for-designing-andteaching-an-effective-object-oriented-design-and-programming-course. Acesso em 20 de junho de 2012.
M. Satratzemi, and S. Xinogalos, and V. Dagdidelis. An environment for teaching objectoriented programming: ObjectKarel. Proceedings of The 3rd IEEE International conference on
Advanced Learning Technologies (ICALT 03), 342--343.
THE PEDAGOGICAL PATTERNS PROJECT (Org.).Pedagogical Patterns. Disponível em:
<http://www.pedagogicalpatterns.org/>. Acesso em: 24 jun. 2012.
Clark, David; MacNish, Cara and Royle, Gordon F.. Java as a teaching language - opportunities, pitfalls
and solutions, in Proceedings of the Third Autralasian Conference on Computer Science Education, ACM,
Brisbane, Australia, July 1998.
8.3 Bibliografia para código-fonte e materiais didáticos
desenvolvidos pelo autor
CAMINHA, Kaléu. Exemplo 1: movimentando uma bola. Disponível em:
<https://github.com/kaleucaminha/javaPlay2Examples/tree/master/src/exemplo1>. Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Exemplo 2: um primeiro jogo com o framework javaPlay. Disponível em:
<https://github.com/kaleucaminha/javaPlay2Examples/tree/master/src/exemplo2>. Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Exemplo 3: jogo que acompanha o roteiro de 10 passos sobre o javaPlay. Disponível em:
<https://github.com/kaleucaminha/javaPlay2Examples/tree/master/src/exemplo3>. Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Guerra Espacial. Disponível em: <https://github.com/kaleucaminha/Guerra-Espacial>.
Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Exemplo Ryu: Etapa 1. Disponível em: <https://github.com/kaleucaminha/Ryu-VersusVegeta/tree/master/src/ryuversusvegeta_2>. Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Exemplo Ryu 2: Etapa 2. Disponível em: <https://github.com/kaleucaminha/Ryu-VersusVegeta/tree/master/src/ryuversusvegeta_3>. Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Exemplo Ryu vs Vegeta. Disponível em: <https://github.com/kaleucaminha/Ryu-VersusVegeta/tree/master/src/ryuversusvegeta_final>. Acesso em: 24 jun. 2012.
Material didático
202 / 227
CAMINHA, Kaléu. JavaPlay em 10 passos: Tutorial para desenvolvimento de um jogo simples utilizando o
framework javaPlay. Disponível em: <http://www.slideshare.net/kaleu/tutorial-1-javaplay-em-10-passos>.
Acesso em: 24 jun. 2012.
CAMINHA, Kaléu. Revisão Jogos 2D: Orientação a Objetos com Jogos 2D. Disponível em:
<http://www.slideshare.net/kaleu/conceitos-de-oo-aplicados-ao-desenvolvimento-de-jogos-2d>. Acesso em:
24 jun. 2012.
Provas
CAMINHA, Kaléu. Prova 2a. Disponível em: <http://www.slideshare.net/kaleu/prova-2a>. Acesso em: 24 jun.
2012.
CAMINHA, Kaléu. Prova 2b. Disponível em: <http://www.slideshare.net/kaleu/prova-2b-2012>. Acesso em:
24 jun. 2012.
CAMINHA, Kaléu. Prova 3b. Disponível em: <http://www.slideshare.net/kaleu/prova-3a-2012>. Acesso em:
24 jun. 2012.
CAMINHA, Kaléu. Prova 3b. Disponível em: <http://www.slideshare.net/kaleu/prova-3b>. Acesso em: 24 jun.
2012.
CAMINHA, Kaléu. Prova 4a. Disponível em: <http://www.slideshare.net/kaleu/prova-4>. Acesso em: 24 jun.
2012.
CAMINHA, Kaléu. Prova 4b. Disponível em: <http://www.slideshare.net/kaleu/prova-4b>. Acesso em: 24 jun.
2012.
CAMINHA, Kaléu. Prova de Revisão. Disponível em: <http://www.slideshare.net/kaleu/prova-de-reviso>.
Acesso em: 24 jun. 2012.
8.4 Bibliografia Consultada
Esta seção corresponde ao conjunto de materiais que não compõe o núcleo do
trabalho, mas que contribuíram, de forma menor, para a realização deste trabalho.
Java
ALVES, William Pereira. Java 2: Programação Multiplataforma. São Paulo: Érica, 2006. 286 p.
MECENAS, Ivan. Java 2 - Fundamentos, Swing e JDBC: Programação Multiplataforma. 2. ed. Rio de
Janeiro: Érica, 2006. 306 p.
DEITEL, Harvey; DEITEL, Paul. Java Como Programar. 6. ed. São Paulo: Pearson Prentice Hall, 2005.
1100 p.
203 / 227
HORSTMANN, Cay S.; L., Gary Cornell. Core Java: Volume I – Fundamentos. 7. ed. Rio de Janeiro: Alta
Books, 2005. 568 p.
HORSTMANN, Cay S.; L., Gary Cornell. Core Java: Volume II - Recursos Avançados. São Paulo:
Pearson Prentice Hall, 2003. 823 p.
Qualidade de Software
MARTIN, Robert C.. Código Limpo: Habilidades Práticas do Agile Software. São Paulo: Alta Books, 2009.
440 p.
KOSCIANSKI, André; SOARES, Michel Dos Santos. Qualidade de Software: Aprenda as metodologias e
técnicas mais modernas para o desenvolvimento de software. 2. ed. São Paulo: Novatec, 2007. 394 p.
204 / 227
9. Anexos
205 / 227
9.1 Anexo I - Classe Carro
import aljava.*;
class Carro {
int posicaoX;
int posicaoY;
int angulo;
String cor;
double quantGasolina;
boolean estaLigado;
char tipoVeiculo;
Carro(){
posicaoX = 20;
posicaoY = 50;
angulo = 0;
quantGasolina = 40.00;
estaLigado = false;
tipoVeiculo = 'e';
cor = "vermelho";
}
void andaFrente(){
posicaoX = posicaoX + 10;
angulo = 0;
//se andou, perde gasolina
quantGasolina -= 0.1;
}
void andaDireita(){
posicaoY = posicaoY + 10;
angulo = 90;
//se andou, perde gasolina
quantGasolina -= 0.1;
}
206 / 227
void liga(){
estaLigado = true;
}
void pintaVerde(){
cor = "verde";
}
void desenha(){
Alj.tela.limpa();
Alj.transforma.rotaciona(angulo, posicaoX+40, posicaoY+20);
Alj.cor.nome( cor );
Alj.desenha.retangulo(posicaoX, posicaoY, 80, 40);
Alj.cor.nome("preto");
Alj.desenha.oval(posicaoX + 10, posicaoY - 10, 20, 20);
Alj.desenha.oval(posicaoX + 10, posicaoY + 30, 20, 20);
Alj.desenha.oval(posicaoX + 50, posicaoY - 10, 20, 20);
Alj.desenha.oval(posicaoX + 50, posicaoY + 30, 20, 20);
Alj.transforma.limpaRotacao();
Alj.tela.exibe();
}
}
9.2 Anexo II – Personagens do jogo “A Aventura do Quadrado”
Este anexo apresenta as quatro classes que representam os quatro personagens
do jogo “O Mundo dos Quadrados”.
9.2.1 Classe SenhorQ
package aaventuradoquadrado.personagens;
import aljava.Alj;
import aljava.jogo.RetanguloGravidade;
/**
* O SenhorQ é o nosso herói.
* Na verdade ele era um ser humano normal, mas que de tanto ficar na
frente do computador,
207 / 227
* foi absorvido por um aplicativo do Facebook que o aprisionou em um
mundo de duas dimensões.
*
* Para ser capaz de voltar ele precisará
* manter sua identidade sem tocar em nenhum outro quadrado.
*
* Ao final, ainda precisará eliminar o super quadradão..
* para só então, poder voltar para a sua vida normal.
*/
public class SenhorQ extends RetanguloGravidade {
int vida;
int forcaPulo;
int velocidade;
public SenhorQ(){
super(40, 200, 32, 32);
vida = 32;
forcaPulo = 20;
velocidade = 4;
}
public void alteraVida(int novaVida){
vida = novaVida;
}
public void alteraForcaPulo(int novaForca){
forcaPulo = novaForca;
}
public void alteraVelocidade(int novaVelocidade){
velocidade = novaVelocidade;
}
@Override
public void processa(){
processaMovimento();
super.processa();
}
public void processaMovimento(){
if(Alj.tecla.press("direita")){
208 / 227
moveX(+velocidade);
}
if(Alj.tecla.press("esquerda")){
moveX(-velocidade);
}
if(Alj.tecla.press("espaco")){
pula(forcaPulo);
}
}
public void perdeVida(){
vida -= 3;
}
public boolean estaMorto(){
return vida <= 0;
}
@Override
public void desenha(){
Alj.cor.hexadecimal("#4512AE");
//O y também muda porque o efeito deve ser do retangulo sendo
consumido
int novoY = y + (altura - vida);
Alj.desenha.retangulo(x, novoY, largura, vida);
super.desenha();
}
}
209 / 227
9.2.2 Classe InimigoQuadradao
package aaventuradoquadrado.personagens;
import aljava.jogo.Retangulo;
/**
* Inimigo besta.
* É só um bloco parado.
* O único porém é que ele é grande, o pulo precisa ser preciso para se
manter vivo.
*/
public class InimigoQuadradao extends Retangulo {
public InimigoQuadradao(int x, int y){
super(x, y, 60, 60);
}
}
9.2.3 Classe InimigoTic
package aaventuradoquadrado.personagens;
import aljava.jogo.RetanguloGravidade;
/**
* Inimigo maluco que pula sem parar
*/
public class InimigoTic extends RetanguloGravidade {
public InimigoTic(int x, int y){
super(x, y, 32, 32);
}
@Override
public void processa(){
super.processa();
pula(16);
}
}
210 / 227
9.2.4 Classe SuperQuadrado
package aaventuradoquadrado.personagens;
import aljava.Alj;
import aljava.jogo.RetanguloGravidade;
public class SuperQuadrado extends RetanguloGravidade {
//-1 = esquerda e 1 = direita
int direcaoMovimento = 1;
int velocidade = 3;
int vida = 100;
int passos;
public SuperQuadrado(){
super(400, 200, 100, 100);
passos = 0;
}
/**
* Este método contém o comportamento do chefão.
* Muitas coisas podem ser feitas aqui.
* Por hora, ele caminhará de um lado ao outro do cenário.
*/
public void inteligenciaArtificial(){
moveX(velocidade * direcaoMovimento);
passos++;
if(passos > 140){
direcaoMovimento *= -1;
passos = 0;
}
}
public int pegaDirecao(){
return direcaoMovimento;
}
public void perdeVida() {
211 / 227
vida -= 2;
}
public boolean estaMorto(){
return vida <= 0;
}
@Override
public void desenha(){
Alj.cor.hexadecimal("#dd4444");
//O y também muda porque o efeito deve ser do retangulo sendo
consumido
int novoY = y + (altura - vida);
Alj.desenha.retangulo(x, novoY, largura, vida);
super.desenha();
}
}
9.3 Anexo III – Classe “TelaSelecao”
A Classe “TelaSelecao” foi desenvolvida em sala com os estudantes de modo a
estimulá-los a pensar e construir classes que possam ser reusadas em projetos
diferentes. Deste modo, a intenção da classe é ter baixo acoplamento com o projeto.
Segue abaixo o código da classe:
package aaventuradoquadrado;
import aljava.*;
import aljava.midia.Imagem;
import aljava.util.ContadorTempo;
public class TelaSelecao
{
Imagem matriz[];
int selecionado;
ContadorTempo contador;
int x;
int y;
int numItensPorLinha;
212 / 227
int espacamento;
int larguraImg;
int alturaImg;
public TelaSelecao(int _x, int _y, Imagem _matriz[]){
numItensPorLinha = 4;
x = _x;
y = _y;
matriz = _matriz;
espacamento = 20;
larguraImg = matriz[0].pegaLargura();
alturaImg = matriz[0].pegaAltura();
contador = new ContadorTempo(200);
selecionado = 2;
}
public int pegaSelecionado(){
return selecionado;
}
public void mudaItensPorLinha(int numItens){
numItensPorLinha = numItens;
}
public void processa(){
if(!contador.terminou()){
return;
}
if(Alj.tecla.press("direita")){
selecionado++;
contador.reinicia();
}
if(Alj.tecla.press("baixo")){
selecionado += numItensPorLinha;
contador.reinicia();
}
213 / 227
if(Alj.tecla.press("cima")){
selecionado -= numItensPorLinha;
contador.reinicia();
}
if(Alj.tecla.press("esquerda")){
selecionado--;
contador.reinicia();
}
if(selecionado > matriz.length-1) {
selecionado = 0;
}
if(selecionado < 0) {
selecionado = matriz.length-1;
}
}
public void desenha(){
for(int i =0; i < matriz.length; i++){
int linha = ( i / numItensPorLinha );
int coluna = (i % numItensPorLinha);
int xCalculado = (coluna * (larguraImg+espacamento) );
xCalculado += x;
int yCalculado = (linha
* (alturaImg+espacamento) );
yCalculado += y;
if(selecionado == i){
Alj.cor.nome("verde");
Alj.desenha.retangulo(xCalculado-5, yCalculado-5,
larguraImg+10, alturaImg+10);
}
matriz[i].desenha( xCalculado , yCalculado);
}
}
}
214 / 227
9.4 Anexo IV – Fases do jogo “A Aventura do Quadrado”
Este anexo apresenta as classes utilizadas como fases no jogo desenvolvido
durante o módulo 4.
9.4.1 Classe TelaInicial
package aaventuradoquadrado.fases;
import aaventuradoquadrado.GerenciadorFases;
import aaventuradoquadrado.TelaSelecao;
import aaventuradoquadrado.personagens.SenhorQ;
import aljava.Alj;
import aljava.midia.Imagem;
public class TelaInicial {
SenhorQ q;
TelaSelecao telaSelecao;
public TelaInicial(SenhorQ _q){
q = _q;
Imagem[] imagens = new Imagem[2];
imagens[0] = new Imagem("recursos/img/q7.png");
imagens[1] = new Imagem("recursos/img/q8.png");
telaSelecao = new TelaSelecao(30, 100, imagens);
}
public void loop() {
Alj.inicializa(288, 288);
int proximoPasso = 0;
boolean loop = true;
while(loop){
telaSelecao.processa();
if(Alj.tecla.press("enter")){
selecionaPersonagem( telaSelecao.pegaSelecionado() );
215 / 227
proximoPasso = 1;
loop = false;
}
desenha();
}
proximaFase(proximoPasso);
}
public void proximaFase(int f){
if(f == 0){
Alj.tela.finaliza();
} else if(f == 1){
vaiParaFase1();
}
}
public void selecionaPersonagem(int num){
if(num == 0){
q.alteraForcaPulo(17);
q.alteraVelocidade(7);
q.alteraVida(27);
q.alteraAltura(27);
q.alteraLargura(27);
}
if(num == 1){
q.alteraForcaPulo(20);
q.alteraVelocidade(4);
q.alteraVida(32);
q.alteraAltura(32);
q.alteraLargura(32);
}
}
public void desenha(){
Alj.cor.nome("preto");
Alj.desenha.retangulo(0, 0, 288, 288);
Alj.cor.nome("branco");
216 / 227
Alj.desenha.texto(30, 50, "Escolha o personagem", 22);
telaSelecao.desenha();
Alj.tela.exibe();
}
private void vaiParaFase1() {
Fase1 fase = (Fase1)GerenciadorFases.pegaFase("fase1");
fase.loop();
}
}
9.4.2 Classe Fase1
package aaventuradoquadrado.fases;
import aaventuradoquadrado.GerenciadorFases;
import aaventuradoquadrado.personagens.InimigoQuadradao;
import aaventuradoquadrado.personagens.InimigoTic;
import aaventuradoquadrado.personagens.SenhorQ;
import aljava.Alj;
import aljava.jogo.Camera;
import aljava.jogo.CenaComColisao;
public class Fase1 {
Camera camera;
SenhorQ q;
CenaComColisao fase1;
InimigoQuadradao umQuadradao;
InimigoTic saltitador;
public Fase1(SenhorQ senhorq){
q = senhorq;
fase1 = new CenaComColisao("recursos/cena/fase1.txt");
//Aqui configura cada bloco do cenário
fase1.configTile(1, "recursos/img/terra.png");
//O terceiro parâmetro informa se o bloco é sólido.
217 / 227
fase1.configTile(2, "recursos/img/fundo.jpg", true);
fase1.tamanhoTiles(32, 32);
camera = new Camera(fase1, q);
//Inicializa inimigos
umQuadradao = new InimigoQuadradao(350, 200);
saltitador = new InimigoTic(200, 200);
//~étodo para garantir colis"ao com o cenário
fase1.adicionaObjeto(q);
fase1.adicionaObjeto(umQuadradao);
fase1.adicionaObjeto(saltitador);
fase1.moveComCenario(umQuadradao);
fase1.moveComCenario(saltitador);
}
public void loop(){
Alj.inicializa(288, 288);
q.alteraX(40);
q.alteraY(40);
int proximoPasso = 0;
boolean loop = true;
while(loop){
q.processaMovimento();
q.processa();
saltitador.processa();
fase1.processa();
camera.processa();
processaColisoes();
//processaVitoria
if(q.pegaX() >= 288){
loop = false;
Alj.tela.exibeMensagem("Você venceu. Boa sorte no
próximo estágio.");
proximoPasso = 2;
}
218 / 227
//processaDerrota
if(q.estaMorto()){
Alj.tela.exibeMensagem("Você perdeu. Tente de novo.");
loop = false;
proximoPasso = 1;
}
desenha();
Alj.util.espera(20);
}
proximaFase( proximoPasso );
}
private void desenha(){
fase1.desenha();
umQuadradao.desenha();
saltitador.desenha();
q.desenha();
Alj.tela.exibe();
}
private void proximaFase(int f){
if(f == 0){
Alj.tela.finaliza();
} else if(f == 1){
TelaInicial fase =
(TelaInicial)GerenciadorFases.pegaFase("telaInicial");
fase.loop();
} else if(f == 2){
Fase2 fase = (Fase2)GerenciadorFases.pegaFase("fase2");
fase.loop();
}
}
private void processaColisoes() {
if(q.toca(umQuadradao)){
q.perdeVida();
219 / 227
fase1.moveHorizontal(1000);
fase1.processa();
q.alteraX(40);
}
if(q.toca(saltitador)){
q.perdeVida();
fase1.moveHorizontal(1000);
fase1.processa();
q.alteraX(40);
}
}
}
9.4.3 Classe Fase2
package aaventuradoquadrado.fases;
import aaventuradoquadrado.GerenciadorFases;
import aaventuradoquadrado.personagens.InimigoQuadradao;
import aaventuradoquadrado.personagens.InimigoTic;
import aaventuradoquadrado.personagens.SenhorQ;
import aljava.Alj;
import aljava.jogo.Camera;
import aljava.jogo.CenaComColisao;
public class Fase2 {
Camera camera;
SenhorQ q;
CenaComColisao fase2;
InimigoTic saltitador;
InimigoTic saltitador2;
public Fase2(SenhorQ senhorq){
q = senhorq;
fase2 = new CenaComColisao("recursos/cena/fase2.txt");
//Aqui configura cada bloco do cenário
fase2.configTile(1, "recursos/img/terra.png");
220 / 227
//O terceiro parâmetro informa se o bloco é sólido.
fase2.configTile(2, "recursos/img/fundo.jpg", true);
//opa, parede invisível
fase2.configTile(3, "recursos/img/fundo.jpg", false);
fase2.tamanhoTiles(32, 32);
camera = new Camera(fase2, q);
//Inicializa inimigos
saltitador = new InimigoTic(200, 200);
saltitador2 = new InimigoTic(32*7, 32*4);
fase2.adicionaObjeto(q);
fase2.adicionaObjeto(saltitador);
fase2.adicionaObjeto(saltitador2);
fase2.moveComCenario(saltitador);
fase2.moveComCenario(saltitador2);
}
public void loop(){
Alj.inicializa(288, 288);
q.alteraX(40);
q.alteraY(40);
int proximoPasso = 0;
boolean loop = true;
while(loop){
q.processaMovimento();
q.processa();
saltitador.processa();
saltitador2.processa();
fase2.processa();
camera.processa();
processaColisoes();
//processaVitoria
if(q.pegaX() >= 288){
loop = false;
proximoPasso = 2;
}
221 / 227
//processaDerrota
if(q.pegaY() >= 288){
Alj.tela.exibeMensagem("Caiu no buraco. Até mais.");
loop = false;
proximoPasso = 1;
}
if(q.estaMorto()){
Alj.tela.exibeMensagem("Você perdeu. Tente de novo.");
loop = false;
proximoPasso = 1;
}
desenha();
Alj.util.espera(20);
}
proximaFase(proximoPasso);
}
private void desenha(){
fase2.desenha();
saltitador.desenha();
saltitador2.desenha();
q.desenha();
Alj.tela.exibe();
}
private void proximaFase(int f){
if(f == 0){
Alj.tela.finaliza();
} else if(f == 1){
TelaInicial fase =
(TelaInicial)GerenciadorFases.pegaFase("telaInicial");
fase.loop();
} else if(f == 2){
Alj.tela.exibeMensagem("Parabéns, você venceu denovo. Agora
é o grande desafio.");
222 / 227
FaseChefao fase =
(FaseChefao)GerenciadorFases.pegaFase("chefao");
fase.loop();
}
}
private void processaColisoes() {
if(q.toca(saltitador)){
q.perdeVida();
fase2.moveHorizontal(1000);
fase2.processa();
q.alteraX(40);
}
if(q.toca(saltitador2)){
q.perdeVida();
fase2.moveHorizontal(1000);
fase2.processa();
q.alteraX(40);
}
}
}
9.4.4 Classe FaseChefao
package aaventuradoquadrado.fases;
import aaventuradoquadrado.GerenciadorFases;
import aaventuradoquadrado.ataques.Tiro;
import aaventuradoquadrado.personagens.SenhorQ;
import aaventuradoquadrado.personagens.SuperQuadrado;
import aljava.Alj;
import aljava.jogo.Camera;
import aljava.jogo.CenaComColisao;
import aljava.util.ContadorTempo;
import java.util.ArrayList;
public class FaseChefao {
SuperQuadrado sq;
SenhorQ q;
CenaComColisao cenario;
223 / 227
Camera camera;
ArrayList<Tiro> tiros;
ContadorTempo contador;
public FaseChefao(SenhorQ senhorq){
q = senhorq;
sq = new SuperQuadrado();
cenario = new CenaComColisao("recursos/cena/chefao.txt");
cenario.configTile(1, "recursos/img/terra.png");
//O terceiro parâmetro informa se o bloco é sólido.
cenario.configTile(2, "recursos/img/fundo.jpg", true);
cenario.tamanhoTiles(32, 32);
cenario.adicionaObjeto(sq);
cenario.adicionaObjeto(q);
cenario.moveComCenario(sq);
camera = new Camera(cenario, q);
tiros = new ArrayList<Tiro>();
//Lançará um tiro por segundo.
contador = new ContadorTempo(1200);
}
public void loop(){
Alj.inicializa(600, 288);
q.alteraX(40);
q.alteraY(40);
int proximoPasso = 0;
boolean loop = true;
while(loop){
q.processaMovimento();
q.processa();
sq.processa();
for(Tiro t : tiros){
224 / 227
t.processa();
}
sq.inteligenciaArtificial();
cenario.processa();
camera.processa();
desenha();
processaColisao();
lancaTiros();
if(q.estaMorto()){
proximoPasso = 0;
loop = false;
}
if(sq.estaMorto()){
proximoPasso = 1;
loop = false;
}
Alj.util.espera(20);
}
proximaFase(proximoPasso);
}
private void desenha(){
cenario.desenha();
q.desenha();
sq.desenha();
for(Tiro t : tiros){
t.desenha();
}
Alj.tela.exibe();
}
private void proximaFase(int f){
225 / 227
if(f == 0){
Alj.tela.exibeMensagem("Você perdeu, tente novamente com
outro personagem.");
TelaInicial t =
(TelaInicial)GerenciadorFases.pegaFase("telaInicial");
t.loop();
} else if(f == 1){
Alj.tela.exibeMensagem("Você venceu. Agora poderá voltar
para casa.");
Alj.tela.exibeMensagem("Ops...a requisição foi redirecionada
pelo sistema...");
Alj.tela.exibeMensagem("Ah não...você está sendo
redirecionado para uma nova missão antes de ser liberado...");
Alj.tela.exibeMensagem("Para poder ir embora você precisará
passar ainda por mais um mundo..");
Alj.tela.exibeMensagem("O MUNDO DOS CÍRCULOS...");
Alj.tela.exibeMensagem("Em breve, uma nova aventura para o
SenhorQ. Aguarde");
Alj.tela.finaliza();
}
}
private void processaColisao() {
if(q.toca(sq)){
q.perdeVida();
int direcao = sq.pegaDirecao();
if(direcao == -1){
cenario.moveHorizontal(-1000);
q.alteraX(550);
} else {
cenario.moveHorizontal(1000);
q.alteraX(60);
}
}
for(Tiro t : tiros){
if(t.toca(q)){
q.perdeVida();
tiros.remove(t);
break;
}
}
226 / 227
for(Tiro t : tiros){
if(t.toca(sq)){
sq.perdeVida();
tiros.remove(t);
break;
}
}
for(Tiro t : tiros){
if(cenario.temColisaoComTile(t, 2)){
t.inverteDirecao();
}
}
}
private void lancaTiros() {
if(contador.terminou()){
contador.reinicia();
int yTiro = Alj.util.sorteia(sq.pegaY(), sq.pegaY()
+sq.pegaAltura());
int xTiro;
int velocidadeTiro;
//Lança os tiros na direção do personagem
if(q.pegaX() < sq.pegaX()){
xTiro = sq.pegaX();
velocidadeTiro = -9;
} else {
xTiro = sq.pegaX() + sq.pegaLargura();
velocidadeTiro = 9;
}
Tiro t = new Tiro( xTiro, yTiro, velocidadeTiro);
cenario.moveComCenario(t);
tiros.add(t);
}
}
}
227 / 227

Documentos relacionados