Construindo um Jogo para a
Web - Breakout
Programação para a Internet
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;
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);
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
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;
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
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
•
Breakout:
–
Atari em 1976.
LISTA DE RECURSOS INICIAIS
Recursos Iniciais
•
Pasta: “Breakout”:
–
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;
–
bg.js
•
Faremos todo o processamento do jogo, ou seja,
daremos vida aos elementos existentes no
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;
index.html
•
Adicione os seguintes Tags com seus
atributos dentro do <body>:
–
<canvas></canvas>
•
id =
“myCanvas”
width=800 height=600
–
<button>Iniciar</button>
•
type=
“button”
onClick=
“Pausar()”
id=
“btStart”
–
<button>Reiniciar</button>
•
type=
“button”
onClick=
“Reiniciar()”
–
<p id=
“info”
></p>
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
<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 h e igh t
bg.js
//Recuperando referência dos objetos no documento
var
c = document.getElementById(
"myCanvas"
);
var
ctx = c.getContext(
"2d"
);
var
info_display = document.getElementById(
"info"
);
var
btnStart = document.getElementById(
"btStart"
);
//Um pequeno teste (remover depois de testar)
ctx.fillStyle =
“#FF0000”
;
//Usar cor vermelha
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;
Posicionamento e Tamanhos
•
Encontramos: Diversos Tijolos, Uma Base
e Uma Bola;
•
Iremos utilizar variáveis para guardar a
posição (X, Y) de cada objeto, bem como
as dimensões e outras propriedades das
formas geométricas utilizadas.
bg.js
//Variáveis do Posicionamento da bola
var ball_cx; //Bola inicia no centro horizontal | definido em reiniciar
var ball_cy; //Bola inicia em 85% da altura | definido em reiniciar
var ball_r; //Raio da bola | definido em reiniciar
//Direção inicial da bola
var dir_x; //Definido em Reiniciar
var dir_y; //Definido em Reiniciar
var speed; //Definido em Reiniciar
//Variáveis da base
var alt_base = 10; //Altura da base
var lar_base = 60; //Largura da base
var x_base; //Definido no Reiniciar
bg.js
//Construção dos Tijolos
var larg_tij = 50; //Largura dos tijolos var altu_tij = 20; //Altura dos tijolos
var espa_tij = 10; //Espaço entre os tijolos
var n_tij_x = Math.floor((c.width - espa_tij) / (larg_tij + espa_tij)); //Máximo de tijolos var n_tij_y = 10; //10 linhas com tijolos
var tot_tij = n_tij_x * n_tij_y; //total de tijolos var tijs_x = newArray(); //Posição x do tijolo var tijs_y = new Array(); //Posição y do tijolo var tijs_v = new Array(); //Tijolo visível?
//Chama função que inicia todas variáveis para dar inicio ao jogo
bg.js
function Reiniciar() //Reiniciar partida
{
//Texto informativo
info_display.innerHTML = “Clique em Iniciar para jogar";
//Posicionamento da bola
ball_cx = Math.floor(c.width / 2); //Bola inicia no centro horizontal
ball_cy = Math.floor(c.height * 0.85); //Bola inicia em 85% da altura
ball_r = 0.0;
//Raio da bola é 1% da menor dimensão
if (c.width < c.height)
ball_r = Math.floor(c.width * 0.01);
else
bg.js
//Continuação da função Reiniciar //Posicionamento da Base
x_base = Math.floor(c.width / 2 - lar_base / 2); y_base = Math.floor(ball_cy + ball_r);
//Direção inicial da bola
dir_x = 0; dir_y = -7;
speed = Math.abs(dir_x) + Math.abs(dir_y);
//Construção dos Tijolos
IniciarTijolos();
//Desenhar a tela
Desenhar(); }
bg.js
//Criar cada um dos tijolos e os define visíveis
function IniciarTijolos() {
at = 0;
//Para cada linha prevista
for(linha_at = 0; linha_at < n_tij_y; linha_at++)
//Em cada linha, Para cada coluna prevista
for (coluna_at = 0; coluna_at < n_tij_x; coluna_at++) {
//Define um X, Y e Visível um novo Tijolo
tijs_x[at] = espa_tij + (coluna_at * (larg_tij + espa_tij)); tijs_y[at] = espa_tij + (linha_at * (altu_tij + espa_tij)); tijs_v[at++] = true;
} }
bg.js
//Atualiza, redesenha
function Desenhar() {
ctx.clearRect(0, 0, c.width, c.height); //Limpar a tela de desenho
desenharTijolos(); //Desenhar todos os tijolos criados
desenharBola(); //Desenhar a bola
desenharBase(); //Desenhar a base
bg.js
//Desenhar Tijolos
function desenharTijolos() {
//Para cada um dos Tijolos criados...
for (at = 0; at < tot_tij; at++) {
//Se o Tijolo estiver vísivel
if (tijs_v[at] == true) { //Desenha o Tijolo ctx.fillStyle = "#00FF00"; ctx.fillRect(tijs_x[at],tijs_y[at],larg_tij,altu_tij); } } }
bg.js
//Desenhar a Bola function desenharBola() { ctx.fillStyle = "#FF0000"; ctx.beginPath();ctx.arc(ball_cx, ball_cy, ball_r, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } //Desenhar a Base function desenharBase() { ctx.fillStyle = "#0000FF"; ctx.fillRect(x_base,y_base,lar_base,alt_base); }
COLOCANDO VIDA
O que precisamos?
•
Fazer a bola se movimentar:
–
Com qual intervalo de tempo?
•
E quando a bola bater em um Tijolo?
•
E quando a bola bater numa Parede?
•
E quando a bola bater na Base?
•
E quando a bola bater no Fundo?
•
E quando o usuário pressionar a Seta
Esquerda?
MOVIMENTAÇÃO DA BOLA
Movendo a Bola
•
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 um espaço percorrido a
cada unidade de tempo para a bola:
–
Variável: speed
•
Agora precisamos determinar o intervalo de
tempo que nosso jogo ira usar para fazer
cada movimento da bola;
•
Como nosso jogo gira em torno
principalmente da bola, este
tempo será como um guia 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);
bg.js
•
Crie as seguintes variáveis globais:
//Controle de execução
var
rodando =
false
;
var
relogio;
//Pausar ou retomar o jogo – Executado pelo btnStart function Pausar() { rodando = !rodando; if (rodando) {
relogio = setInterval("Desenhar()" , intervalo); info_display.innerHTML = "Executando..."; btnStart.innerHTML = "Pausar"; } else { clearInterval(relogio); info_display.innerHTML = "Pausa"; btnStart.innerHTML = "Iniciar"; } }
bg.js
bg.js
//Atualiza, redesenha, loop principal do jogo
function Desenhar() {
RecalcPos(); //Recalcular posição da bola
ctx.clearRect(0, 0, c.width, c.height); //Limpar a tela de desenho
desenharTijolos(); //Desenhar todos os tijolos criados
desenharBola(); //Desenhar a bola
desenharBase(); //Desenhar a base
bg.js
•
Incluir na função Reiniciar():
//Se estiver em execução, pausa
if
(rodando)
Pausar();
bg.js
//Recalcular a posição da bola
function RecalcPos() {
ball_cx += dir_x; //Incrementa movimento X a posição da bola
ball_cy += dir_y; //Incrementa movimento Y a posição da bola
}
DETECTANDO COLISÕES
Colisões
•
Durante a trajetória, a bola poderá
encontrar:
–
3 paredes diferentes;
–
A base do jogador;
–
Diversos tijolos;
–
O fundo do cenário (fim de jogo);
•
Cada um destes objetos deverá causar
uma mudança de direção diferente sob a
bola;
•
Num plano 2D, colisões são simples de serem detectadas:
– Colisão Inferior, Superior, Lateral Esquerda e Lateral Direita:– yt + altura <= yb – r r
Detectando Colisões
(xt, yt) (xb, yb) largura altur aDetectando Colisões
•
Num plano 2D, colisões são simples de serem detectadas:
– Colisão Inferior, Superior, Lateral Esquerda e Lateral Direita:– yt >= yb + r r (xt, yt) (xb, yb) largura altur a
r
Detectando Colisões
•
Num plano 2D, colisões são simples de serem detectadas:
– Colisão Inferior, Superior, Lateral Esquerda e Lateral Direita:– xt + largura >= xb – r (xt, yt) (xb, yb) largura altur a
•
Num plano 2D, colisões são simples de serem detectadas:
– Colisão Inferior, Superior, Lateral Esquerda e Lateral Direita:– xt <= xb + r r
Detectando Colisões
(xt, yt) (xb, yb) largura altur abg.js
//Verifica colisão com Paredes function VerificaParedes() { //Parede esquerda if (ball_cx - ball_r <= 0) { dir_x *= -1; } //Parede direita
if (ball_cx + ball_r >= c.width - 1) { dir_x *= -1; } //Parede superior if (ball_cy - ball_r <= 0) { dir_y *= -1; } }
Colisão na Base
•
Além de detectar a colisão com a base, precisamos identificar a
distância do centro, pois isto muda a direção da bola:
– var dist = ball_cx - (x_base + (lar_base / 2)); – dist /= (lar_base / 2);
– dir_x = dist * (speed * 0.75); // Máximo 1/4 da velocidade para X
bg.js
//Verifica colisão com Base
function VerificaBase() {
if (ball_cx + ball_r >= x_base && ball_cx - ball_r <= x_base + lar_base)
if (ball_cy + ball_r >= y_base && ball_cy + ball_r <= y_base + alt_base) {
var dist = ball_cx - (x_base + (lar_base / 2)); dist /= (lar_base / 2);
dir_x = dist * (speed * 0.75); dir_y = -(speed - Math.abs(dist)); }
Colisão nos Tijolos
•
A verificação de colisão em um tijolo é feita da mesma forma que
na base, porém teremos tot_tij de tijolos para verificar e não
apenas um;
•
Só podemos descobrir se não estamos batendo em algum Tijolo
depois de verificar cada um deles e constatar que não há colisão
nenhuma;
•
Ao bater em um tijolo, temos que constatar se a colisão foi
bg.js
//Verifica colisão com Tijolos function VerificaTijolos()
{ //Para cada um dos tijolos.. for (at = 0; at < tot_tij; at++)
{ //Se o tijolo atual for visível... if (tijs_v[at] == true)
{ //Verifico se há colisão com ele..
if (ball_cy - ball_r < tijs_y[at] + altu_tij && ball_cy + ball_r > tijs_y[at])
if (ball_cx - ball_r < tijs_x[at] + larg_tij && ball_cx + ball_r > tijs_x[at])
{ //Procuro pela distância da bola em relação as linhas do Tijolo var distx1 = Math.abs((ball_cx - ball_r) - (tijs_x[at] + larg_tij));
var distx2 = Math.abs((ball_cx + ball_r) - tijs_x[at]);
var disty1 = Math.abs((ball_cy - ball_r) - (tijs_y[at] + altu_tij));
var disty2 = Math.abs((ball_cy + ball_r) - tijs_y[at]);
if (distx2 < distx1)
distx1 = distx2;
if (disty2 < disty1)
bg.js
if (distx1 == disty1) //Bateu na quina
{
dir_y *= -1; dir_x *= -1; }
else if (distx1 < disty1) //Bateu em linha vertical
{
dir_x *= -1; }
else //Bateu em linha horizontal
{
dir_y *= -1; }
tijs_v[at] = false; //Tijolo batido, não é mais visível
} }
} }
Colisão no Fundo
•
Entenda “fundo” pela parte inferior da tela;
•
O que ocorre quando a bola encostar neste fundo?
–
Game Over!
•
Esta colisão será detectada de forma similar as laterais
e superior, mas será tratada de forma diferente!
bg.js
//Verifica Game Over
function
VerificaGameOver()
{
//Se estivermos em posição de game over..
if
(ball_cy + ball_r >= c.height - 1)
{
Pausar();
//Parar o jogo e informar o fim.
info_display.innerHTML =
"GAME OVER!"
;
}
Alterações na Iteração
•
O que falta alterar?
–
Qual é a função executada repetidas vezes a cada contagem
de tempo?
• Desenhar()
•
Todas as detecções que programamos, deve ser
bg.js
//Atualiza, redesenha e VERIFICA
function Desenhar() {
RecalcPos(); //Recalcular posição da bola
ctx.clearRect(0, 0, c.width, c.height); //Limpar a tela de desenho
VerificaParedes(); //NOVO – Verifica colisão
VerificaTijolos(); //NOVO – Verifica colisão
VerificaBase(); //NOVO – Verifica colisão
VerificaGameOver(); //NOVO – Verifica colisão
desenharTijolos(); //Desenhar todos os tijolos criados
desenharBola(); //Desenhar a bola
desenharBase(); //Desenhar a base
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 ira intervir basicamente
através de comandos!
Eventos!
•
Nosso
document
possuí propriedades de
eventos que podem ser associadas à
funções quaisquer;
•
Estas funções determinar algo a ser feito
quando aquele evento ocorrer:
– document
.onkeydown
•
Ao descer uma tecla qualquer;
– document
.onkeyup
bg.js
//Informações sobre teclas
var
rightDown =
false
;
var
leftDown =
false
;
//Eventos
document
.onkeydown=onKD;
bg.js
//rightDown ou leftDown para mover para os lados
function
onKD(evt) {
if
(evt.keyCode == 39) rightDown =
true
;
else if
(evt.keyCode == 37) leftDown =
true
;
}
//rightUp ou leftUp para parar de mover
function
onKU(evt) {
if
(evt.keyCode == 39) rightDown =
false
;
else if
(evt.keyCode == 37) leftDown =
false
;
}
bg.js
var move_base = 7; //Variável de velocidade da base //Recalcular a posição da bola E DA BASE
function RecalcPos() { if (leftDown) { x_base -= move_base; if (x_base < 0) x_base = 0; } if (rightDown) { x_base += move_base;
if (x_base + lar_base > c.width - 1)
x_base = (c.width - 1) - lar_base; }
ball_cx += dir_x; //Incrementa movimento X a posição da bola
ball_cy += dir_y; //Incrementa movimento Y a posição da bola
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:
–
bounce.mp_ e bounce.ogg;
–
brick.mp_ e brick.ogg; e
–
gameover.mp_ e gameover.ogg.
index.html
•
Adicionar dentro do <body>:
<audio controls
id
="bounce"
>
<source
src
="bounce.mp3"
type
="audio/mpeg"
>
<source
src
="bounce.ogg"
type
="audio/ogg"
>
</audio>
<audio controls
id
="brick"
>
<source
src
="brick.mp3"
type
="audio/mpeg"
>
<source
src
="brick.ogg"
type
="audio/ogg"
>
</audio>
<audio controls
id
="gameover"
>
<source
src
="gameover.mp3"
type
="audio/mpeg"
>
<source
src
="gameover.ogg"
type
="audio/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