aboutsummaryrefslogtreecommitdiff
path: root/files/es/games/tutorials/html5_gamedev_phaser_device_orientation/index.html
blob: 26b3eb46f1bbb706a5a33b12f56be595752916fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
---
title: >-
  Introducción al Desarrollo de Juegos en HTML5 con Phaser y la API de
  Orientación a Dispositivos
slug: Games/Tutorials/HTML5_Gamedev_Phaser_Device_Orientation
tags:
  - API Vibración
  - API orientacion de dispositivos
  - Canvas
  - Desarrollo de videojuegos
  - HTML5
  - Phaser
translation_of: Games/Tutorials/HTML5_Gamedev_Phaser_Device_Orientation
original_slug: Games/Workflows/HTML5_Gamedev_Phaser_Device_Orientation
---
<div>{{GamesSidebar}}</div><p>{{ draft() }}</p>

<h2 id="Introducción">Introducción</h2>

<p><span style="line-height: 1.5;">En este tutorial iremos a través del proceso de construcción de un juego en HTML5 para móviles que utilizará las <em>APIs</em> de <a href="https://developer.mozilla.org/en-US/Apps/Build/gather_and_modify_data/responding_to_device_orientation_changes">Orientación para Dispositivos</a> y <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/Vibration">Vibración</a> para mejorar la jugabilidad y estará construido utilizando el <em>framework</em> <a href="http://phaser.io/">Phaser</a>. Se recomienda tener conocimientos básicos de JavaScript para sacar mayor provecho a este tutorial.</span></p>

<h2 id="Ejemplo"><span style="line-height: 1.5;">Ejemplo</span></h2>

<p><span style="line-height: 1.5;">Al finalizar este tutorial tendrás un juego <em>demo</em> completamente funcional: <a href="http://orb.enclavegames.com/">Cyber Orb</a>. Se verá más o menos así:</span></p>

<p><span style="line-height: 1.5;"><img alt="" src="https://mdn.mozillademos.org/files/10297/cyber-orb.png" style="display: block; height: 450px; margin: 0px auto; width: 300px;"></span></p>

<h2 id="Phaser_framework">Phaser framework</h2>

<p><a href="http://phaser.io/">Phaser</a> es un <em>framework</em> para construir juegos, de móvil o escritorio, en HTML5 . Es nuevo pero está creciendo velozmente gracias a la apasionada comunidad involucrada en el proceso de desarrollo. Puedes chequearlo <a href="https://github.com/photonstorm/phaser">en GitHub</a> donde se encuentra como <em>open source. </em>Lee <a href="http://docs.phaser.io/">la documentación</a> en línea y recorre su gran colección de <a href="http://examples.phaser.io/">ejemplos</a>. El <em>framework</em> Phaser provee una serie de herramientas que acelerarán el desarrollo y te ayudaran a manejar las tareas genéricas necesarias para completar tu juego, para que así puedas concentrarte en la idea del juego en sí.</p>

<h2 id="Empezando_con_el_proyecto">Empezando con el proyecto</h2>

<p>Puedes ver <a href="https://github.com/EnclaveGames/Cyber-Orb">el código fuente de Cyber Orb</a> en GitHub. <span style="line-height: 1.5;">La estructura de carpetas no es nada complicada: </span><span style="line-height: 1.5;">el punto de partida es el archivo </span><code>index.html</code><span style="line-height: 1.5;"> donde inicializaremos el <em>framework</em> y </span><span style="line-height: 1.5;">configuraremos el canvas donde correrá el juego.</span></p>

<p><img alt="" src="https://mdn.mozillademos.org/files/10357/cyber-orb-github.png" style="display: block; height: 423px; width: 620px;"></p>

<p><span style="line-height: 1.5;">Puedes hacer clic en el archivo index desde tu navegador favorito para iniciar el juego y probarlo. </span><span style="line-height: 1.5;">También hay tres carpetas en el directorio: </span></p>

<ul>
 <li><span style="line-height: 1.5;"><code>img</code></span>: Todas las imágenes que usaremos en el juego.</li>
 <li><span style="line-height: 1.5;"><code>src</code></span>: Los archivos JavaScript que contienen todo el código fuente del juego definido dentro.</li>
 <li><span style="line-height: 1.5;"><code>audio</code>:</span> Los archivos de sonido usados en el juego.</li>
</ul>

<h2 id="Configurando_el_canvas">Configurando el canvas</h2>

<p>Vamos a renderizar nuestro juego sobre el elemento <code>&lt;canvas&gt;</code>, pero no lo haremos manualmente  — de esto se ocupará el <em>framework. </em> Vamos a configurarlo: nuestro punto de partida es el archivo <code>index.html</code> con el siguiente contenido. Puedes crearlo tú mismo si quieres hacer un seguimiento más detallado:</p>

