Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
PHASER
www.number.890m.com
INTRODUCAO
O objetivo dessa apostila e explicar de forma simples e rapida os conceitos mais basicos do
uso do framework Phaser para a criacao de jogos para browsers. Para isso partiremos do exemplo
de jogo de plataforma 2d desenvolvido por Thomas Paleff.
Diego Oliveira.
2017 | nibblediego@gmail.com
www.number.890m.com
2
Contents
1 A GAME ENGINE PHASER 4
1.1 O QUE E O PHASER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 BAIXANDO O PHASER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 UM POUCO DE HTML 5
5 MENU DE JOGO 12
5.1 ADICIONANDO TEXTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
6 DIMENSIONAMENTO DE IMAGENS 16
3
1 A GAME ENGINE PHASER
www.number.890m.com
O Phaser e uma biblioteca JavaScript open source para desenvolvimento de jogos em HTML5
criado pela Photon Storm. Seu foco e criar jogos que rodam em navegadores como o Internet
Explorer 9 para cima, Firefox, Chrome e Safari. Em dispositivos moveis, o Phaser e suportado
no iOS5 para cima e no navegador Safari. No Android, ele e suportado a partir da versao
2.2 para cima tanto no navegador padrao quanto no Chrome mobile. O Phaser roda tambem
em dispositivos que utilizam o sistema Tizen e perfeitamente no Kindle com ajuda do HTML5
Wrapper, o que significa que voce pode utilizar os jogos nestes dispositivos sem problemas.
O projeto do Phaser esta hospedado no GitHub. O projeto possui dois branches (versoes
paralelas em desenvolvimento) esses branches sao:
A sugestao e que voce use sempre a ultima versao estavel (master). Uma vez que a dev
pode conter alguns bugs. Apos baixar o Phaser, recomenda-se que voce siga o guia oficial para
iniciantes (Getting Started Guide). O guia aborda a configuracao de um servidor web local, do
ambiente de desenvolvimento, e da programacao na nuvem se este for seu interesse. Tambem
mostra como utilizar o Phaser com um exemplo simples. Esse guia esta na pagina oficial do
Phaser escrito em ingles e atualmente nao possui traducao.
4
2 PREPARANDO O AMBIENTE DE DESENVOLVI-
MENTO
Vamos comecar criando duas pastas chamadas assets e js (embora voce possa colocar o
nome que bem entender) e um arquivo html.
A pasta assets ira conter as imagens, sons e arquivos visuais usados no jogo.
A pasta js, ira conter o framework phaser.
Ja o arquivo html ira conter todo o codigo javascript.
Dentro da pasta assets coloque as imagens que serao utilizadas. Nesse primeiro exemplo
vamos utilizar 4 imagens png com dimensoes 21 x 21.
3 UM POUCO DE HTML
Essa e a estrutura basica e um arquivo html e nao ha nele nenhuma novidade. O mais
importante aqui e a inclusao do arquivo phaser.min.js dentro da pasta js.
5
4 COMECANDO A USAR O PHASER
Agora estamos prontos para escrever o codigo do nosso jogo. Nesta apostila todo o nosso
javascript sera escrito dentro do body do html, mas convem lembrar que voce pode escreve-lo
num arquivo externo e linca-lo ao html. O que e ate recomendado pelos desenvolvedores web.
4 };
5
4.2 METODOS
Nao nos interessa muito criar estados vazios. Na verdade, desejamos que o estado real-
ize alguma(s) tarefa(s) e assim como todo objeto exploramos essa possibilidade por meio de
metodos.
7 create : function () {
8 // Aqui criamos o jogo .
9 },
10
11 update : function () {
12 /* Aqui atualizamos os dados do jogo a uma taxa de 60 fps . */
13 },
14 };
init: Esse metodo carrega variaveis que se iniciam com o jogo tais como contadores e etc.
Como inicialmente nao teremos nada do tipo nao sera necessario declara-lo.
6
preload: Esse metodo e responsavel por carregar imagens e sons que o jogo ira conter.
create: Esse metodo ira conter o jogo em si.
update: Esse metodo sera responsavel pela atualizacao dos dados do jogo. Isso sera feito
60 vezes por segundo (60 fps).
Voce pode modificar esses nomes (init, preload, etc.) desde que modifique de forma correta o
modo como se declara o estado (como se sabe o JavaScript possui mais de uma forma de declarar
um objeto), entretanto essa nomenclatura de tao adotada pela comunidade do phaser se tornou
quase oficial. Por isso voce vera esses nomes em quase todos os tutoriais disponveis na internet
(ou livros) o que facilita muito a leitura de codigos criados por terceiros. Aqui nao sera diferente!
Na linha:
Os valores 500 e 200 e o tamanho da tela que o jogo tera. O parametro Phaser.AUTO
da ao Phaser a liberdade de escolher automaticamente entre usar o WebGL ou Canvas para
renderizacao do jogo. Dando preferencia sempre ao WebGL.
Voce pode trocar o AUTO por CANVAS ou WEBGL, entretanto e recomendavel que voce
nao altere esse parametro.
Finalmente, entre as aspas duplas ( ) deve ficar a id da tag (do html) que ira conter o jogo.
Se voce deixar o espaco entre elas vazio entao o jogo sera exibido no canto superior esquerdo
da janela do browser.
Cada vez que quisermos usar imagens, sons, e etc., primeiro precisamos carrega-los. No caso
de uma imagem estatica, podemos fazer isso usando o: game.load.image na funcao preload.
1 preload : function () {
2 game . load . image ( player , assets / player . png ) ;
3 game . load . image ( wall , assets / wall . png ) ;
4 game . load . image ( coin , assets / coin . png ) ;
5 game . load . image ( enemy , assets / enemy . png ) ;
6 },
Onde o primeiro valor entre aspas simples ( e ) e o novo nome que sera utilizado para fazer
referencia a imagem. E o segundo o caminho para a imagem.
Note que o nosso jogo ira conter 4 imagens e todas elas estao no interior da pasta assets.
Agora vamos adicionar algumas configuracoes no jogo, para isso, adicione o seguinte dentro
da funcao create().
7
4 // Adiciona o motor ARCADE
5 game . physics . startSystem ( Phaser . Physics . ARCADE ) ;
6
A ARCADE e um motor de jogo que nos permite simular um sistema de fsica no jogo.
O Phaser contem outras tres bibliotecas sendo a ARCADE a mais simples, a que menos exige
do hardware e por experiencia propria a que menos da problema.
Vamos agora adicionar o jogador que podemos controlar com as teclas direcionais. Para isso
adicione o seguinte tambem dentro da funcao create() .
A linha 02 cria um ouvinte (listener) para as teclas up, down, left e right retornando um valor
de true para cada uma delas sempre que forem pressionadas.
A linha 05 cria o player nas coordenadas (70, 100) da tela do jogo usando a imagem que
nomeamos como player (veja item 4.3) na funcao preload.
Se voce testar o codigo agora podera notar que o sprite do player nao esta exatamente
centrado. Isso porque o x e o y que estabelecemos em game.add.sprite e a posicao do canto
superior esquerdo do sprite, tambem chamado de ponto de ancoragem. Portanto, e o canto
superior esquerdo do jogador que esta realmente centrado, como voce pode ver aqui:
Voce pode corrigir isso, embora neste caso nao venha a ser de muita utilidade, alterando a
posicao do ponto de ancoragem. Aqui estao alguns exemplos de como podemos fazer isso:
8
8 this . player . anchor . setTo (0 , 1) ;
9
0,0 1,0
0,1 1,1
Para centralizar o sprite voce pode definir o ponto de ancoragem para o meio do sprite.
Assim, adicione na funcao create:
1 this . player . anchor . setTo (0.5 , 0.5) ;
Adicionamos o player, gravidade, ouvintes para o teclado e toda uma fsica ao mundo. Agora
esta na hora de fazer o jogador andar e saltar. Para isso adicione o seguinte na funcao update()
.
O proximo passo e ter um nvel para o nosso jogador. Podemos configura-lo assim, na funcao
create() .
9
7 var level = [
8 x xx xx xx xxx xx xx xxx xx xx x ,
9 ! ! x,
10 ! o x,
11 ! o x,
12 ! x,
13 ! o ! x x,
14 xxxxxxxxxxxxxxxx !!!!! x ,
15 ];
E para realmente ter o nvel exibido, adicione isso logo abaixo do codigo anterior.
Observe que esta nao e uma maneira muito eficiente de criar o cenario. Atualmente, temos
cerca de 50 pequenas paredes, mas podemos reduzir esse numero para 4 se esticassemos as
paredes horizontalmente ou verticalmente. Essa otimizacao sera explicada mais a frente.
Finalmente, precisamos lidar com todas as colisoes da nossa plataforma. Para isso acrescente
o codigo a seguir, logo no incio, da funcao update() .
10
5 game . physics . arcade . overlap ( this . player , this . coins , this . takeCoin ,
null , this ) ;
6
6 // reinicia o game
7 restart : function () {
8 game . state . start ( jogo ) ;
9 }
4.8 RESULTADO
Aqui esta uma imagem do nosso pequeno jogo de plataformas 2D que construmos juntos.
No proximo tutorial partiremos deste ponto para aprendermos mais sobre o Phaser.
11
Codigo completo do jogo.
Embora seja tentador recomendo que o leitor nao copie e cole o codigo a seguir, mas que va
escrevendo enquanto tenta se lembrar a funcao de cada linha.
12
53 }
54
83 restart : function () {
84 game . state . start ( jogo ) ;
85 }
86 };
87
5 MENU DE JOGO
Normalmente os jogos possuem uma tela inicial antes de tudo. Vamos fazer uma.
Primeiro criamos um novo estado chamado mainState com os metodos preload, e create
e update.
1 var mainState = {
2 preload : function () {
3 game . load . image ( player , assets / image / player . png ) ;
13
4 game . load . image ( wall , assets / image / wall . png ) ;
5 game . load . image ( coin , assets / image / coin . png ) ;
6 game . load . image ( enemy , assets / image / enemy . png ) ;
7 game . load . image ( logo , assets / image / logo . png ) ;
8 },
9 create : function () {
10 game . stage . backgroundColor = #3598 db ;
11 this . cursor = game . input . keyboard . createCursorKeys () ;
12 this . logo = game . add . sprite (70 , 100 , logo ) ;
13 },
14 update : function () {
15 if ( this . game . input . mousePointer . isDown ) {
16 // Chama o estado game
17 game . state . start ( game ) ;
18 }
19 }
20 };
Na funcao preload foi colocado todas as imagens usadas anteriormente mais uma (logo.png)
que sera o logotipo do jogo. Com isso tambem eliminamos a necessidade da funcao no estado
jogoState uma vez que as imagens ja estao sendo carregadas aqui.
Na funcao update foi utilizada um novo metodo o mousePointer. Ele basicamente retorna
um valor de true quando o ponteiro do mouse e pressionado sobre a tela do jogo. Quando isso
ocorrer sera chamado o estado jogo (que e o estado atual do jogo).
para
14
5.1 ADICIONANDO TEXTO
Voce pode colocar alguma informacao na tela de menu como por exemplo um aviso de que
e necessario clicar na tela para iniciar. O metodo utilizado para tal fim e o text ele deve ser
acrescentado dentro da funcao create.
15
Codigo completo do jogo.
Novamente e apresentado o codigo escrito ate agora, entretanto dessa vez vai ser escrito
apenas o que foi modificado.
24 var jogoState = {
25 create : function () {
26 /* o codigo que estava aqui */
27
28 },
29 update : function () {
30 /* o codigo que estava aqui */
31 },
32
16
6 DIMENSIONAMENTO DE IMAGENS
Anteriormente foi dito que existe uma forma mais eficiente de criar o cenario. No momento
temos 50 pequenas paredes quando poderamos ter apenas 4 se esticassemos as imagens.
1 preload : function () {
2 game . load . image ( player , player . png ) ;
3 },
4 create : function () {
5 var player = game . add . sprite (20 , 20 , player ) ;
6
7 /* Reduz uma imagem em 50%. Pode ser usado para ampliar imagens
tambem . */
8 player . scale . set (0.5) ;
9 },
Esse mesmo metodo pode ser usado para gerar um escalamento vertical ou horizontal de
forma independente uma da outra.
1 preload : function () {
2 game . load . image ( player , assets / image / player . png ) ;
3 },
4 create : function () {
5 var player = game . add . sprite (20 , 20 , player ) ;
6
7 /* Escala x somente */
8 player . scale . x = 0.3;
9
10 /* Escala y somente */
11 player . scale . y = 0.8;
12 },
Primeiro criamos mais tres funcoes. Vamos escreve-las abaixo da funcao restart.
1 restart : function () {
2 game . state . start ( jogo ) ;
3 },
4
5 writeCoin : function () {
6
7 },
8
9 writeWall : function () {
10
11 },
12
17
13 writeEnemie : function () {
14
15 }
1 writeCoin : function (x , y ) {
2 var coin = game . add . sprite (x , y , coin ) ;
3 this . coins . add ( coin ) ;
4 },
1 writeWall : function (x , y , w , h ) {
2 var wall = game . add . sprite (x , y , wall ) ;
3 wall . scale . x = w ;
4 wall . scale . y = h ;
5 this . walls . add ( wall ) ;
6 wall . body . immovable = true ;
7 },
8
9 writeEnemie : function (x , y , w , h ) {
10 var enemy = game . add . sprite (x , y , enemy ) ;
11 enemy . scale . x = w ;
12 enemy . scale . y = h ;
13 this . enemies . add ( enemy ) ;
14 }
Agora podemos alterar o nosso codigo chamando essas funcoes sempre que necessario. O
codigo completo (com os valores que voce ira precisar passar como parametro) se encontra na
pagina a seguir.
Lembre-se que quanto menos hardware um jogo consome, melhor sera o seu desempenho em
termos de processamento. Cinquenta verificacoes a 60fps para o browser de um PC nao e muito,
mas para um tablet ou smartphone e crtico.
Existe ainda a possibilidade de criar o cenario por meio de um programa especfico (recomenda-
se o Tiled) e salva-lo como um arquivo json.
18
Codigo completo.
1 var jogoState = {
2 create : function () {
3 // Codigo que estava aqui
4
7 // inimigos
8 this . writeEnemie (42 , 50 , 1 , 5) ;
9 this . writeEnemie (336 , 155 , 5 , 1) ;
10 this . writeEnemie (200 , 51 , 1 , 1) ;
11 this . writeEnemie (200 , 135 , 1 , 1) ;
12
13 // paredes
14 this . writeWall (42 , 30 , 20 , 1) ;
15 this . writeWall (42 , 155 , 14 , 1) ;
16 this . writeWall (315 , 135 , 1 , 1) ;
17 this . writeWall (441 , 50 , 1 , 6) ;
18
19 // moedas
20 this . writeCoin (200 , 93) ;
21 this . writeCoin (375 , 70) ;
22 this . writeCoin (150 , 134) ;
23 },
24
27 restart : function () {
28 game . state . start ( jogo ) ;
29 },
30
31 writeCoin : function (x , y ) {
32 var coin = game . add . sprite (x , y , coin ) ;
33 this . coins . add ( coin ) ;
34 },
35
36 writeWall : function (x , y , w , h ) {
37 var wall = game . add . sprite (x , y , wall ) ;
38 wall . scale . x = w ;
39 wall . scale . y = h ;
40 this . walls . add ( wall ) ;
41 wall . body . immovable = true ;
42 },
43
44 writeEnemie : function (x , y , w , h ) {
45 var enemy = game . add . sprite (x , y , enemy ) ;
46 enemy . scale . x = w ;
47 enemy . scale . y = h ;
48 this . enemies . add ( enemy ) ;
49 }
50 };
19