Construindo um Jogo para a Web – Bomberman

Transcrição

Construindo um Jogo para a Web – Bomberman
Construindo um Jogo para a
Web – Bomberman
Programação para a Internet
Prof. Vilson Heck Junior
Tecnologias Necessárias
• Tecnologias já Estudadas:
– HTML;
– CSS;
– JavaScript;
• Tecnologias Novas:
–
–
–
–
–
Computação Gráfica Básica;
Noções de Geometria;
Noções de Física;
Reprodução de Sons;
Enredo;
Computação Gráfica
• É um campo da Ciência da Computação que
estuda métodos para sintetizar e manipular
digitalmente conteúdo visual:
– Geração de imagens 2D;
– Geração de imagens 3D (renderização);
– Com ou sem animação;
Noções de Geometria
• Gráficos 2D ou 3D são na verdade a
composição de pequenas peças
geométricas:
• A relação espacial dada entre diferentes
objetos existentes em uma cena deve ser
respeitada:
– Dois corpos não podem ocupar um mesmo
lugar no espaço!
Noções de Física
• Objetos podem possuir algum tipo de
movimento ou interação com outros
objetos;
• Para isto, geralmente respeitam
alguma(s) regras físicas:
– Próximas a real: Simulação;
– Diferenciadas: Arcade;
Reprodução de Sons
• O som é o elemento responsável por
estimular o sentido da audição;
• Não tanto quanto os gráficos, mas os sons
são responsáveis por completar uma boa
sensação de imersão em jogos e
entretenimento;
• Geralmente os sons (músicas ou barulhos)
serão escolhidos conforme um
determinado contexto ou acontecimento.
Enredo
• O enredo irá explicar ao usuário o que
deverá ser feito e deve ser o principal
responsável por atrair a atenção do
jogador:
– História;
– Diversão;
– Desafios;
– Passatempo;
– ...
Enredo
• Bomberman:
– Lançado em 1983;
– Plataforma: PC doméstico;
– Desenvolvido pela Husdson Soft.
Nintendo -1989
Enredo
• Bomberman:
– Jogo árcade baseado em labirintos;
– Inimigos não podem te alcançar;
– Destruir paredes e inimigos com bombas.
Nosso Conceito
Bomberman
LISTA DE RECURSOS INICIAIS
Recursos Iniciais
• Pasta: “Bomberman”:
– index.html
• Construiremos de um documento web, inserindo todos os
demais elementos necessários;
– estilo.css
• Definiremos algumas configurações de cores, bordas e outros
para nossa interface;
– Bomba.js & bomberman.js & Mapa.js & mapaMascara.js
• Faremos todo o processamento e configurações do jogo, ou seja,
daremos ações aos acontecimentos e eventos do jogo.
– Jogador.js & Inimigo.js
• Implementaremos a parte de movimentação do jogador e dos
inimigos;
index.html
•
•
•
•
•
Crie o arquivo como doctype para html 5;
Crie as tags para:
– <html>, <head>, <body> e <title>;
Estipule um <link> com arquivo de estilo;
Adicione os arquivos de <script> dentro do <head>:
– mapaMascara.js
– Mapa.js
– Jogador.js
– Inimigo.js
– Bomba.js
Adicione o arquivo de <script> bomberman.js ao fim do <body>;
– Importante: adicionar os outros arquivos js antes, pois o último
precisa dos primeiros já executados.
index.html
• Adicione os seguintes Tags com seus atributos dentro
do <body>:
– <canvas>Navegador não suportado!</canvas>
• id = “tela” width=200 height=200
– <button>Iniciar</button>
• onclick=“pausar()” id=“btnIniciar”
– <button>Novo Jogo</button>
• onclick=“reiniciar()” id=“btnNovo”
– <p id="tecla"></p>
– <p>A,S,D,W -> Mover<br>
Barra de Espaço -> Liberar bomba</p>
estilo.css
body { background-color: #224422;
text-align: center; }
#tela {
background-color: black;
border: 2px solid red; }
button {
background-color: #EE9999;
color: white;
border: 1px solid red;
width: 100px;
height: 30px;
font-weight: bold;
cursor: pointer; }
button:hover { background-color: #EEBBBB; }
button:disabled {
background-color: #DDDDDD;
cursor: not-allowed; }
Bomberman
DESENHANDO NO CANVAS
<canvas>
• Canvas é um termo inglês dado a alguns tipos
de tela para pintura;
• No nosso caso, será uma área dentro do
documento HTML onde poderemos pintar o
que precisarmos;
• Nosso pincel e paleta de cores estão
disponíveis através de código JavaScript.
<canvas>
• O Canvas é feito para oferecer suporte a
rápido desenho de cenas bidimensionais
ou tridimensionais:
– Geralmente acelerado por Hardware;
0
X
width
0
y
height
bomberman.js
//Recuperando referência dos objetos no documento
var canvas = document.getElementById("tela");
var ctx = canvas.getContext("2d");
//Um pequeno teste (remover depois de testar)
ctx.fillStyle = "#FF0000"; //Usar cor vermelha
ctx.fillRect(20, 30, 50, 100); //x=20, y=30, w=50 e h=100
Desenhando
• Temos uma tela para desenho;
• Conhecemos uma primeira ferramenta para
pintar algo;
• Temos que utilizar esta ferramenta de forma a
construir o cenário inicial do nosso jogo;
Relembrando
Estrutura de Dados: matriz
Posições da matriz
Descrição Representação Gráfica
Código (cor)
Livre
0 - (preto)
Parede
1 - (branco)
Jogador
2 - (vermelho)
Tijolo
3 - (verde)
Inimigo
4 - (azul)
Bomba
5 - (N/A)
Mapa.js
function Mapa() {
//Sem elementos estáticos
}
//Compreensão do conteúdo do mapa
Mapa.LIVRE = 0;
Mapa.PAREDE = 1;
Mapa.JOGADOR = 2;
Mapa.TIJOLO = 3;
Mapa.INIMIGO = 4;
Mapa.BOMBA = 5;
//Linhas e colunas existentes no mapa atual
Mapa.colunas = 0;
Mapa.linhas = 0;
//Largura e altura de cada linha/coluna em pixels
Mapa.largura = 40;
mapaMascara.js
Exemplo de cenário com 5 colunas e 6
linhas:
var mapaMascara =
[ [1, 1, 1, 1, 1],
[1, 0, 2, 0, 1],
[1, 3, 1, 0, 1],
[1, 3, 1, 3, 1],
[1, 3, 4, 0, 1],
[1, 1, 1, 1, 1] ];
Dimensões
• Cada elemento da matriz terá uma largura e
altura, sendo elementos quadrados: largura =
altura.
Largura
Dimensões
• A largura, ou altura, geral do jogo, será definida pela
largura de cada elemento x o número de elementos:
AlturaTotal = Largura * nLinhas
Mapa.js
...
//Mantém e carrega o mapa atual
Mapa.atual = null;
Mapa.carregar = function (canvas) {
Mapa.atual = new Array();
var y, x;
for (y = 0; y < mapaMascara.length; y++) {
Mapa.atual.push(mapaMascara[y].slice(0));
}
Mapa.linhas = Mapa.atual.length;
Mapa.colunas = Mapa.atual[0].length;
canvas.width = Mapa.colunas * Mapa.largura;
canvas.height = Mapa.linhas * Mapa.largura;
};
Mapa.js
//Carrega textura e desenha mapa
Mapa.imgTijolo = new Image();
Mapa.imgTijolo.src = "tijolo.png";
Mapa.desenhar = function (ctx) {
if (Mapa.atual != null) {
var x, y;
for (y = 0; y < Mapa.linhas; y++) {
for (x = 0; x < Mapa.colunas; x++) {
if (Mapa.atual[y][x] == Mapa.PAREDE) {
ctx.fillStyle = "#BBBBBB";
ctx.fillRect(x * Mapa.largura, y * Mapa.largura,
Mapa.largura, Mapa.largura);
} else if (Mapa.atual[y][x] == Mapa.TIJOLO) {
ctx.drawImage(Mapa.imgTijolo, x * Mapa.largura, y *
Mapa.largura, Mapa.largura, Mapa.largura);
}
}
}
}
};
bomberman.js
var canvas = document.getElementById("tela");
var ctx = canvas.getContext("2d");
//Adicionar temporariamente. Remover depois.
Mapa.carregar(canvas);
Mapa.desenhar(ctx);
Jogador.js
//Classe para controle e movimentos do jogador
function Jogador() {
}
Jogador.x = -1;
Jogador.y = -1;
Jogador.desenhar = function (ctx) {
ctx.fillStyle = "#00BBBB";
ctx.fillRect(Jogador.x * Mapa.largura + 2, Jogador.y *
Mapa.largura + 2, Mapa.largura - 4, Mapa.largura - 4);
};
Mapa.js
Mapa.carregar = function (canvas) {
...
for (y = 0; y < mapaMascara.length; y++) {
Mapa.atual.push(mapaMascara[y].slice(0));
for (x = 0; x < Mapa.atual[y].length; x++) {
switch (Mapa.atual[y][x]) {
case Mapa.JOGADOR:
Jogador.x = x;
Jogador.y = y;
break;
}
}
}
...
};
bomberman.js
var canvas = document.getElementById("tela");
var ctx = canvas.getContext("2d");
//Adicionar temporariamente. Remover depois.
Mapa.carregar(canvas);
Mapa.desenhar(ctx);
Jogador.desenhar(ctx);
Bomberman
OS VILÕES!
Os Vilões
• No Bomberman, os vilões são “monstros” que
andam pelo labirinto;
• Cada mapa terá um número diferente de inimigos.
• Em nossa implementação, cada inimigo será uma
instância de uma classe chamada Inimigo;
• Cada vez que encontramos Mapa.INIMIGO no
mapa, instanciamos um novo objeto Inimigo.
Inimigo.js
//Classe para controle e movimentos dos inimigos
function Inimigo(x, y, imagem) {
this.x = x;
this.y = y;
Construtor
this.imagem = imagem;
this.desenhar = function (ctx) {
ctx.drawImage(this.imagem, this.x * Mapa.largura,
this.y * Mapa.largura, Mapa.largura, Mapa.largura);
};
}
Inimigo.js
//Classe para controle e movimentos dos inimigos
...
Inimigo.todos = new Array();
Inimigo.desenharTodos = function (ctx) {
var i;
for (i = 0; i < Inimigo.todos.length; i++) {
Inimigo.todos[i].desenhar(ctx);
}
};
Mapa.js
Mapa.carregar = function (canvas) {
...
switch (Mapa.atual[y][x]) {
case Mapa.JOGADOR:
Jogador.x = x;
Jogador.y = y;
break;
case Mapa.INIMIGO:
var inimigoImg = new Image();
inimigoImg.src = "inimigo.png";
inimigoImg.onload = desenharTudo;
Inimigo.todos.push(new Inimigo(x, y, inimigoImg));
break;
}
bomberman.js
function reiniciar() {
Mapa.carregar(canvas);
desenharTudo();
document.getElementById("btnIniciar").disabled = false;
document.getElementById("btnIniciar").innerHTML = "Iniciar";
}
function desenharTudo() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
Mapa.desenhar(ctx);
Jogador.desenhar(ctx);
Inimigo.desenharTodos(ctx);
}
reiniciar();
Testar!
Bomberman
GERAÇÃO DE MAPAS
Geração de Mapas
• Em “Arquivos para Atividades Práticas”
– Na pasta “bomberman”;
– Baixe BombermanMapGenerator.zip;
– Isto é um projeto NetBeans!
• Gerar um arquivo BMP no MS Paint!
– Observar cores que irão definir objetos.
• Converter com o software Java!
Geração de Mapas
• Em “Arquivos para Atividades Práticas”
– Na pasta “bomberman”;
– Baixe “cenario.png” para qualquer pasta
– Converta o arquivo com o Gerador de
Mapas baixado anteriormente;
• salve o arquivo gerado com nome
mapaMascara.js ;
• Coloque o arquivo gerado dentro da pasta do
seu projeto, substituindo o arquivo digitado
anteriormente.
Bomberman
• Teste sua página!
Bomberman
COLOCANDO VIDA
O que precisamos?
• Fazer o Bomberman se movimentar ao pressionar de tecla?
• Fazer os inimigos se movimentarem:
– Com qual intervalo de tempo?
– Para qual direção?
• O que acontece se o usuário ordenar que o Bomberman se mova
contra uma parede?
• O que ocorre quando o Bomberman liberar uma boba?
• O que ocorre quando o Bomberman encontrar um inimigo?
– E se a bomba explodir perto de um inimigo?
• E quando acabarem todos os inimigos do mapa?
Movimentação do Bomberman
• O Bomberman irá se movimentar conforme
teclas que o usuário pressionar:
– A, S, D, W;
– Outras teclas configuradas;
Bomberman
INTERAGINDO COM O USUÁRIO
Eventos!
• A interação é dada por uma troca entre a
máquina e o usuário;
• A máquina fornece principalmente
imagens que descrevem uma situação,
onde pode ser necessária a intervenção
do usuário;
• O usuário irá intervir basicamente
através de comandos!
– Comandos são captados através de eventos.
Eventos!
• Nosso document possui propriedades de
eventos que podem ser associadas à
funções quaisquer;
• Estas funções determinam algo a ser
feito quando aquele evento ocorrer:
– document.onkeydown
• Ao descer uma tecla qualquer;
– document.onkeyup
• Ao soltar uma tecla qualquer;
bomberman.js
document.onkeydown = function (evt) {
document.getElementById("tecla").innerHTML =
evt.keyCode;
}
Teste!
bomberman.js
document.onkeydown = function (evt) {
Jogador.tratarTecla(evt);
}
Apagar o
<p id=“tecla”>
do HTML
Jogador.js
//Configurações de teclas para o Jogador
Jogador.cmdEsq = 65; //A
Jogador.cmdDir = 68; //D
Jogador.cmdCim = 87; //W
Jogador.cmdBai = 83; //S
Jogador.cmdBomba = 32; //Espaço
//Variáveis para controle de movimentação
Jogador.proximoMov = null;
Jogador.plantarBomba = false;
Jogador.js
//Tratar tecla pressionado conforme comportamento do Jogador
Jogador.tratarTecla = function (evt) {
switch (evt.keyCode) {
case Jogador.cmdEsq:
case Jogador.cmdDir:
case Jogador.cmdCim:
case Jogador.cmdBai:
Jogador.proximoMov = evt.keyCode;
evt.preventDefault();
break;
case Jogador.cmdBomba:
Jogador.plantarBomba = true;
evt.preventDefault();
break;
}
};
Jogador.js (1/3)
//Com base no último movimento solicitado, executa movimento
Jogador.mover = function () {
var nx = -1;
var ny = -1;
switch (Jogador.proximoMov) {
case Jogador.cmdEsq:
nx = Jogador.x - 1;
break;
case Jogador.cmdDir:
nx = Jogador.x + 1;
break;
case Jogador.cmdCim:
ny = Jogador.y - 1;
break;
case Jogador.cmdBai:
ny = Jogador.y + 1;
break;
}
Jogador.js (2/3)
if (Jogador.plantarBomba) {
if (Bomba.todas.length < Bomba.maxBombas) {
Bomba.todas.push(new Bomba(this.x, this.y));
}
Jogador.plantarBomba = false;
}
if (nx >= 0 && nx < Mapa.colunas) {
switch (Mapa.atual[Jogador.y][nx]) {
case Mapa.PAREDE:
case Mapa.TIJOLO:
case Mapa.BOMBA:
break;
default:
Jogador.x = nx;
break;
}
}
Jogador.js (3/3)
if (ny >= 0 && ny < Mapa.linhas) {
switch (Mapa.atual[ny][Jogador.x]) {
case Mapa.PAREDE:
case Mapa.TIJOLO:
case Mapa.BOMBA:
break;
default:
Jogador.y = ny;
break;
}
}
Jogador.proximoMov = null;
};
Bomberman
• Colocar temporariamente os comandos dentro, no
fim da função Jogador.tratarTecla(evt):
– Jogador.mover();
– desenharTudo();
• Teste sua página!
Bomberman
CONTROLE GLOBAL DO MOVIMENTO
Movendo com Tempo
• Todo tipo de movimento tem uma velocidade;
• Como determinamos a velocidade de algum
objeto?
– Medida Espacial / Tempo!
• KM/h
• m/s
• ...
Controlando o Tempo
• Como já definimos, a unidade de espaço de cada
movimento dos inimigos e do jogador será por posição;
• Agora precisamos determinar o intervalo de tempo que
nosso jogo irá usar para fazer cada movimento dos
elementos;
• Como nosso jogo gira em torno do Bomberman e dos
Inimigos (e cada um terá uma velocidade diferente), estes
tempos serão como guias para todo o jogo.
Controlando o Tempo
• Função JavaScript:
– relogio = setInterval(“NomeFuncao()”, intervalo);
• relogio é uma referência ao timer/clock que foi criado;
• NomeFuncao() é a função que será executada a cada
intervalo;
• intervalo é um número inteiro representando a
quantidade em milissegundos de intervalo entre uma
execução e outra da função NomeFuncao().
– clearInterval(relogio);
• Para o relógio de repetição;
bomberman.js
• Crie a variável:
– var intervaloJogador = 200;
– var intervaloInimigos = 400;
• A primeira variável irá definir a quantidade de
milissegundos entre cada movimento do Jogador;
• O intervalo entre os movimentos dos inimigos será um
pouco maior, para deixá-los mais lentos.
bomberman.js
• Crie as variáveis:
– var tempoJogador = null;
– var tempoInimigos = null;
• Elas serão responsaveis por armazenar a referência aos
objetos que farão a temporização de movimento do
Jogador e dos Inimigos.
bomberman.js
function reiniciar() {
if (tempoJogador != null) {
pausar();
}
intervaloJogador = 200;
intervaloInimigos = intervaloJogador * 2;
Mapa.carregar(canvas);
desenharTudo();
document.getElementById("btnIniciar").disabled = false;
document.getElementById("btnIniciar").innerHTML = "Iniciar";
//Bomba.todas.length = 0;
//Bomba.maxBombas = 1;
}
bomberman.js
function pausar() {
if (tempoJogador == null) {
tempoJogador = setInterval("atualizaJogador()",
intervaloJogador);
tempoInimigos = setInterval("atualizaInimigos()",
intervaloInimigos);
document.getElementById("btnIniciar").innerHTML = "Pausar";
} else {
clearInterval(tempoJogador);
tempoJogador = null;
clearInterval(tempoInimigos);
tempoInimigos = null;
document.getElementById("btnIniciar").innerHTML =
"Continuar";
}
}
bomberman.js
function atualizaJogador() {
Jogador.mover();
desenharTudo();
}
function atualizaInimigos() {
desenharTudo();
}
Bomberman
• Se você ainda não retirou os seguintes comandos
de dentro da função Jogador.tratarTecla(evt), retire:
– Jogador.mover();
– desenharTudo();
• Teste sua página!
Bomberman
MOVIMENTAÇÃO DOS INIMIGOS
Movimentação dos Inimigos
• Para que os inimigos se movam, precisamos
definir regras que de alguma forma
demonstrem coerência no seu movimento;
• Por exemplo:
–
–
–
–
Não mudar de direção a todo o segundo;
Ser capaz de eventualmente trocar de direção;
Não atravessar as paredes;
Entre outros.
• Antes de mover, o inimigo precisa verificar
as possibilidades para onde pode se mover.
Inimigo.js
function Inimigo(x, y, imagem) {
...
this.direcoes = new Array();
this.direcaoAtual = 0;//Parado
...
}
Construtor
Inimigo.js
this.mover = function () {
this.direcoes.length = 0;
this.adicionaDirecao(this.direcaoAtual, 8);
this.adicionaDirecao(Jogador.cmdCim, 4);
this.adicionaDirecao(Jogador.cmdEsq, 4);
this.adicionaDirecao(Jogador.cmdDir, 4);
this.adicionaDirecao(Jogador.cmdBai, 4);
this.adicionaDirecao(0, 1);//Ficar parado
var aleat = Math.round(Math.random() * (this.direcoes.length -1));
this.direcaoAtual = this.direcoes[aleat];
switch (this.direcaoAtual) {
case Jogador.cmdDir:
case Jogador.cmdCim:
this.x++;
this.y--;
break;
break;
case Jogador.cmdEsq:
case Jogador.cmdBai:
this.x--;
this.y++;
break;
break;
}
};
Inimigo.js (1/2)
this.adicionaDirecao = function (dir, vezes) {
var nx = this.x;
var ny = this.y;
switch(dir) {
case Jogador.cmdEsq:
nx--;
break;
case Jogador.cmdDir:
nx++;
break;
case Jogador.cmdCim:
ny--;
break;
case Jogador.cmdBai:
ny++;
break;
} //Fim do switch
Inimigo.js (2/2)
if (nx < 0 || ny < 0 || nx >= Mapa.colunas || ny >=
Mapa.linhas) {
return;
}
switch (Mapa.atual[ny][nx]) {
case Mapa.PAREDE:
case Mapa.TIJOLO:
case Mapa.BOMBA:
return;
}
var z;
for (z = 0; z < vezes; z++) {
this.direcoes.push(dir);
}
}; //Fim do adicionaDirecao()
Inimigo.js
//Mover todos os inimigos: método estático!
Inimigo.moverTodos = function() {
var i;
for (i = 0; i < Inimigo.todos.length; i++) {
Inimigo.todos[i].mover();
}
};
bomberman.js
function atualizaInimigos() {
Inimigo.moverTodos();
desenharTudo();
}
Testar!
Alterações Restantes
• O que falta alterar?
– INSERIR A BOMBA!
– E quando explode a bomba?
• Se atingir o próprio bomberman? Se atingir um inimigo? Se atingir um
tijolo? Se atingir uma parede?
– Fim de jogo?
– Sons?
bomberman.js
function atualizaJogador() {
Jogador.mover();
desenharTudo();
if (Jogador.verificaMorte()) {
gameOver();
}
}
function atualizaInimigos() {
Inimigo.moverTodos();
desenharTudo();
if (Jogador.verificaMorte()) {
gameOver();
}
}
Jogador.js
//Verifica se o Jogador morre (contato com inimigo)
Jogador.verificaMorte = function() {
var i;
for (i = 0; i < Inimigo.todos.length; i++) {
if (Jogador.x == Inimigo.todos[i].x &&
Jogador.y == Inimigo.todos[i].y) {
return true;
}
}
return false;
};
bomberman.js
//Executa comandos para efetuar o gameover
function gameOver() {
if (tempoJogador != null) {
pausar();
}
document.getElementById("btnIniciar").disabled = true;
}
Testar!
Bomberman
A BOMBA!
A Bomba
•
•
•
•
•
Depois de ser armada (criada), a bomba terá um tempo até a sua explosão;
Ao explodir, ela irá alcançar um raio, apenas nas quatro direções básicas: cima, baixo,
esquerda e direita;
O raio da explosão pode ser limitado por qualquer objeto que haja no caminho;
Caso a bomba atinja o Jogador ou algum Inimigo, este deverá morrer;
Caso a bomba atinja outra bomba, a segunda também deverá explodir imediatamente.
Bomba.js
function Bomba(x, y) {
this.x = x;
this.y = y;
this.ciclos = Bomba.nCiclosAtual;
this.cicloAtual = 0;
this.raio = Bomba.raioAtual;
Mapa.atual[y][x] = Mapa.BOMBA;
}
Bomba.som = null;
Bomba.todas = new Array();
Bomba.todas.length = 0;
Bomba.maxBombas = 1; //Valor definido no "novo jogo"
Bomba.nCiclosAtual = 15;
Bomba.raioAtual = 2;
Bomba.nCiclosPos = 2;
Bomba.js (1/5)
this.desenhar = function(ctx) {
var raio = Mapa.largura / 2;
var prop = 0.5 + ((0.5 * this.cicloAtual) / this.ciclos);
if (prop > 1) {
prop = 1;
}
ctx.fillStyle = "rgb(" + Math.round(prop * 255) +", " +
Math.round(prop * 100) + ", 0)";
if (this.cicloAtual <= this.ciclos) {
ctx.beginPath();
ctx.arc(this.x * Mapa.largura + raio, this.y *
Mapa.largura + raio, raio, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
} else {
//Pinta o ponto central da explosão
ctx.fillRect(this.x * Mapa.largura, this.y * Mapa.largura,
Mapa.largura, Mapa.largura);
Bomba.js (2/5)
} else {
...
var nx, ny, r; //Para cima
for (r = 1; r <= this.raio; r++) {
ny = this.y - r;
if (ny >= 0) {
if (Mapa.atual[ny][this.x] == Mapa.PAREDE) {
break;
} else {
ctx.fillRect(this.x * Mapa.largura, ny *
Mapa.largura, Mapa.largura, Mapa.largura);
}
if (Mapa.atual[ny][this.x] == Mapa.TIJOLO) {
break;
}
} //Fecha if (ny >= 0)
} //Fecha for (r)
Bomba.js (3/5)
} else {
...
//Para baixo
for (r = 1; r <= this.raio; r++) {
ny = this.y + r;
if (ny < Mapa.linhas) {
if (Mapa.atual[ny][this.x] == Mapa.PAREDE) {
break;
} else {
ctx.fillRect(this.x * Mapa.largura, ny *
Mapa.largura, Mapa.largura, Mapa.largura);
}
if (Mapa.atual[ny][this.x] == Mapa.TIJOLO) {
break;
}
} //Fecha if (ny)
} //Fecha for (r)
Bomba.js (4/5)
} else {
...
//Para esquerda
for (r = 1; r <= this.raio; r++) {
nx = this.x - r;
if (nx >= 0) {
if (Mapa.atual[this.y][nx] == Mapa.PAREDE) {
break;
} else {
ctx.fillRect(nx * Mapa.largura, this.y *
Mapa.largura, Mapa.largura, Mapa.largura);
}
if (Mapa.atual[this.y][nx] == Mapa.TIJOLO) {
break;
}
} //Fecha if (nx)
} //Fecha for (r)
Bomba.js (5/5)
//Para direita
for (r = 1; r <= this.raio; r++) {
nx = this.x + r;
if (nx < Mapa.colunas) {
if (Mapa.atual[this.y][nx] == Mapa.PAREDE) {
break;
} else {
ctx.fillRect(nx * Mapa.largura, this.y *
Mapa.largura, Mapa.largura, Mapa.largura);
}
if (Mapa.atual[this.y][nx] == Mapa.TIJOLO) {
break;
}
} //Fecha if (nx)
} //Fecha for (r)
} //Fecha o else
}; //Fecha o método desenhar()
Bomba.js
Bomba.desenharTodas = function (ctx) {
var i;
for (i = 0; i < Bomba.todas.length; i++) {
Bomba.todas[i].desenhar(ctx);
}
};
bomberman.js
//REVISAR A FUNÇÃO
function reiniciar() {
if (tempoJogador != null) {
pausar();
}
Mapa.carregar(canvas);
desenharTudo();
document.getElementById("btnIniciar").disabled = false;
document.getElementById("btnIniciar").innerHTML = "Iniciar";
intervaloJogador = 200;
intervaloInimigos = intervaloJogador * 2;
Bomba.todas.length = 0;
Bomba.maxBombas = 1;
}
bomberman.js
//REVISAR A FUNÇÃO
function desenharTudo() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
Mapa.desenhar(ctx);
Bomba.desenharTodas(ctx);
Jogador.desenhar(ctx);
Inimigo.desenharTodos(ctx);
}
Testar!
Bomba.js
Bomba.executarTodosCiclos = function () {
var i;
for (i = 0; i < Bomba.todas.length; i++) {
Bomba.todas[i].executarCiclo();
}
};
Bomba.js
this.executarCiclo = function () {
this.cicloAtual++;
if (this.cicloAtual > this.ciclos) {
if (this.cicloAtual == this.ciclos + 1 && Bomba.som !=
null) {
//Bomba.som.currentTime = 0;
//Bomba.som.play();
}
//this.explodir();
}
};
bomberman.js
//REVISAR A FUNÇÃO
function atualizaJogador() {
Jogador.mover();
Bomba.executarTodosCiclos();
desenharTudo();
if (Jogador.verificaMorte()) {
gameOver();
}
}
Testar!
Bomba.js (1/5)
this.explodir = function () {
var nx, ny, r, continua;
//Para cima
continua = false;
for (r = 1; r <= this.raio; r++) {
ny = this.y - r;
if (ny >= 0) {
continua = this.verificaEstrago(this.x, ny);
}
if (!continua) {
break;
}
} //Fim do for
Bomba.js (2/5)
//Para baixo
continua = false;
for (r = 1; r <= this.raio; r++) {
ny = this.y + r;
if (ny < Mapa.linhas) {
continua = this.verificaEstrago(this.x, ny);
}
if (!continua) {
break;
}
}
Bomba.js (3/5)
//Para esquerda
continua = false;
for (r = 1; r <= this.raio; r++) {
nx = this.x - r;
if (nx >= 0) {
continua = this.verificaEstrago(nx, this.y);
}
if (!continua) {
break;
}
}
Bomba.js (4/5)
//Para direita
continua = false;
for (r = 1; r <= this.raio; r++) {
nx = this.x + r;
if (nx < Mapa.colunas) {
continua = this.verificaEstrago(nx, this.y);
}
if (!continua) {
break;
}
}
Bomba.js (5/5)
//Garante o tempo da explosão ativa
if (this.cicloAtual > this.ciclos + Bomba.nCiclosPos) {
var posicao = Bomba.todas.indexOf(this);
Bomba.todas.splice(posicao, 1);
Mapa.atual[this.y][this.x] = Mapa.LIVRE;
}
}; //Fim do método explodir()
Bomba.js (1/3)
this.verificaEstrago = function (x, y) {
//Se encontrar uma parede, para o avanço da explosão
if (Mapa.atual[y][x] == Mapa.PAREDE) {
return false;
}
//Se encontrar um tijolo, quebra e para
if (Mapa.atual[y][x] == Mapa.TIJOLO) {
if (this.cicloAtual > this.ciclos +
Bomba.nCiclosPos) {
Mapa.atual[y][x] = Mapa.LIVRE;
}
return false;
}
Bomba.js (2/3)
//Se encontrar uma bomba, explode quando for necessário
var i;
for (i = 0; i < Bomba.todas.length; i++) {
if (Bomba.todas[i].x == x &&
Bomba.todas[i].y == y &&
this != Bomba.todas[i] &&
Bomba.todas[i].cicloAtual < Bomba.todas[i].ciclos) {
//Vai explodir
Bomba.todas[i].cicloAtual = Bomba.todas[i].ciclos;
}
}
//Se encontrar o jogador, fim de jogo
if (Jogador.x == x && Jogador.y == y) {
gameOver();
}
Bomba.js (3/3)
//Se encontrar um inimigo, mata-o
i = 0;
while (i < Inimigo.todos.length) {
if (Inimigo.todos[i].x == x && Inimigo.todos[i].y == y) {
Inimigo.todos.splice(i, 1);
} else {
i++;
}
}
return true;
};//Fim do método verificaEstrago()
Bomba.js
this.executarCiclo = function () {
this.cicloAtual++;
if (this.cicloAtual > this.ciclos) {
if (this.cicloAtual == this.ciclos + 1 && Bomba.som !=
null) {
//Bomba.som.currentTime = 0;
//Bomba.som.play();
}
this.explodir();
}
};
Retirar o comentário
Testar!
Bomberman
ESTÍMULOS SONOROS
Estímulos Sonoros
• Conforme comentado anteriormente, quanto mais
estimularmos, de forma positiva, os sentidos dos
jogadores, maior a probabilidade dele se sentir
como parte do jogo;
• Para isto, iremos adicionar alguns pequenos sons
associados a eventos como colisões;
• Baixe os arquivos e salve na subpasta snd:
– bomba.mp_;
– bomba.ogg;
<audio> e <source>
• HTML 5!
• MIME Types:
– MP3 – audio/mpeg
– Ogg – audio/ogg
– Wav – audio/wav
• Suporte:
– Ps.: Múltiplos <source> fornecem redundância!
Browser
MP3
Wav
Ogg
IE 9+
Sim
Não
Não
Chrome 6+
Sim
Sim
Sim
Firefox 3.6+
Não
Sim
Sim
Safari 5+
Sim
Sim
Não
Opera 10+
Não
Sim
Sim
index.html
...
<audio controls id=“sndBomba">
<source src="snd/bomba.mp_" type="audio/mpeg">
<source src="snd/bomba.ogg" type="audio/ogg">
</audio>
<script src=“bomberman.js"></script>
bomberman.js
//Recuperando referência dos objetos no documento
var canvas = document.getElementById("tela");
var ctx = canvas.getContext("2d");
Bomba.som = document.getElementById("sndBomba");
Bomba.js
this.executarCiclo = function () {
this.cicloAtual++;
if (this.cicloAtual > this.ciclos) {
if (this.cicloAtual == this.ciclos + 1 && Bomba.som !=
null) {
Bomba.som.currentTime = 0;
Bomba.som.play();
}
this.explodir();
}
};
Retirar os comentários
Testar!
Trabalho
1.
2.
3.
4.
50%
5.
50%
6.
7.
8.
9.
10.
11.
Customize cores e outras configurações do arquivo de estilo;
Customize cores, tamanhos e disposição dos objetos do jogo (dentro do
Javascript). Utilize gradientes e/ou imagens;
Complete o HTML informando o nome da disciplina, o nome do
instituto e o seu nome, dispondo os elementos com layouts CSS;
Existe um bug: quando o jogo não esta em execução, teclas
pressionadas são processadas ao retomar o jogo. Corrija este bug.
Bug: Ao pressionar o botão “Novo Jogo”, o jogo reinicia mas duplica os
Inimigos existentes.
Crie um placar com pontuação;
Crie uma indicação visual dentro do Canvas de fim de jogo;
Adicione novos sons a eventos diferentes no jogo;
Adicione teclas de atalho para “Pausa” e para “Novo Jogo”;
Ao evoluir no jogo, crie novos desafios para o jogador;
–
Adicione outros elementos a seu critério;
Entregue os arquivos por e-mail ao Professor junto com uma
descrição/resposta para cada item do trabalho.