<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8" /&gt;
    &lt;title&gt;Cyber Orb&lt;/title&gt;
    &lt;style&gt; body { margin: 0; background: #333; } &lt;/style&gt;
    &lt;script src="src/phaser.min.js"&gt;&lt;/script&gt;
    &lt;script src="src/Boot.js"&gt;&lt;/script&gt;
    &lt;script src="src/Preloader.js"&gt;&lt;/script&gt;
    &lt;script src="src/MainMenu.js"&gt;&lt;/script&gt;
    &lt;script src="src/Game.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script&gt;
(function() {
    var game = new Phaser.Game(320, 480, Phaser.CANVAS, 'game');
    game.state.add('Boot', Ball.Boot);
    game.state.add('Preloader', Ball.Preloader);
    game.state.add('MainMenu', Ball.MainMenu);
    game.state.add('Game', Ball.Game);
    game.state.start('Boot');
})();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>

<p><span style="line-height: 1.5;">Hasta ahora tenemos una simple página web </span><code>HTML</code><span style="line-height: 1.5;"> con el contenido básico en la sección </span><code>&lt;head&gt;</code><span style="line-height: 1.5;">: configuración de caracteres, título, estilo y las inclusión de los archivos JavaScripts. El </span><code>&lt;body&gt;</code><span style="line-height: 1.5;"> contiene la inicialización del framework Phaser y las definiciones del estado del juego.</span></p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">var</span> game <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Phaser<span class="punctuation token">.</span>Game</span><span class="punctuation token">(</span><span class="number token">320</span><span class="punctuation token">,</span> <span class="number token">480</span><span class="punctuation token">,</span> Phaser<span class="punctuation token">.</span>CANVAS<span class="punctuation token">,</span> <span class="string token">'game'</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>La linea de arriba inicializará la intancia de Phaser — los argumentos son el ancho del <code>&lt;canvas&gt;</code>, su altura, el método de renderizado (estamos utilizando <code>CANVAS</code> pero también existen disponibles las opciones <code>WEBGL</code> y <code>AUTO</code>) y el ID opcional del contenedor DOM en el que queremos poner el <code>&lt;canvas&gt;</code>. Si no hay nada especificado en el último argumento o el elemento no es encontrado, el <code>&lt;canvas&gt;</code> será añadido a la etiqueta <code>&lt;body&gt;</code>. Sin el <em>framework </em>para añadir el elemento canvas hubieses tenido que escribir algo como esto dentro de la etiqueta <code>&lt;body&gt;</code>:</p>

<pre class="brush: html line-numbers  language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>canvas</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">'</span>game<span class="punctuation token">'</span></span> <span class="attr-name token">width</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">'</span>320<span class="punctuation token">'</span></span> <span class="attr-name token">height</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">'</span>480<span class="punctuation token">'</span></span><span class="punctuation token">&gt;</span></span><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>canvas</span><span class="punctuation token">&gt;</span></span></code></pre>

<p>Es importante recordar que el <em>framework</em> está montando métodos útiles para acelerar un montón de cosas como la manipulación de imagenes o la administración de elementos, que serían más difíciles si tuvieramos que hacerlo manualmente.</p>

<div class="note">
<p><strong>Nota</strong>: Puedes leer este artículo: "<a href="http://gamedevelopment.tutsplus.com/tutorials/getting-started-with-phaser-building-monster-wants-candy--cms-21723">Building Monster Wants Candy</a>" para una introducción en profundidad a las funciones y métodos específicos de Phaser.</p>
</div>

<p>Volviendo a los estados del juego: La linea de abajo añade un nuevo estado al juego llamado <code>Boot</code>:</p>

<pre class="brush: js"><code class="language-html">game.state.add('Boot', Ball.Boot);</code></pre>

<p>El primer valor es el nombre del estado, el segundo es el objeto al que queremos asignárselo. El metodo <code>start</code> está iniciando el estado dado y haciendolo activo. Veamos qué es lo que son los estados realmente.</p>

<pre class="brush: html"> </pre>

<h2 id="Gestionando_los_estados_de_juego">Gestionando los estados de juego</h2>

<p>Los estados en Phaser son partes separadas de la lógica del juego, en nuestro caso los estamos cargando de archivos JavaScript independientes para un mejor mantenimiento. En este juego tenemos estados básicos: <code>Boot</code>, <code>Preloader</code>, <code>MainMenu</code>, <code>Howto</code> y <code>Game</code>. <code>Boot</code> se hará cargo de la inicialización de algunas opciones de configuración, <code>Preloader</code> cargará todos los elementos utilizados como los gráficos y el audio, <code>MainMenu</code> es el menu con el botón de inicio, <code>Howto</code> muestra las intrucciones de cómo jugar y el estado <code>Game</code> es el que finalmente te permite jugar el juego. Veamos rapidamente el contenido de esos estados.</p>

<h3 id="Boot.js">Boot.js</h3>

<p>El estado <code>Boot</code> es el primero en el juego.</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">var</span> Ball <span class="operator token">=</span> <span class="punctuation token">{</span>
    _WIDTH<span class="punctuation token">:</span> <span class="number token">320</span><span class="punctuation token">,</span>
    _HEIGHT<span class="punctuation token">:</span> <span class="number token">480</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span>
Ball<span class="punctuation token">.</span>Boot <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>game<span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">;</span>
Ball<span class="punctuation token">.</span>Boot<span class="punctuation token">.</span>prototype <span class="operator token">=</span> <span class="punctuation token">{</span>
    preload<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">image</span><span class="punctuation token">(</span><span class="string token">'preloaderBg'</span><span class="punctuation token">,</span> <span class="string token">'img/loading-bg.png'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">image</span><span class="punctuation token">(</span><span class="string token">'preloaderBar'</span><span class="punctuation token">,</span> <span class="string token">'img/loading-bar.png'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span><span class="punctuation token">,</span>
    create<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>scale<span class="punctuation token">.</span>scaleMode <span class="operator token">=</span> Phaser<span class="punctuation token">.</span>ScaleManager<span class="punctuation token">.</span>SHOW_ALL<span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>scale<span class="punctuation token">.</span>pageAlignHorizontally <span class="operator token">=</span> <span class="keyword token">true</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>scale<span class="punctuation token">.</span>pageAlignVertically <span class="operator token">=</span> <span class="keyword token">true</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>state<span class="punctuation token">.</span><span class="function token">start</span><span class="punctuation token">(</span><span class="string token">'Preloader'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre>

<p>El objeto principal <code>Ball</code> es definido y estamos añadiendo dos variables llamadas <code>_WIDTH</code> y <code>_HEIGHT</code> esos seran el ancho y la altura del canvas de nuestro juego, respectivamente — nos ayudarán a posicionar los elementos en la pantalla. Estamos cargando dos imagenes primero que serán usadas después en el estado <code>Preload</code> para mostrar el progreso de la carga de los demás elementos. La función <code>create</code> contiene algunas de las configuraciones básicas: estamos configurando la escala y la alineación del canvas, y avanzando al estado <code>Preload</code> cuando todo este listo.</p>

<h3 id="Preloader.js">Preloader.js</h3>

<p>El estado <code>Preloader</code> se ocupa de cargar todos los elementos:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js">Ball<span class="punctuation token">.</span>Preloader <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>game<span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">;</span>
Ball<span class="punctuation token">.</span>Preloader<span class="punctuation token">.</span>prototype <span class="operator token">=</span> <span class="punctuation token">{</span>
    preload<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>preloadBg <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">sprite</span><span class="punctuation token">(</span><span class="punctuation token">(</span>Ball<span class="punctuation token">.</span>_WIDTH<span class="number token">-297</span><span class="punctuation token">)</span><span class="operator token">*</span><span class="number token">0.5</span><span class="punctuation token">,</span> <span class="punctuation token">(</span>Ball<span class="punctuation token">.</span>_HEIGHT<span class="number token">-145</span><span class="punctuation token">)</span><span class="operator token">*</span><span class="number token">0.5</span><span class="punctuation token">,</span> <span class="string token">'preloaderBg'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>preloadBar <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">sprite</span><span class="punctuation token">(</span><span class="punctuation token">(</span>Ball<span class="punctuation token">.</span>_WIDTH<span class="number token">-158</span><span class="punctuation token">)</span><span class="operator token">*</span><span class="number token">0.5</span><span class="punctuation token">,</span> <span class="punctuation token">(</span>Ball<span class="punctuation token">.</span>_HEIGHT<span class="number token">-50</span><span class="punctuation token">)</span><span class="operator token">*</span><span class="number token">0.5</span><span class="punctuation token">,</span> <span class="string token">'preloaderBar'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">setPreloadSprite</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>preloadBar<span class="punctuation token">)</span><span class="punctuation token">;</span>

        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">image</span><span class="punctuation token">(</span><span class="string token">'ball'</span><span class="punctuation token">,</span> <span class="string token">'img/ball.png'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="comment token">// ...</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">spritesheet</span><span class="punctuation token">(</span><span class="string token">'button-start'</span><span class="punctuation token">,</span> <span class="string token">'img/button-start.png'</span><span class="punctuation token">,</span> <span class="number token">146</span><span class="punctuation token">,</span> <span class="number token">51</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="comment token">// ...</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>load<span class="punctuation token">.</span><span class="function token">audio</span><span class="punctuation token">(</span><span class="string token">'audio-bounce'</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="string token">'audio/bounce.ogg'</span><span class="punctuation token">,</span> <span class="string token">'audio/bounce.mp3'</span><span class="punctuation token">,</span> <span class="string token">'audio/bounce.m4a'</span><span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span><span class="punctuation token">,</span>
    create<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>state<span class="punctuation token">.</span><span class="function token">start</span><span class="punctuation token">(</span><span class="string token">'MainMenu'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre>

<p>Para crear un nuevo botón tenemos el método <code>add.button</code> con la siguiente lista de argumentos opcionales:</p>

<ul>
 <li>Posición absoluta superior del canvas, en pixeles.</li>
 <li>Posición absoluta izquierda del canvas, en pixeles.</li>
 <li>Nombre del elemento imagen utilizado por el botón.</li>
 <li>Función que será ejecutada cuando alguien haga click sobre el botón.</li>
 <li>El contexto de la ejecución.</li>
 <li>Cuadro (<em>frame) </em>del elemento imagen utilizado para el estado 'hover' del botón (cuando el mouse se encuentra sobre él).</li>
 <li>Cuadro (<em>frame)</em> del elemento imagen utilizado para el estado 'normal' o 'out' del botón.</li>
 <li>Cuadro (<em>frame) </em>del elemento imagen utilizado para el 'click' o 'down' del botón.</li>
</ul>

<p>El <code>anchor.set</code> colocará el punto de ancla en el botón con el cual se realizarán y aplicarán todos los cálculos de posición para el botón. En nuestro caso, está anclado a la mitad del borde izquierdo y al comienzo del borde superior, para así centrarlo de manera horizontal facilmente, sin necesidad de saber su ancho.</p>

<p>Cuando el boton de inicio es presionado, en lugar de saltar directamente a la acción, el juego mostrará la pantalla con las intrucciones para jugar.</p>

<h3 id="Howto.js">Howto.js</h3>

<pre class="brush: js line-numbers  language-js"><code class="language-js">Ball<span class="punctuation token">.</span>Howto <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>game<span class="punctuation token">)</span> <span class="punctuation token">{</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span>
Ball<span class="punctuation token">.</span>Howto<span class="punctuation token">.</span>prototype <span class="operator token">=</span> <span class="punctuation token">{</span>
    create<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>buttonContinue <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">button</span><span class="punctuation token">(</span><span class="number token">0</span><span class="punctuation token">,</span> <span class="number token">0</span><span class="punctuation token">,</span> <span class="string token">'screen-howtoplay'</span><span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>startGame<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span><span class="punctuation token">,</span>
    startGame<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>state<span class="punctuation token">.</span><span class="function token">start</span><span class="punctuation token">(</span><span class="string token">'Game'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre>

<p>El estado <code>Howto</code> muesta las intrucciones de juego en la pantalla antes de comenzar el juego. Luego de clickear la pantalla el juego es lanzado.</p>

<h3 id="Game.js">Game.js</h3>

<p>El estado <code>Game</code> del archivo <code>Game.js</code> es donde ocurre toda la magia. Todas las inicializaciones estan en la función <code>create()</code> (que se lanza una vez al comienzo del juego). Luego de eso, algunas funcionalidades requeriran más código para controlar — escribiremos nuestras propias funciones para manejar tareas más complicadas. En particular, toma nota de la función <code>update()</code> que es ejecutada en cada <em>frame </em>y actualiza cosas como la posición de la pelota.</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js">Ball<span class="punctuation token">.</span>Game <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>game<span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">;</span>
Ball<span class="punctuation token">.</span>Game<span class="punctuation token">.</span>prototype <span class="operator token">=</span> <span class="punctuation token">{</span>
    create<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    initLevels<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    showLevel<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>level<span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    updateCounter<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    managePause<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    manageAudio<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    update<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    wallCollision<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    handleOrientation<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span><span class="punctuation token">,</span>
    finishLevel<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span><span class="punctuation token">}</span>
<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre>

<p>Las funciones <code>create</code> y <code>update</code> son específicas del <em>framework</em>, mientras que otras seran nuestras propias creaciones:</p>

<ul>
 <li><code>initLevels</code> inicializa los datos del nivel.</li>
 <li><code>showLevel</code> imprime los datos del nivel en la pantalla.</li>
 <li><code>updateCounter</code> actualiza el tiempo dedicado a jugar cada nivel y registra el tiempo total dedicado al juego.</li>
 <li><code>managePause</code> pausa y reanuda el juego.</li>
 <li><code>manageAudio</code> enciende y apaga el audio.</li>
 <li><code>wallCollision</code> es ejecutado cuando la pelota golpea las paredes u otros objetos.</li>
 <li><code>handleOrientation</code> es la función ligada al evento responsable por la API de orientación de dispositivo, proporciona los controles de movimiento cuando el juego es ejecutado en un dispositivo móvil con el hardware apropiado.</li>
 <li><code>finishLevel</code> carga un nuevo nivel cuando se completa el nivel actual, o termina el juego si se completa el nivel final.</li>
</ul>

<h4 id="Agregando_la_pelota_y_sus_mecanismos_de_movimiento">Agregando la pelota y sus mecanismos de movimiento</h4>

<p>Primero vamos a ir a la función <code>create()</code>, inicializamos el objeto <code>ball</code> y le asignamos unas cuantas propiedades:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>ball <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">sprite</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>ballStartPos<span class="punctuation token">.</span>x<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>ballStartPos<span class="punctuation token">.</span>y<span class="punctuation token">,</span> <span class="string token">'ball'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>anchor<span class="punctuation token">.</span><span class="keyword token">set</span><span class="punctuation token">(</span><span class="number token">0.5</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>physics<span class="punctuation token">.</span><span class="function token">enable</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">,</span> Phaser<span class="punctuation token">.</span>Physics<span class="punctuation token">.</span>ARCADE<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">setSize</span><span class="punctuation token">(</span><span class="number token">18</span><span class="punctuation token">,</span> <span class="number token">18</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>bounce<span class="punctuation token">.</span><span class="keyword token">set</span><span class="punctuation token">(</span><span class="number token">0.3</span><span class="punctuation token">,</span> <span class="number token">0.3</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>Aqui estamos agregando un sprite en un lugar de la pantalla y utilizando la imagen de la pelota de los elementos gráficos ya cargados. También estamos configurando el <code>anchor</code> (ancla) que realizará los cálculos de física para el centro de la pelota, habilitando el motor de físicas Arcade (que manejara todas las físicas para el movimiento de la pelota), y estableciendo el tamaño del cuerpo para la detección de colisiones. La propiedad <code>bounce</code> es utilizada para configurar el 'rebote' de la pelota cuando golpea los obstaculos.</p>

<h4 id="Controlando_la_pelota">Controlando la pelota</h4>

<p>Es genial tener lista la pelota para poder lanzarla en la zona del juego, pero también es importante poder realmente moverla! Ahora vamos a añadir la capacidad de controlar con el teclado la pelota en los dispositivos de escritorio, y luego pasaremos a la implementación de la API de Orientación de Dispositivo. Vamos a enfocarnos en el teclado primero añadiendo lo siguiente a la función <code>create()</code>:</p>

<pre class="brush: js">this.keys = this.game.input.keyboard.createCursorKeys();</pre>

<p>Como puedes ver, hay una función especial de Phaser llamada <code>createCursorKeys()</code> que nos dará un objeto con controladores de evento para las cuatro teclas de flecha, que nos permitira jugar con: arriba, abajo, izquierda y derecha.</p>

<p>A continuación añadiremos el siguiente código a la función <code>update()</code>, para que sea ejecutado en cada <em>frame</em>. El objeto <code>this.keys</code> será chequeado con el input del jugador (las teclas que presione por ejemplo) así la pelota podrá reaccionar acorde, con una fuerza predefinida:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>keys<span class="punctuation token">.</span>left<span class="punctuation token">.</span>isDown<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>x <span class="operator token">-</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>movementForce<span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="keyword token">else</span> <span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>keys<span class="punctuation token">.</span>right<span class="punctuation token">.</span>isDown<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>x <span class="operator token">+</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>movementForce<span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>keys<span class="punctuation token">.</span>up<span class="punctuation token">.</span>isDown<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>y <span class="operator token">-</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>movementForce<span class="punctuation token">;</span>
<span class="punctuation token">}</span>
<span class="keyword token">else</span> <span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>keys<span class="punctuation token">.</span>down<span class="punctuation token">.</span>isDown<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>y <span class="operator token">+</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>movementForce<span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p>De esa manera podemos verificar qué tecla es presionada en determinado <em>frame</em> y aplicar la fuerza definida a la pelota, así aumentar la velocidad en la dirección correcta.</p>

<h4 id="Implementando_la_API_de_Orientación_del_Dispositivo">Implementando la API de Orientación del Dispositivo</h4>

<p>Probablemente la parte más interesante del juego es que utiliza la API de Orientación para Dispositivos móviles. Gracias a esto puedes jugar el juego inclinando el dispositivo en la dirección que quieres que la pelota ruede. Aquí está el código de la función <code>create()</code><em> </em>responsable por esto:</p>

<pre class="brush: js">window.addEventListener("deviceorientation", this.handleOrientation, true);</pre>

<p>Vamos a añadir un detector de eventos al evento "<code>deviceorientation</code>" y vincularlo a la función <code>handleOrientation</code>, se ve como esto:</p>

<pre class="brush: js">handleOrientation: function(e) {
    var x = e.gamma;
    var y = e.beta;
<code class="language-js">    Ball<span class="punctuation token">.</span>_player<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>x <span class="operator token">+</span><span class="operator token">=</span> x<span class="punctuation token">;</span>
    Ball<span class="punctuation token">.</span>_player<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>y <span class="operator token">+</span><span class="operator token">=</span> y<span class="punctuation token">;</span></code>
}</pre>

<p><span style="line-height: 1.5;">Mientras más inclines el dispositivo, más fuerza se aplica a la pelota y la velocidad en la que se mueve es mayor.</span></p>

<p><span style="line-height: 1.5;"><img alt="" src="https://mdn.mozillademos.org/files/10369/cyber-orb-flame-orientation.png"></span></p>

<div class="note">
<p><span style="line-height: 1.5;"><strong>Nota</strong>: Para encontrar más sobre implementar la orientación de los dispositivos y cómo se vé en código crudo, lee </span> <a href="https://developer.mozilla.org/en-US/Apps/Build/gather_and_modify_data/responding_to_device_orientation_changes">Keep it level: responding to device orientation changes</a>.</p>
</div>

<h4 id="Añadiendo_el_agujero">Añadiendo el agujero</h4>

<p>El principal objetivo del juego es mover la pelota desde la posición inicial a la posición final: un agujero en el suelo. Esta implementación es muy similar a la parte anterior en donde creamos la pelota, y también es añadida en la función <code>create()</code> de nuestro estado <code>Game</code>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>hole <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">sprite</span><span class="punctuation token">(</span>Ball<span class="punctuation token">.</span>_WIDTH<span class="operator token">*</span><span class="number token">0.5</span><span class="punctuation token">,</span> <span class="number token">90</span><span class="punctuation token">,</span> <span class="string token">'hole'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>physics<span class="punctuation token">.</span><span class="function token">enable</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>hole<span class="punctuation token">,</span> Phaser<span class="punctuation token">.</span>Physics<span class="punctuation token">.</span>ARCADE<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>hole<span class="punctuation token">.</span>anchor<span class="punctuation token">.</span><span class="keyword token">set</span><span class="punctuation token">(</span><span class="number token">0.5</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>hole<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">setSize</span><span class="punctuation token">(</span><span class="number token">2</span><span class="punctuation token">,</span> <span class="number token">2</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>La diferencia está en que el cuerpo del agujero se configura como inamovible por lo que no se moverá cuando acertamos con la pelota y tendrá calculada la detección de colisión (esto se tratará más adelante en este artículo).</p>

<h4 id="Construyendo_el_laberinto_de_bloques"><strong>Construyendo el laberinto de bloques</strong></h4>

<p>Para hacer más difícil el juego, y más interesante, añadiremos algunos obstaculos entre la pelota y la sálida. Podríamos usar un editor de niveles pero por motivo de este tutorial, vamos a crear algo nosotros mismos.</p>

<p>Para contener el bloque de información usaremos un <em>array</em> con los datos de nivel: para cada bloque almacenaremos las posiciones abolutas izquierda y superior en pixeles (<strong>x </strong>e <strong>y</strong>) y el tipo de bloque: horizontal o vertical (<code>t</code> con el valor <code>'w'</code> para el ancho, y <code>'h'</code> para la altura). Luego, para cargar el nivel analizaremos los datos y mostraremos los bloques especificos para ese nivel. En la función <code>initLevels</code> tenemos:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>levelData <span class="operator token">=</span> <span class="punctuation token">[</span>
    <span class="punctuation token">[</span>
        <span class="punctuation token">{</span> x<span class="punctuation token">:</span> <span class="number token">96</span><span class="punctuation token">,</span> y<span class="punctuation token">:</span> <span class="number token">224</span><span class="punctuation token">,</span> t<span class="punctuation token">:</span> <span class="string token">'w'</span> <span class="punctuation token">}</span>
    <span class="punctuation token">]</span><span class="punctuation token">,</span>
    <span class="punctuation token">[</span>
        <span class="punctuation token">{</span> x<span class="punctuation token">:</span> <span class="number token">72</span><span class="punctuation token">,</span> y<span class="punctuation token">:</span> <span class="number token">320</span><span class="punctuation token">,</span> t<span class="punctuation token">:</span> <span class="string token">'w'</span> <span class="punctuation token">}</span><span class="punctuation token">,</span>
        <span class="punctuation token">{</span> x<span class="punctuation token">:</span> <span class="number token">200</span><span class="punctuation token">,</span> y<span class="punctuation token">:</span> <span class="number token">320</span><span class="punctuation token">,</span> t<span class="punctuation token">:</span> <span class="string token">'h'</span> <span class="punctuation token">}</span><span class="punctuation token">,</span>
        <span class="punctuation token">{</span> x<span class="punctuation token">:</span> <span class="number token">72</span><span class="punctuation token">,</span> y<span class="punctuation token">:</span> <span class="number token">150</span><span class="punctuation token">,</span> t<span class="punctuation token">:</span> <span class="string token">'w'</span> <span class="punctuation token">}</span>
    <span class="punctuation token">]</span><span class="punctuation token">,</span>
    <span class="comment token">// ...</span>
<span class="punctuation token">]</span><span class="punctuation token">;</span></code></pre>

<p>Todos los elementos del <em>array</em> contienen una colección de bloques con una posición <code>x</code> e <code>y</code> y un valor <code>t</code> para cada uno. Luego de <code>levelData</code> pero dentro de la función <code>initLevels</code>, añadiremos los bloques dentro de un <em>array</em> en el loop <code>for</code> usando algunos de los métodos específicos del <em>framework</em>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">for</span><span class="punctuation token">(</span><span class="keyword token">var</span> i<span class="operator token">=</span><span class="number token">0</span><span class="punctuation token">;</span> i<span class="operator token">&lt;</span><span class="keyword token">this</span><span class="punctuation token">.</span>maxLevels<span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">var</span> newLevel <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">group</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    newLevel<span class="punctuation token">.</span>enableBody <span class="operator token">=</span> <span class="keyword token">true</span><span class="punctuation token">;</span>
    newLevel<span class="punctuation token">.</span>physicsBodyType <span class="operator token">=</span> Phaser<span class="punctuation token">.</span>Physics<span class="punctuation token">.</span>ARCADE<span class="punctuation token">;</span>
    <span class="keyword token">for</span><span class="punctuation token">(</span><span class="keyword token">var</span> e<span class="operator token">=</span><span class="number token">0</span><span class="punctuation token">;</span> e<span class="operator token">&lt;</span><span class="keyword token">this</span><span class="punctuation token">.</span>levelData<span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">.</span>length<span class="punctuation token">;</span> e<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">var</span> item <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>levelData<span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">[</span>e<span class="punctuation token">]</span><span class="punctuation token">;</span>
        newLevel<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span>item<span class="punctuation token">.</span>x<span class="punctuation token">,</span> item<span class="punctuation token">.</span>y<span class="punctuation token">,</span> <span class="string token">'element-'</span><span class="operator token">+</span>item<span class="punctuation token">.</span>t<span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
    newLevel<span class="punctuation token">.</span><span class="function token">setAll</span><span class="punctuation token">(</span><span class="string token">'body.immovable'</span><span class="punctuation token">,</span> <span class="keyword token">true</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    newLevel<span class="punctuation token">.</span>visible <span class="operator token">=</span> <span class="keyword token">false</span><span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>levels<span class="punctuation token">.</span><span class="function token">push</span><span class="punctuation token">(</span>newLevel<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p>Primero, <code>add.group()</code> es usado para crear un nuevo grupo de items. Luego, el <em>body tipe</em> <code>ARCADE</code> se configura para permitir los cálculos de física. El método <code>newLevel.create</code> crea nuevos items en el grupo con posiciones superior e izquierda iniciales y su propia imagen. Si no quieres recorrer nuevamente la lista de elementos para agregar una propiedad a cada uno explicitamente, puedes usar <code>setAll</code> en un grupo para aplicarlo a todos los items en ese grupo.</p>

<p>Los objetos son almacenados en el <em>array</em> <code>this.levels</code>, el cual es por defecto invisible. Para cargar niveles específicos, nos aseguramos de que los niveles previos esten escondidos, y mostramos el nivel actual:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js">showLevel<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span>level<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">var</span> lvl <span class="operator token">=</span> level <span class="operator token">|</span> <span class="keyword token">this</span><span class="punctuation token">.</span>level<span class="punctuation token">;</span>
    <span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>levels<span class="punctuation token">[</span>lvl<span class="number token">-2</span><span class="punctuation token">]</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>levels<span class="punctuation token">[</span>lvl<span class="number token">-2</span><span class="punctuation token">]</span><span class="punctuation token">.</span>visible <span class="operator token">=</span> <span class="keyword token">false</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>levels<span class="punctuation token">[</span>lvl<span class="number token">-1</span><span class="punctuation token">]</span><span class="punctuation token">.</span>visible <span class="operator token">=</span> <span class="keyword token">true</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p>Gracias a eso el juego da al jugador un reto: ahora tiene que rodar la pelota a través del área de juego y guiarla por el laberinto construido por bloques. Es solo un ejemplo de cargar los niveles, y solo hay 5 puramente para mostrar la idea, pero podés trabajar en expandirlo por tu cuenta.</p>

<h4 id="Detección_de_colisión"><strong>Detección de colisión</strong></h4>

<p>Hasta este punto tenemos la pelota, que puede ser controlada por el jugador, el agujero que se tiene que alcanzar y los obstáculos que bloquean el camino. <span style="line-height: 1.5;">Sin embargo, hay un problema: nuestro juego todavía no tiene ninguna detección de colisiones, así que no sucede nada cuando la pelota golpea los bloques, sólo los atraviesa. Vamos a arreglarlo! La buena noticia es que el <em>framework</em> se ocupará de calcular la detección de colisones, nosotros sólo debemos especificar los objetos con los que colisionará en la función <code>update()</code>:</span></p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>physics<span class="punctuation token">.</span>arcade<span class="punctuation token">.</span><span class="function token">collide</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>borderGroup<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>wallCollision<span class="punctuation token">,</span> <span class="keyword token">null</span><span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>physics<span class="punctuation token">.</span>arcade<span class="punctuation token">.</span><span class="function token">collide</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>levels<span class="punctuation token">[</span><span class="keyword token">this</span><span class="punctuation token">.</span>level<span class="number token">-1</span><span class="punctuation token">]</span><span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>wallCollision<span class="punctuation token">,</span> <span class="keyword token">null</span><span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>Esto le dirá al <em>framework</em> que ejecute la función <code>wallCollision</code> cuando la pelota golpee cualquiera de las paredes. Podemos usar la función <code>wallCollision</code> para añadir cualquier funcionalidad que querramos, como por ejemplo agregar el sonido de rebote e implementar la <strong>API de Vibración</strong>.</p>

<p><span style="line-height: 1.5;">También debemos volver al objeto pelota y limitarlo a moverse sólo en la zona visible, para que no salga de la pantalla. Hay una función muy útil en Phaser que se llama </span><code style="font-style: normal; line-height: 1.5;">collideWorldBounds</code><span style="line-height: 1.5;">:</span></p>

<pre class="brush: js">ball.body.collideWorldBounds = true;</pre>

<p>Hace exactamente lo que necesitamos: ahora la pelota rebotará en los bordes de la pantalla como de las paredes.</p>

<h4 id="Añadiendo_el_sonido">Añadiendo el sonido</h4>

<p>Entre los elementos precargados hay una pista de audio (en varios formatos para asegurar la compatibilidad con el navegador), que podremos usar ahora. Debe primero ser definida en la función <code>create()</code>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>bounceSound <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">audio</span><span class="punctuation token">(</span><span class="string token">'audio-bounce'</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p><span class="punctuation token">Si el estado del audio es <code>true</code> (es decir que el sonido del juego está activado)</span> podremos reproducirlo en la función <code>wallCollision</code>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>audioStatus<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>bounceSound<span class="punctuation token">.</span><span class="function token">play</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p>Eso es todo: cargar y reproducir sonidos es sencillo con Phaser.</p>

<h4 id="Implementando_la_API_de_Vibración">Implementando la API de Vibración</h4>

<p>Cuando la detección de colisión funcione como es esperado, añadamos algunos efectos especiales con la ayuda de la API de Vibración.<img alt="" src="https://mdn.mozillademos.org/files/10371/cyber-orb-flame-vibration.png"></p>

<p>La mejor forma de usarla en nuestro caso es haciendo que el teléfono vibre cada vez que la pelota golpee las paredes: dentro de la función <code>wallCollision</code>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">if</span><span class="punctuation token">(</span><span class="string token">"vibrate"</span> <span class="keyword token">in</span> window<span class="punctuation token">.</span>navigator<span class="punctuation token">)</span> <span class="punctuation token">{</span>
    window<span class="punctuation token">.</span>navigator<span class="punctuation token">.</span><span class="function token">vibrate</span><span class="punctuation token">(</span><span class="number token">100</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span></code></pre>

<p><span class="punctuation token">Si el método <code>vibrate</code> es soportado por el navegador y está disponible en el objeto <code>window.navigator</code>, hará vibrar al telefono por 100 milisegundos. Eso es todo!</span></p>

<h4 id="Añadiendo_el_tiempo_transcurrido">Añadiendo el tiempo transcurrido</h4>

<p>Para mejorar la re-jugabilidad y dar a los jugadores la opción de competir entre ellos, almacenaremos el tiempo transcurrido: los jugadores entonces intentaran mejorar su tiempo de finalizacion. Para implementar esto en el juego tenemos que crear una variable para almacenar el número actual de segundos transcurrido desde el inicio del juego y mostrarselo al jugador durante el juego. Definamos primero las variables en la función <code>create</code>:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>timer <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> <span class="comment token">// time elapsed in the current level</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> <span class="comment token">// time elapsed in the whole game</span></code></pre>

<p>Luego, podemos inicializar los objetos de texto necesarios para mostrar la información al usuario:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>timerText <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">text</span><span class="punctuation token">(</span><span class="number token">15</span><span class="punctuation token">,</span> <span class="number token">15</span><span class="punctuation token">,</span> <span class="string token">"Time: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>fontBig<span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">this</span><span class="punctuation token">.</span>totalTimeText <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>add<span class="punctuation token">.</span><span class="function token">text</span><span class="punctuation token">(</span><span class="number token">120</span><span class="punctuation token">,</span> <span class="number token">30</span><span class="punctuation token">,</span> <span class="string token">"Total time: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>fontSmall<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>Estamos definiendo la posición superior e izquierda del texto, el contenido que se muestra y el estilo aplicado al texto. Lo hemos impreso en pantalla, pero sería bueno actualizar los valores cada segundo:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>time<span class="punctuation token">.</span>events<span class="punctuation token">.</span><span class="function token">loop</span><span class="punctuation token">(</span>Phaser<span class="punctuation token">.</span>Timer<span class="punctuation token">.</span>SECOND<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>updateCounter<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>Este bucle, también en la función <code>create</code>, ejecutará la función <code>updateCounter</code> cada segundo desde el comienzo del juego, así podemos aplicar los cambios acordes. Así es como se ve la función <code>updateCounter</code> completa:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js">updateCounter<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="operator token">++</span><span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>timerText<span class="punctuation token">.</span><span class="function token">setText</span><span class="punctuation token">(</span><span class="string token">"Time: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="keyword token">this</span><span class="punctuation token">.</span>totalTimeText<span class="punctuation token">.</span><span class="function token">setText</span><span class="punctuation token">(</span><span class="string token">"Total time: "</span><span class="operator token">+</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer<span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span><span class="punctuation token">,</span></code></pre>

<p>Como puedes ver estamos incrementando la variable <code>this.timer</code> y actualizando el contenido del objeto de texto con el valor actual en cada iteración, por lo que el jugador verá el tiempo transcurrido.</p>

<h4 id="Terminando_el_nivel_y_el_juego">Terminando el nivel y el juego</h4>

<p>La pelota está rodando en la pantalla, el temporizador funciona y tenemos el agujero al que tenemos que llegar. Vamos a configurar la posibilidad de finalizar el juego! La siguiente linea en la funcion <code>update()</code> añade un detector que se activa cuando la pelota llega al agujero.</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js"><span class="keyword token">this</span><span class="punctuation token">.</span>physics<span class="punctuation token">.</span>arcade<span class="punctuation token">.</span><span class="function token">overlap</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>hole<span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">.</span>finishLevel<span class="punctuation token">,</span> <span class="keyword token">null</span><span class="punctuation token">,</span> <span class="keyword token">this</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<p>Esto funciona de manera similar al método <code>colide</code> explicado anteriormente. Cuando la pelota se superpone con el agujero (en lugar de colisionar), la función <code>finishLevel</code> es ejecutada:</p>

<pre class="brush: js line-numbers  language-js"><code class="language-js">finishLevel<span class="punctuation token">:</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
    <span class="keyword token">if</span><span class="punctuation token">(</span><span class="keyword token">this</span><span class="punctuation token">.</span>level <span class="operator token">&gt;=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>maxLevels<span class="punctuation token">)</span> <span class="punctuation token">{</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer <span class="operator token">+</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">;</span>
        <span class="function token">alert</span><span class="punctuation token">(</span><span class="string token">'Congratulations, game completed!\nTotal time of play: '</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer<span class="operator token">+</span><span class="string token">' seconds!'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>game<span class="punctuation token">.</span>state<span class="punctuation token">.</span><span class="function token">start</span><span class="punctuation token">(</span><span class="string token">'MainMenu'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
    <span class="keyword token">else</span> <span class="punctuation token">{</span>
        <span class="function token">alert</span><span class="punctuation token">(</span><span class="string token">'Congratulations, level '</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>level<span class="operator token">+</span><span class="string token">' completed!'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer <span class="operator token">+</span><span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>timer <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>level<span class="operator token">++</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>timerText<span class="punctuation token">.</span><span class="function token">setText</span><span class="punctuation token">(</span><span class="string token">"Time: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>timer<span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>totalTimeText<span class="punctuation token">.</span><span class="function token">setText</span><span class="punctuation token">(</span><span class="string token">"Total time: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>totalTimer<span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>levelText<span class="punctuation token">.</span><span class="function token">setText</span><span class="punctuation token">(</span><span class="string token">"Level: "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>level<span class="operator token">+</span><span class="string token">" / "</span><span class="operator token">+</span><span class="keyword token">this</span><span class="punctuation token">.</span>maxLevels<span class="punctuation token">)</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>x <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>ballStartPos<span class="punctuation token">.</span>x<span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>y <span class="operator token">=</span> <span class="keyword token">this</span><span class="punctuation token">.</span>ballStartPos<span class="punctuation token">.</span>y<span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>x <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span>ball<span class="punctuation token">.</span>body<span class="punctuation token">.</span>velocity<span class="punctuation token">.</span>y <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span>
        <span class="keyword token">this</span><span class="punctuation token">.</span><span class="function token">showLevel</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
    <span class="punctuation token">}</span>
<span class="punctuation token">}</span><span class="punctuation token">,</span></code></pre>

<p>Si el nivel actual es igual al maximo número de niveles (5, en este caso), entonces el juego termina: recibiras un mensaje de felicitación junto con el numero de segundas transcurridos durante todo el juego, y un botoón para presionar que te llevará al menú principal.</p>

<p>Si el nivel actual es menor que 5, todas las variables necesarias se reinician y el siguiente nivel es cargado.</p>

<h2 id="Ideas_para_nuevas_características">Ideas para nuevas características</h2>

<p><span style="line-height: 1.5;">Esto no es más que una demostración funcional de un juego que podría tener un montón de características adicionales. Por ejemplo podemos añadir poderes para recoger en el camino que harán que nuestra pelota ruede más rápido, otro podría detener el temporizador durante unos segundos o dar la pelota poderes especiales para atravesar obstáculos. También hay espacio para los obstáculos y trampas que harán más lenta la pelota, acelerar el tiempo o trampas de la propia pelota. Puedes crear más niveles con dificultades diferentes para cada uno. Incluso puedes obtener logros, tablas de clasificación y medallas para diferentes acciones en el juego. Hay un sinfín de posibilidades: sólo dependen de tu imaginación.</span></p>

<h2 id="Resumen">Resumen</h2>

<p>Espero que este tutorial te ayude a introducirte dentro del desarrollo de los juegos 2D y te inspire a crear asombrosos juegos por tu cuenta. Puedes jugar el demo de Cyber Orb y chequear su código fuente en GitHub.</p>

<p>HTML5 nos da herramientas en bruto, los <em>frameworks</em> construidos sobre estas se están volviendo más rápidos y mejores, por lo que ahora es un gran momento para meterse en el desarrollo de juegos web. En este tutorial usamos Phaser, pero hay un gran número de otros <em>frameworks</em> que vale la pena considerar también, como ImpactJS, Construct 2 o PlayCanvas — depende de tus preferencias, habilidades de programación (o la falta de estas), el tamaño de tu proyecto, los requerimientos y otros aspectos. Deberías chequearlos todos y decidir cual es el que mejor se ajusta a tus necesidades.</p>