diff options
author | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:46:50 +0100 |
---|---|---|
committer | Florian Merz <me@fiji-flo.de> | 2021-02-11 14:46:50 +0100 |
commit | a55b575e8089ee6cab7c5c262a7e6db55d0e34d6 (patch) | |
tree | 5032e6779a402a863654c9d65965073f09ea4182 /files/es/games/tutorials | |
parent | 8260a606c143e6b55a467edf017a56bdcd6cba7e (diff) | |
download | translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.tar.gz translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.tar.bz2 translated-content-a55b575e8089ee6cab7c5c262a7e6db55d0e34d6.zip |
unslug es: move
Diffstat (limited to 'files/es/games/tutorials')
15 files changed, 1561 insertions, 0 deletions
diff --git a/files/es/games/tutorials/2d_breakout_game_phaser/rebotar_en_las_paredes/index.html b/files/es/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html index 0276d5dc7f..0276d5dc7f 100644 --- a/files/es/games/tutorials/2d_breakout_game_phaser/rebotar_en_las_paredes/index.html +++ b/files/es/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html diff --git a/files/es/games/tutorials/2d_breakout_game_phaser/botones/index.html b/files/es/games/tutorials/2d_breakout_game_phaser/buttons/index.html index 672d7528a6..672d7528a6 100644 --- a/files/es/games/tutorials/2d_breakout_game_phaser/botones/index.html +++ b/files/es/games/tutorials/2d_breakout_game_phaser/buttons/index.html diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html new file mode 100644 index 0000000000..d168aa0102 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html @@ -0,0 +1,101 @@ +--- +title: Rebota en las paredes +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls +--- +<div>{{GamesSidebar}}</div><div> +<p>{{IncludeSubnav("/es/docs/Games")}}</p> +</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado")}}</p> + +<div class="summary"> +<p>Este es el tercer paso de 10 del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">tutorial Canvas para el desarrollo de juegos</a>. Puedes encontrar el código fuente y pegarle un vistazo después de completar esta lección <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson03.html">Gamedev-Canvas-workshop/lesson3.html</a>.</p> +</div> + +<p><span class="seoSummary">Es agradable ver nuestra bola moviéndose, pero desaparece rápidamente de la pantalla, limitando la diversión que podemos tener con ella. Para superar esto, implementaremos una detección de colisión muy simple (que se explicará <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch/Collision_detection">más adelante</a> con más detalle) para hacer que la pelota rebote en los cuatro bordes del Canvas.</span></p> + +<h2 id="Detección_de_colisión_simple">Detección de colisión simple</h2> + +<p>Para detectar la colisión verificamos si la bola está tocando (chocando con) la pared y si es así, cambiaremos la dirección de su movimiento en consecuencia.</p> + +<p>Para facilitar los cálculos, definamos una variable llamada <code>ballRadius</code> que mantendrá el radio del círculo dibujado y se utilizará para los cálculos. Añade esto a tu código, en algún lugar por debajo de las declaraciones de variables existentes:</p> + +<pre class="brush: js">var ballRadius = 10;</pre> + +<p>Ahora actualice la línea que dibuja la bola dentro de la funcion drawBall() a esto:</p> + +<pre class="brush: js">ctx.arc(x, y, ballRadius, 0, Math.PI*2);</pre> + +<h3 id="Rebotando_arriba_y_abajo">Rebotando arriba y abajo</h3> + +<p>Hay cuatro paredes para rebotar la pelota - vamos a centrarnos en la de arriba en primer lugar. Tendremos que comprobar, en cada fotograma, si la pelota está tocando el borde superior del Canvas - si es así, invertiremos el movimiento de la bola para que empiece a moverse en la dirección opuesta y se mantenga dentro de los límites visibles. Recordando que el sistema de coordenadas comienza desde la parte superior izquierda, podemos llegar a algo como esto:</p> + +<pre class="brush: js">if(y + dy < 0) { + dy = -dy; +}</pre> + +<p>Si el valor de y de la posición de la bola es menor que cero, cambie la dirección del movimiento en el eje y, estableciéndolo igual a sí mismo, invertido. Si la pelota se movía hacia arriba con una velocidad de 2 píxeles por fotograma, ahora se moverá "arriba" con una velocidad de -2 píxeles, lo que en realidad equivale a bajar a una velocidad de 2 píxeles por fotograma.</p> + +<p>El código anterior se ocuparía de que la pelota rebote desde el borde superior, así que ahora vamos a pensar en el borde inferior:</p> + +<pre class="brush: js">if(y + dy > canvas.height) { + dy = -dy; +}</pre> + +<p>Si la posición y de la pelota es mayor que la altura del canvas (recuerde que contamos los valores y desde la parte superior izquierda, de modo que el borde superior empieza en 0 y el borde inferior está en 480 píxeles, la altura del canvas), entonces rebota del borde inferior invirtiendo el movimiento del eje y como antes.</p> + +<p>Podríamos fusionar esas dos sentencias en una para ahorrar código:</p> + +<pre class="brush: js">if(y + dy > canvas.height || y + dy < 0) { + dy = -dy; +}</pre> + +<p>Si cualquiera de las dos afirmaciones es verdadera, invierte el movimiento de la pelota.</p> + +<h3 id="Rebotando_en_la_izquierda_y_derecha">Rebotando en la izquierda y derecha</h3> + +<p>Tenemos el borde superior e inferior cubiertos, así que pensemos en los de izquierda y derecha. Es muy similar en realidad, todo lo que tienes que hacer es repetir las declaraciones de x en lugar de y:</p> + +<pre class="brush: js">if(x + dx > canvas.width || x + dx < 0) { + dx = -dx; +} + +if(y + dy > canvas.height || y + dy < 0) { + dy = -dy; +}</pre> + +<p>En este punto, debe insertar el bloque de código anterior en la función draw(), justo antes de la llave de cierre.</p> + +<h3 id="¡La_pelota_sigue_desapareciendo_en_la_pared!">¡La pelota sigue desapareciendo en la pared!</h3> + +<p>Prueba tu código en este punto, y te quedarás impresionado - ¡ahora tenemos una pelota que rebotó en los cuatro bordes del canvas! Pero tenemos otro problema sin embargo - cuando la bola golpea cada pared se hunde en ella levemente antes de cambiar la dirección:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/10432/ball-in-wall.png" style="display: block; height: 320px; margin: 0px auto; width: 480px;"></p> + +<p>Esto es porque estamos calculando el punto de colisión de la pared y el centro de la bola, mientras que deberíamos hacerlo por su circunferencia. La bola debe rebotar justo después de que toca la pared, no cuando ya está a medio camino en la pared, así que vamos a ajustar nuestras declaraciones un poco para incluir eso. Actualice el último código que agregó, a esto:</p> + +<pre class="brush: js">if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { + dx = -dx; +} +if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) { + dy = -dy; +}</pre> + +<p>Cuando la distancia entre el centro de la bola y el borde de la pared es exactamente igual que el radio de la pelota, cambiará la dirección del movimiento. Restando el radio de un ancho del eje y añadiéndolo al otro nos da la impresión de una adecuada detección de colisiones - la pelota rebota de las paredes como debería hacerlo.</p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Chequea el código acabado para esta parte con el tuyo, y juega:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/redj37dc/","","370")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: cambia el color de la bola a un color al azar, cada vez que golpea una pared.</p> +</div> + +<h2 id="Siguientes_pasos">Siguientes pasos</h2> + +<p>Ahora hemos llegado al punto donde nuestra pelota se mueve y permanece en el tablero de juego. En el capítulo cuarto, veremos la implementación del control de una pala - vea <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado">Control de Pala y teclado</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html new file mode 100644 index 0000000000..99c944764b --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html @@ -0,0 +1,126 @@ +--- +title: Construye el muro de ladrillos +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Build_the_brick_field +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/es/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones")}}</p> + +<div class="summary"> +<p>Este es el sexto<strong> paso de 10 del</strong> <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro">Tutorial del Lienzo (Canvas) para desarrollar juegos (Gamedev Canvas Tutorial)</a>. Puedes encontrar el código fuente como debería quedar tras completar esta lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson06.html">Gamedev-Canvas-workshop/lesson6.html</a>.</p> +</div> + +<p>Hemos cambiado la mecánica del juego y ahora ya podemos perder.<span class="seoSummary"> Esto es genial porque significa que el juego finalmente se comporta como un juego. Sin embargo, pronto resultará aburrido si todo lo que puedes conseguir es hacer rebotar la pelota en las paredes y en la pala. Lo que el juego necesitamos es romper ladrillos con la bola. Ahora vamos a dibujar los ladrillos.</span></p> + +<h2 id="Declarar_e_inicializar_las_variables_de_los_ladrillos">Declarar e inicializar las variables de los ladrillos</h2> + +<p>El propósito principal de esta lección consiste en escribir unas pocas líneas de código para los ladrillos, utilizando un bucle anidado que recorra una matriz bidimensional. Pero, antes, necesitamos preparar unas variables que definan la información sobre los ladrillos, como su ancho y alto, filas y columnas, etc. Añade estas líneas a tu programa, debajo de las otras variables que has definido antes:</p> + +<pre class="brush: js">var brickRowCount = 3; +var brickColumnCount = 5; +var brickWidth = 75; +var brickHeight = 20; +var brickPadding = 10; +var brickOffsetTop = 30; +var brickOffsetLeft = 30;</pre> + +<p>Aquí hemos definido el número de filas (Row) y columnas (Column) de ladrillos, su ancho (Width) y alto (Height), el hueco entre los ladrillos para que no se toquen (Padding), y un margen superior (Top) e izquierdo (Left) para que no se dibujen tocando los bordes.</p> + +<p>Guardaremos nuestros ladrillos en una matriz bidimensional que contendrá las columnas (c) de los ladrillos. Cada columna contendrá, a su vez, toda la fila (r) de ladrillos. Cada ladrillo se va a representar con un objeto con las posiciones "x" e "y" en las que se dibujará. Añade esto detrás de las definiciones de las variables:</p> + +<pre class="brush: js">var bricks = []; +for(c=0; c<brickColumnCount; c++) { + bricks[c] = []; + for(r=0; r<brickRowCount; r++) { + bricks[c][r] = { x: 0, y: 0 }; + } +}</pre> + +<p>El código anterior pasará por las filas y las columnas y creará los ladrillos. TEN EN CUENTA que esos objetos que representan a los ladrillos también se utilizarán para detectar colisiones más adelante.</p> + +<p>Por si no lo terminas de entender... bricks[0][0] es el primer ladrillo (columna 0, fila 0) y se dibujará en "x" 0 e "y" 0. El siguiente ladrillo será el brick[0][1] (columna 0, fila 1) y se dibujará también en (0,0). Así, continuaremos hasta el final de la primera columna, que será el ladrillo bricks[0][2] porque hay 3 filas, de la 0 a la 2. Terminará así el bucle de dentro y seguirá el de fuera, valiendo ahora la "c" 1. Seguiremos recorriendo bricks[] hasta llegar a bricks[2][4], que es el último ladrillo.</p> + +<h2 id="Dibujar_los_bloques">Dibujar los bloques</h2> + +<p>Ahora vamos a crear una función para recorrer todos los bloques de la matriz y dibujarlos en la pantalla:</p> + +<pre class="brush: js">function drawBricks() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + bricks[c][r].x = 0; + bricks[c][r].y = 0; + ctx.beginPath(); + ctx.rect(0, 0, brickWidth, brickHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); + } + } +} +</pre> + +<p>Viene a ser lo mismo de antes, sólo que hemos añadido ctx.rect() para dibujar un rectángulo por cada ladrillo, además de otras llamadas a funciones para que, efectivamente, se dibuje el rectángulo.</p> + +<p>Cada ladrillo se dibujará en la posición (0, 0), tendrá un ancho brickWidth y un alto de brickHeight.</p> + +<p>Estupendo pero... ¡estamos dibujando todos los ladrillos en el mismo sitio! ¡Eso no puede ser!</p> + +<p>Vamos a calcular en qué posición "x" e "y" se tiene que dibujar cada ladrillo así:</p> + +<pre class="brush: js">var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft; +var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop; +</pre> + +<p>El primer ladrillo se dibujará arriba a la izquierda, concretamente en (brickoffsetLeft, brickOffsetTop), porque c y r valen 0.</p> + +<p>El siguiente ladrillo (columna 0, fila 1) se dibujará más abajo.</p> + +<p>Intenta hacer tú mismo los cálculos y verás cómo cada ladrillo de la misma columna se dibujará más abajo o más arriba según en qué fila se encuentre.</p> + +<p>También verás cómo cada ladrillo de la misma fila se dibujará más a la izquierda o a la derecha según en qué columna se encuentre.</p> + +<p>Vamos a terminar la función drawBricks() para que quede así:</p> + +<pre class="brush: js">function drawBricks() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft; + var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop; + bricks[c][r].x = brickX; + bricks[c][r].y = brickY; + ctx.beginPath(); + ctx.rect(brickX, brickY, brickWidth, brickHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); + } + } +}</pre> + +<h2 id="Dibujar_los_bloques_(ahora_sí)">Dibujar los bloques (ahora sí)</h2> + +<p>Lo estamos haciendo muy bien, pero si has probado te habrás dado cuenta de que no se dibuja nada. ¿Qué es lo que falla?</p> + +<p>Pues, sencillamente, que tenemos definida la función drawBricks() pero no la llamamos desde ningún sitio.</p> + +<p>Añade drawBricks() dentro de draw(), justo antes de drawBall ():</p> + +<pre class="brush: js">drawBricks(); +</pre> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Compara tu código con este:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/kundan333/myd4vbwg/2/","","320")}}</p> + +<div class="note"> +<p>Ejercicio: Prueba a cambiar el número de bloques por fila o columna, o sus posiciones (utiliza las variables que definiste al principio de este capítulo).</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>¡Así que ahora tenemos ladrillos! Un gran avance pero... la pelota no los rompe, simplemente los atraviesa. En el siguiente capítulo lo arreglaremos: <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones">Detección de colisiones</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html new file mode 100644 index 0000000000..e6d950b834 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html @@ -0,0 +1,128 @@ +--- +title: Detección de colisiones +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection +--- +<div>{{GamesSidebar}}</div> + +<div>{{IncludeSubnav("/en-US/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win")}}</p> + +<div class="summary"> +<p>Este es el séptimo paso de los 10 del juego "<a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Gamedev Canvas tutorial</a>". Puedes encontrar el código como deberá quedar después de completar la leción en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson07.html">Gamedev-Canvas-workshop/lesson7.html</a>.</p> +</div> + +<p><span class="seoSummary">Ya tenemos los ladrillos en la pantalla pero el juego todavía no es muy interesante, porque la bola los atraviesa. Tenemos que pensar una manera de detectar colisiones para que la bola pueda rebotar en los ladrillos y romperlos.</span></p> + +<p><span class="seoSummary">Nosotros decidimos cómo implementar esto, por supuesto, pero puede ser complicado calcular si la bola está tocando el rectángulo o no, porque no hay funciones del <canvas> que sirvan para saberlo. En este tutorial vamos a hacerlo de la manera más fácil que existe: comprobaremos si el centro de la bola está tocando (colisionando) con cualquiera de los ladrillos. No siempre funcionará a la perfección y hay formas de detectar colisiones más sofisticadas que funcionan mejor, pero no nos interesa verlas porque estamos aprendiendo y tenemos que hacer las cosas fáciles</span>.</p> + +<h2 id="Una_función_para_detectar_colisiones">Una función para detectar colisiones</h2> + +<p>Para lograr nuestro objetivo vamos a definir una función que, con un bucle, recorrerá todos los ladrillos y comparará la posición de cada uno con la posición de la bola, cada vez que se dibuje un fotograma. Para que el código sea más legible definiremos la variable "b" que almacenará el objeto ladrillo en cada vuelta de bucle:</p> + +<pre class="brush: js">function collisionDetection() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var b = bricks[c][r]; + // calculations + } + } +}</pre> + +<p>Si el centro de la bola está dentro de las coordenadas de uno de nuestros ladrillos, cambiaremos la dirección de la bola. Se cumplirá que el centro de la bola está dentro de ladrillo si se cumplen al mismo tiempo estas cuatro condiciones:</p> + +<ul> + <li>La posición "x" de la bola es mayor que la posición "x" del ladrillo</li> + <li>La posición "x" de la bola es menor que la posición del ladrillo más el ancho del ladrillo</li> + <li>La posición "y" de la bola es mayor que la posición "y" del ladrillo.</li> + <li>La posición "y" de la bola es menor que la posición del ladrillo más su altura.</li> +</ul> + +<p>Traducimos esto a JavaScript:</p> + +<pre class="brush: js">function collisionDetection() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var b = bricks[c][r]; + if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) { + dy = -dy; + } + } + } +}</pre> + +<p>Añade lo anterior a tu código, debajo de la función <code>keyUpHandler()</code>.</p> + +<h2 id="Hacer_que_los_ladrillos_desaparezcan_cuando_reciben_un_golpe">Hacer que los ladrillos desaparezcan cuando reciben un golpe</h2> + +<p>El código anterior funcionará correctamente y la bola cambiará de dirección. El problema es que los ladrillos siguen donde están. Tenemos que imaginar una forma de ocuparnos de los que ya hemos golpeado con la bola. Podemos hacerlo añadiendo un parámetro extra para indicar si queremos pintar cada ladrillo en la pantalla o no. En la parte del código donde inicializamos los ladrillos, añadiremos una propiedad <code>status</code> a cada ladrillo. Cambia tu código fijándote en la línea que está resaltada:</p> + +<pre class="brush: js; highlight:[5]">var bricks = []; +for(c=0; c<brickColumnCount; c++) { + bricks[c] = []; + for(r=0; r<brickRowCount; r++) { + bricks[c][r] = { x: 0, y: 0, status: 1 }; + } +}</pre> + +<p>A continuación consultaremos el "status" de cada ladrillo para saber si lo tenemos que dibujar o no. Si "status" vale 1, lo dibujaremos. Si vale 0, no lo dibujaremos porque habrá sido golpeado por la bola. Actualiza tu función <code>drawBricks()</code> para que quede así:</p> + +<pre class="brush: js; highlight:[4,5,6,7,8,9,10,11,12,13,14]">function drawBricks() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + if(bricks[c][r].status == 1) { + var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft; + var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop; + bricks[c][r].x = brickX; + bricks[c][r].y = brickY; + ctx.beginPath(); + ctx.rect(brickX, brickY, brickWidth, brickHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); + } + } + } +}</pre> + +<h2 id="Actualizar_el_status_en_la_función_de_detección_de_colisiones">Actualizar el "status" en la función de detección de colisiones</h2> + +<p>Ahora tenemos que ocuparnos del valor de "status" en la función <code>collisionDetection()</code>: si el ladrillo está activo (status 1) comprobaremos si hay colisión. Si hay colisión, pondremos el "status" de ese ladrillo a 0 para no volver a pintarlo. Actualiza <code>collisionDetection()</code> así:</p> + +<pre class="brush: js; highlight:[5,6,7,8,9,10]">function collisionDetection() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var b = bricks[c][r]; + if(b.status == 1) { + if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) { + dy = -dy; + b.status = 0; + } + } + } + } +}</pre> + +<h2 id="Activar_la_función_de_detección_de_colisiones">Activar la función de detección de colisiones</h2> + +<p>Ya sólo falta llamar a la función <code>collisionDetection()</code> desde la función <code>draw()</code>. Añade la línea siguiente dentro de <code>draw()</code> function, justo después de la llamada a <code>drawPaddle()</code>:</p> + +<pre class="brush: js">collisionDetection(); +</pre> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Ahora se comprueban las colisiones cada vez que se dibuja un fotograma. Concretamente, miramos si la bola colisiona con cada ladrillo. ¡Ahora ya podemos romper ladrillos! :-</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/kundan333/myd4vbwg/5/","","320")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: cambia el color de la bola cada vez que choque con un ladrillo.</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>Definitivamente, lo estamos consiguiendo. ¡Adelanteeee! En el capítulo octavo nos ocuparemos de la <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win">Puntuación y fin del juego ganando</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html new file mode 100644 index 0000000000..59703d3bc7 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html @@ -0,0 +1,108 @@ +--- +title: Crea el lienzo (canvas) y dibuja en él +slug: >- + Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it +translation_of: >- + Games/Tutorials/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/en-US/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola")}}</p> + +<div class="summary"> +<p>Este es el primero de los 10 pasos del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Tutorial del Lienzo (Canvas) para desarrollar juegos (Gamedev Canvas Tutorial)</a>. Puedes encontrar el código fuente como debería quedar tras completar esta lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson01.html">Gamedev-Canvas-workshop/lesson1.html</a>.</p> +</div> + +<p><span class="seoSummary">Antes de que podamos programar la parte funcional del juego, necesitamos crear la estructura básica de la página que lo va a contener. Podemos hacerlo utilizando HTML y el elemento {{htmlelement("canvas")}} .</span></p> + +<h2 id="El_HTML_del_juego">El HTML del juego</h2> + +<p>La estructura del documento HTML es muy simple, porque todo el juego se visualizará dentro del elemento {{htmlelement("canvas")}}. Con tu editor de textos favorito, prepara un documento en blanco, guárdalo como <code>index.html</code> en un lugar adecuado, y escribe el siguiente código:</p> + +<pre class="brush: html"><!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <title>Gamedev Canvas Workshop</title> + <style> + * { padding: 0; margin: 0; } + canvas { background: #eee; display: block; margin: 0 auto; } + </style> +</head> +<body> + +<canvas id="myCanvas" width="480" height="320"></canvas> + +<script> + // JavaScript code goes here +</script> + +</body> +</html> +</pre> + +<p>En la cabecera (head) tenemos un <code>charset</code>, el título de la página {{htmlelement("title")}} y un poco de CSS básico. El {{htmlelement("body")}} contiene los elementos{{htmlelement("canvas")}} y {{htmlelement("script")}}. Representaremos el juego en el primero y escribiremos el código JavaScript que lo controla en el segundo. El elemento {{htmlelement("canvas")}} tiene el <code>id</code> <code>myCanvas</code> para que podamos hacer referencia a él con facilidad, y mide 480 píxeles de ancho por 320 de alto. Todo el código JavaScript que vamos a escribir en este tutorial lo pondremos entre las etiquetas <code><script><font face="Thread-00002020-Id-00000048"> y</font></code> <code></script></code>.</p> + +<h2 id="El_lienzo_(canvas)">El lienzo (canvas)</h2> + +<p>Para que podamos visualizar los gráficos en el elemento {{htmlelement("canvas")}}, primero tenemos que preparar una referencia a él en JavaScript. Añade lo siguiente después de la etiqueta <code><script>:</code></p> + +<pre class="brush: js">var canvas = document.getElementById("myCanvas"); +var ctx = canvas.getContext("2d");</pre> + +<p>Aquí estamos guardando una referencia al elemento {{htmlelement("canvas")}} en la variable <code>canvas</code>. Después estamos creando la variable <code>ctx</code> para guardar el contexto de gráficos 2D, que es la herramienta que realmente utilizaremos para dibujar.</p> + +<p>Veamos un fragmento de código de ejemplo que dibuja un cuadrado rojo en el canvas. Añade el código a continuación y abre el archivo <code>index.html</code> con un navegador para comprobar que funciona:</p> + +<pre class="brush: js">ctx.beginPath(); +ctx.rect(20, 40, 50, 50); +ctx.fillStyle = "#FF0000"; +ctx.fill(); +ctx.closePath();</pre> + +<p>Todas las instrucciones están entre los métodos {{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}} y {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}. Estamos definiendo un rectángulo utilizando {{domxref("CanvasRenderingContext2D.rect()","rect()")}}: los dos primeros valores especifican las coordenadas de la esquina superior izquierda del rectángulo en el canvas, y los otros dos sirven para indicar el ancho y el alto. En nuestro caso, el rectángulo se dibuja a 20 píxeles desde la izquierda de la pantalla y 40 píxeles desde la parte de arriba, y tiene 50 píxeles de ancho y 50 de alto, con lo que obtenemos un cuadrado perfecto. La propiedad {{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}} guarda un color que utilizará el método {{domxref("CanvasRenderingContext2D.fill()","fill()")}} para pintar el cuadrado que, en nuestro caso, será rojo.</p> + +<p>Podemos dibujar otras cosas aparte de rectángulos. Aquí hay un fragmento de código que dibuja un círculo verde. Prueba a añadir esto al final de tu código JavaScript, guárdalo y recarga la página en el navegador:</p> + +<pre class="brush: js">ctx.beginPath(); +ctx.arc(240, 160, 20, 0, Math.PI*2, false); +ctx.fillStyle = "green"; +ctx.fill(); +ctx.closePath();</pre> + +<p>Como puedes ver, estamos utilizando otra vez los métodos {{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}} y {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}. De lo que hay en medio, la parte más importante del código anterior es el método {{domxref("CanvasRenderingContext2D.arc()","arc()")}}. Tiene seis parámetros:</p> + +<ul> + <li>las coordenadas x e y del centro del arco</li> + <li>el radio del arco</li> + <li>los ángulos inicial y final (en qué ángulo empezar y terminar de dibujar el círculo, en radianes)</li> + <li>la dirección hacia la que se dibujará (<code>false</code> para seguir el sentido de las agujas del reloj, que es el valor por defecto, o <code>true</code> para el sentido contrario). Este parámetro es opcional.</li> +</ul> + +<p>La propiedad {{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}} tiene un valor distinto al que habíamos puesto antes. Esto se debe a que, como ocurre en CSS, el color se puede especificar como un valor hexadecimal, como un nombre de color en inglés, la función <code>rgba()</code>, o cualquiera de los otros métodos de descripción de color que existen.</p> + +<p>En lugar de utilizar {{domxref("CanvasRenderingContext2D.fill()","fill()")}} y rellenar las formas con colores, podemos utilizar {{domxref("CanvasRenderingContext2D.stroke()","stroke()")}} para colorear únicamente el trazo exterior. Prueba a añadir también esto a tu código JavaScript:</p> + +<pre class="brush: js">ctx.beginPath(); +ctx.rect(160, 10, 100, 40); +ctx.strokeStyle = "rgba(0, 0, 255, 0.5)"; +ctx.stroke(); +ctx.closePath();</pre> + +<p>El código anterior dibuja un rectángulo vacío con el perímetro azul. Gracias al canal alfa de la función <code>rgba()</code>, que es el cuarto valor (Red, Green, Blue, Alpha), el color azul será medio transparente.</p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Aquí está el código fuente completo de la primera lección, ejecutándose en un JSFiddle:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/x62h15e2/","","370")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: cambia el tamaño y el color de las figuras.</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>Hemos preparado la estructura HTML básica y hemos aprendido un poquito a manejar el canvas. Para continuar, en el segundo capítulo averiguaremos cómo mover la bola en nuestro juego (<a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola">Mueve la bola</a>).</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html new file mode 100644 index 0000000000..a3bd5e2c2e --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html @@ -0,0 +1,95 @@ +--- +title: Terminando +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Terminando +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Finishing_up +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/en-US/docs/Games")}}</div> + +<p>{{Previous("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton")}}</p> + +<div class="summary"> +<p>Este es el último de los 10 pasos del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Gamedev Canvas tutorial</a>. Puedes encontrar el código fuente tal y como quedará al terminar esta lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson10.html">Gamedev-Canvas-workshop/lesson10.html</a>.</p> +</div> + +<p>Siempre es posible mejorar cualquier juego que hagamos. Por ejemplo, podemos dar vidas al jugador. Así, aunque pierda la bola una o dos veces, todavía puede intentar derribar todo el muro. También podemos mejorar los aspectos gráficos.</p> + +<h2 id="Dar_vidas_al_jugador">Dar vidas al jugador</h2> + +<p>Dar vidas es bastante sencillo. Primero, añade una variable para guardar el número de vidas que tiene en cada momento. Ponla después de las que ya tienes:</p> + +<pre class="brush: js">var lives = 3;</pre> + +<p>Mostrar por pantalla el número de vidas es prácticamente lo mismo que mostrar el contador de puntos. Añade la función siguiente detrás de la función <code>drawScore()</code>:</p> + +<pre class="brush: js">function drawLives() { + ctx.font = "16px Arial"; + ctx.fillStyle = "#0095DD"; + ctx.fillText("Lives: "+lives, canvas.width-65, 20); +}</pre> + +<p>En lugar de terminar el juego inmediatamente, restaremos una vida hasta que ya no quede ninguna. También podemos colocar la bola y la paleta en la posición inicial cuando el jugador empiece con la vida siguiente. En la función <code style="font-style: normal; font-weight: normal;">draw()</code> cambia las dos líneas siguientes...</p> + +<pre class="brush: js">alert("GAME OVER"); +document.location.reload();</pre> + +<p>... por estas otras:</p> + +<pre class="brush: js">lives--; +if(!lives) { + alert("GAME OVER"); + document.location.reload(); +} +else { + x = canvas.width/2; + y = canvas.height-30; + dx = 2; + dy = -2; + paddleX = (canvas.width-paddleWidth)/2; +}</pre> + +<p>Ahora, cuando la bola toca el fondo, restamos una vida. Si no queda ninguna, el jugador pierde y termina la partida. Si queda alguna, entonces colocamos la bola y la paleta en el centro, y hacemos que la bola vaya en la nueva dirección correcta y a la velocidad inicial.</p> + +<h3 id="Sacar_por_pantalla_el_contador_de_vidas">Sacar por pantalla el contador de vidas</h3> + +<p>Tienes que añadir una llamada a <code>drawLives()</code> dentro de <code>draw()</code> debajo de la llamada a <code>drawScore():</code></p> + +<pre class="brush: js">drawLives(); +</pre> + +<h2 id="Mejorar_el_refresco_con_requestAnimationFrame()">Mejorar el refresco con requestAnimationFrame()</h2> + +<p>Ahora vamos a ocuparnos de algo que no es particular de este juego, sino de la forma en la que se muestran las imágenes en pantalla.</p> + +<p>{{domxref("window.requestAnimationFrame", "requestAnimationFrame")}} ayuda al navegador a refrescar la imagen mejor que con el método {{domxref("windowTimers.setInterval()", "setInterval()")}} que estamos utilizando. Cambia la línea siguiente...</p> + +<pre class="brush: js">setInterval(draw, 10);</pre> + +<p>...por esta otra:</p> + +<pre class="brush: js">draw();</pre> + +<p>Y, ahora, al final de la función draw(), justo antes de la llave que la cierra, añade la línea siguiente, que hará que la función <code>draw()</code> se llame a sí misma una y otra vez:</p> + +<pre class="brush: js">requestAnimationFrame(draw);</pre> + +<p>Ahora draw() se ejecuta una y otra vez con un bucle <code>requestAnimationFrame()</code> pero, en lugar de hacerlo cada 10 milisegundos, dejamos que sea el navegadro quien decida cada cuánto tiempo. El navegador sincronizará el refresco, es decir, el número de fotogramas por segundo, a lo que sea capaz la máquina que está ejecutando el juego. De este modo la animación será más eficiente y más suave que el viejo método <code>setInterval()</code>.</p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Ya hemos terminado. ¡La versión final del juego está lista para publicar!</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/9temh0ta/","","320")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: cambia el número de vidas y el ángulo de la trayectoria de la bola cuando golpea la paleta.</p> +</div> + +<h2 id="Game_over_-_de_momento!">Game over - de momento!</h2> + +<p>Enhorabuena, has terminado todas las lecciones. Ya has aprendido las técnicas básicas de manipulación del <canvas> y la lógica que hay detrás de los juegos 2D sencillos.</p> + +<p>Ahora sería un buen momento para aprender a utilizar entornos de desarrollo (frameworks) y de continuar con el desarrollo de juegos. Puedes echar un vistazo a estas otra forma de realizar el mismo juego que has visto en <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/2D_breakout_game_Phaser">2D breakout game using Phaser</a>, o de echar un vistazo al tutorial <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/HTML5_Gamedev_Phaser_Device_Orientation">Cyber Orb built in Phaser</a>. También puedes leer el contenido de <a href="https://developer.mozilla.org/en/docs/Games">Games section on MDN</a> para inspirarte y seguir aprendiendo.</p> + +<p>También puedes volve al <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro">índice de este tutorial</a>. ¡Diviértete programando!</p> + +<p>{{Previous("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html new file mode 100644 index 0000000000..d57ccef444 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html @@ -0,0 +1,75 @@ +--- +title: Fin del juego +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego +tags: + - Canvas + - Fin del juego + - JavaScript + - Tutorial + - graficos +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Game_over +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/es-ES/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques")}}</p> + +<div class="summary"> +<p>Este es el quinto paso de 10 del <a href="/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Gamedev Canvas tutorial</a>. Puedes ver como debería quedar el código fuente después de completar esta lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson05.html">Gamedev-Canvas-workshop/lesson5.html</a>.</p> +</div> + +<p><span id="result_box" lang="es"><span>Es divertido ver la bola rebotando en las paredes y ser capaz de mover la pala pero, aparte de eso, el juego no hace nada y no tiene ningún progreso ni un objetivo final.</span> <span>Sería bueno desde el punto de vista del juego poder perder.</span> <span>La lógica asociada a perder en este juego es fácil de entender: si se te escapa la bola y alcanza el borde inferior de la pantalla, pierdes y se acabó el juego</span></span><span lang="es"><span>.</span></span></p> + +<h2 id="Implementar_el_final_del_juego">Implementar el final del juego</h2> + +<p><span id="result_box" lang="es"><span>Intentemos implementar el final del juego en nuestro juego.</span> <span>Aquí está el trozo de código de la tercera lección en donde hicimos que la pelota rebotara en las paredes:</span></span></p> + +<pre class="brush: js">if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { + dx = -dx; +} + +if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) { + dy = -dy; +}</pre> + +<p><span id="result_box" lang="es"><span>En lugar de dejar que la pelota rebote en las cuatro paredes, vamos a permitir que lo haga sólo en tres: izquierda, arriba y derecha.</span> Alcanzar <span>la pared inferior supondrá el fin del juego.</span> <span>Editaremos el segundo bloque if y lo convertiremos en un "if else" que activará el estado de "final de juego" cuando la pelota colisione con el borde inferior del terreno de juego.</span> <span>Por ahora nos conformaremos con mostrar un mensaje con la función alert() y con reiniciar el juego volviendo a cargar la página. Modifica el segundo if para que quede así</span><span>:</span></span></p> + +<pre class="brush: js">if(y + dy < ballRadius) { + dy = -dy; +} else if(y + dy > canvas.height-ballRadius) { + alert("GAME OVER"); + document.location.reload(); +}</pre> + +<h2 id="Hacer_que_la_pala_golpee_la_bola">Hacer que la pala golpee la bola</h2> + +<p>Para terminar esta lección sólo nos falta detectar la colisión de la bola y la paleta para que pueda rebotar, volviendo hacia la zona de juego. La manera más sencilla de hacerlo es comprobar si el centro de la bola está entre los límites izquierdo y derecho de la paleta. Actualiza el último <span id="result_box" lang="es"><span>fragmento del código, el "if else" de antes, para que te quede así:</span></span></p> + +<pre class="brush: js">if(y + dy < ballRadius) { + dy = -dy; +} else if(y + dy > canvas.height-ballRadius) { + if(x > paddleX && x < paddleX + paddleWidth) { + dy = -dy; + } + else { + alert("GAME OVER"); + document.location.reload(); + } +}</pre> + +<p>Si la bola toca el <span id="result_box" lang="es"><span>borde inferior del lienzo (Canvas) debemos comprobar si golpea la pala.</span> <span>Si es así, entonces rebota como el jugador se imagina que va a ocurrir;</span> si no,<span> el juego ha terminado.</span></span></p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Aquí tienes el código que funciona para que lo compares con el tuyo:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/z4zy79fo/","","320")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: haz que la bola se mueva más rápida cuando golpea la pala.</p> +</div> + +<h2 id="Siguientes_pasos">Siguientes pasos</h2> + +<p><span id="result_box" lang="es"><span>Lo estamos haciendo bastante bien hasta ahora y nuestro juego está empezando a despertar interés ahora que se puede perder. </span><span>Pero todavía falta algo.</span> <span>Vamos a pasar al sexto capítulo,</span></span> <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques">Construir el muro de ladrillos</a>, <span lang="es"><span>y crear algunos ladrillos para que la bola los destruya.</span></span></p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/index.html new file mode 100644 index 0000000000..10ea794d5f --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/index.html @@ -0,0 +1,52 @@ +--- +title: Famoso juego 2D usando JavaScript puro +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro +tags: + - 2D Canvas JavaScript Tutorial + - Principiante Juegos +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/es-ES/docs/Games")}}</div> + +<p>{{Next("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it")}}</p> + +<p class="summary">En este tutorial paso a paso creamos un juego de la MDN, sencillo y muy famoso, escrito íntegramente en JavaScript puro. Todos los elementos gráficos aparecerán dentro de la etiqueta {{htmlelement("canvas")}} de HTML5.</p> + +<p>Cada paso tiene ejemplos editables y listos para ejecutar, para que puedas ver qué aspecto debería tener el ejercicio en cada momento. Apenderás a utilizar el elemento {{htmlelement("canvas")}} para implementar mecánicas de juego fundamentales como la representación de imágenes, el movimiento, la detección de colisiones, los mecanismos de control y el final del juego ganando o perdiendo.</p> + +<p>Para aprovechar al máximo esta serie de artículos necesitas tener ya un conocimiento básico o intermedio de <a href="/en-US/Learn/Getting_started_with_the_web/JavaScript_basics">JavaScript</a>. Cuando termines este tutorial serás capaz de construir tus propios juegos Web.</p> + +<p><img alt="Gameplay screen from the game MDN Breakout where you can use your paddle to bounce the ball and destroy the brick field, with keeping the score and lives." src="https://mdn.mozillademos.org/files/10383/mdn-breakout-gameplay.png" style="display: block; height: 320px; margin: 0px auto; width: 480px;"></p> + +<h2 id="Detalle_de_las_lecciones">Detalle de las lecciones</h2> + +<p>Todas las lecciones y las diferentes versiones del <a href="http://breakout.enclavegames.com/lesson10.html">famoso juego MDN</a> que estamos construyendo juntos están <a href="https://github.com/end3r/Canvas-gamedev-workshop">disponibles en GitHub</a>:</p> + +<ol> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it">Crea el lienzo (canvas) y dibuja en él</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola">Mueve la bola</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls">Rebota en las paredes</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado">Control de la pala y el teclado</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego">Fin del juego</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Construye_grupo_bloques">Construye el muro de ladrillos</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones">Detección de colisiones</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win">Cuenta los puntos y gana</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton">Controles del ratón</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Terminando">Finalizando</a></li> +</ol> + +<p>Empezar con JavaScript puro es la mejor forma de adquirir un conocimiento sólido sobre desarrollo de juegos. Después, puedes escoger cualquier entorno de desarrollo (framework) que te guste y usarlo para tus proyectos. Los frameworks son simplemente herramientas construidas con el lenguaje JavaScript; por tanto aunque planees trabajar con ellas, es bueno aprender primero sobre el mismo lenguaje para saber exactamente qué es lo que hay por debajo. Los frameworks aceleran el tiempo de desarrollo y ayudan a tener en cuenta las partes aburridas del juego, pero si algo no funciona como esperas, siempre puedes intentar depurarlo o simplemente escribir tu solución en JavaScript puro.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estás interesado en aprender sobre el desarrollo de juegos en 2D usando una entorno de desarrollo, consulta esta serie homóloga, <a href="/en-US/docs/Games/Workflows/2D_breakout_game_Phaser">famoso juego 2D usando Phaser</a>.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Esta serie de artículos puede usarse como material para talleres prácticos de desarrollo de juegos. También puedes hacer uso del <a href="/en-US/docs/">kit de contenido canvas Gamedev</a> basado en este tutorial si quieres dar una charla sobre desarrollo de juegos en general.</p> +</div> + +<h2 id="Siguientes_pasos">Siguientes pasos</h2> + +<p>Vale, ¡vamos a empezar! Dirígete hacia el primer tema — <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it">Crea el lienzo (canvas) y dibuja en él</a>.</p> + +<p>{{Next("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it")}} </p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html new file mode 100644 index 0000000000..65e32f0ac2 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html @@ -0,0 +1,53 @@ +--- +title: Controles del ratón +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Mouse_controls +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/en-US/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Terminando")}}</p> + +<div class="summary"> +<p>Este es el noveno paso de 10 del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">tutorial Canvas para el desarrollo de juegos</a>. Puedes encontrar el código y pegarle un vistazo después de completar esta lección <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson09.html">Gamedev-Canvas-workshop/lesson9.html</a>.</p> +</div> + +<p>El juego en sí está terminado, así que ahora vamos a pulirlo. Ya le hemos puesto el control del teclado y ahora le añadiremos el control del ratón<span class="seoSummary">.</span></p> + +<h2 id="Detectar_el_movimiento_del_ratón">Detectar el movimiento del ratón</h2> + +<p>Detectar el movimiento del ratón es más fácil que detectar las pulsaciones de las teclas. Todo lo que necesitamos es un añadir "escuchador" al evento {{event("mousemove")}}.Añade esta línea destrás de los otros "listeners", justo debajo del evento <code>keyup</code>:</p> + +<pre class="brush: js">document.addEventListener("mousemove", mouseMoveHandler, false);</pre> + +<h2 id="Asociar_el_movimiento_de_la_pala_con_el_movimiento_del_ratón">Asociar el movimiento de la pala con el movimiento del ratón</h2> + +<p>Podemos cambiar la posición de la pala basándonos en las coordenadas del puntero del ratón. Eso es lo que hace la función siguiente. Añádela detrás de la línea que acabas de añadir:</p> + +<pre class="brush: js">function mouseMoveHandler(e) { + var relativeX = e.clientX - canvas.offsetLeft; + if(relativeX > 0 && relativeX < canvas.width) { + paddleX = relativeX - paddleWidth/2; + } +}</pre> + +<p>En esta función calculamos un valor <code style="font-style: normal; font-weight: normal;">relativeX</code>, que es la posición horizontal del ratón en el "viewport" (<code style="font-style: normal; font-weight: normal;">e.clientX</code>), menos la distancia entre el borde izquierdo del terreno de juego y el borde izquierdo del "viewport" (<code style="font-style: normal; font-weight: normal;">canvas.offsetLeft</code>).</p> + +<p>Si el valor resultante es mayor que cero y menor que el ancho del terreno de juego, es que el ratón está dentro de los límites, y calculamos la posición de la paleta poniéndole el valor <code style="font-style: normal; font-weight: normal;">relativeX</code> menos la mitad del ancho de la paleta, para que el movimiento sea de verdad relativo a la mitad de la paleta.</p> + +<p>Ahora, la paleta seguirá la posición del cursor del ratón pero, como restringimos el movimiento al <canvas>, no desaparecerá completamente por los lados.</p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Aquí tienes el código para comparar:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/L3gngab5/","","320")}}</p> + +<div class="summary"> +<p>Ejercicio: ajusta los límites del movimiento de la pala para que siempre se vea la pala completa (ahora sólo se ve media en los laterales).</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>Ya tenemos el juego terminado, pero aún lo podemos mejorar con algunos trucos <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Terminando">Finalizando</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Terminando")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html new file mode 100644 index 0000000000..60a5df8c5a --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html @@ -0,0 +1,154 @@ +--- +title: Mueve la bola +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Mueve_la_bola +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Move_the_ball +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/es-ES/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls")}}</p> + +<div class="summary"> +<p>Este es el segundo paso de los 10 del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">tutorial de Canvas para el desarrollo de juegos</a>. Puedes encontrar el código fuente como debería quedar después de completar la lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson02.html">Gamedev-Canvas-workshop/lesson2.html</a>.</p> +</div> + +<p><span id="result_box" lang="es"><span>Ya sabes cómo dibujar una pelota, lo has aprendido en el artículo anterior. Ahora vamos a hacer que se mueva.</span> <span>Técnicamente, estaremos pintando la pelota en la pantalla, borrándola y luego pintándola de nuevo en una posición ligeramente diferente cada fotograma para dar la impresión de movimiento, igual que se hace en las películas.</span></span></p> + +<p> </p> + +<h2 id="Definir_un_bucle_de_dibujo">Definir un bucle de dibujo</h2> + +<p> </p> + +<p><span id="result_box" lang="es"><span>Para actualizar el dibujo del lienzo en cada fotograma, necesitamos definir una función de dibujo que se ejecutará una y otra vez, cambiando una serie de variables para modificar la posición de cada personaje (sprite). Para que una misma función se ejecute una y otra vez puedes utilizar una función </span><span>de sincronización de JavaScript, como</span></span> {{domxref("WindowTimers.setInterval()", "setInterval()")}} or {{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}.</p> + +<p><span id="result_box" lang="es"><span>Elimina todo el código JavaScript que tienes ahora mismo en de tu archivo HTML, excepto las dos primeras líneas, y añade lo siguiente debajo de ellas.</span> <span>La función draw() se ejecutará dentro de setInterval cada 10 milisegundos:</span></span></p> + +<pre class="brush: js">function draw() { + // código para dibujar +} +setInterval(draw, 10);</pre> + +<p><span id="result_box" lang="es"><span>Gracias a la naturaleza infinita de setInterval, la función draw () se llamará cada 10 milisegundos por siempre, o hasta que lo detengamos.</span> <span>Ahora, vamos a dibujar la bola. A</span></span><span lang="es"><span>grega lo siguiente dentro de tu función draw ():</span></span></p> + +<pre class="brush: js">ctx.beginPath(); +ctx.arc(50, 50, 10, 0, Math.PI*2); +ctx.fillStyle = "#0095DD"; +ctx.fill(); +ctx.closePath(); +</pre> + +<p>Prueba tu código actualizado ahora — la bola debería repintarse en cada fotograma (frame).</p> + +<h2 id="Hacer_que_se_mueva">Hacer que se mueva</h2> + +<div id="gt-res-content"> +<div class="trans-verified-button-small" dir="ltr">Aunque la bola se está dibujando cada 10 milisegundos no se nota porque no hay movimiento, se dibuja una y otra vez en el mismo sitio.<span id="result_box" lang="es"><span>Vamos a cambiar eso.</span> <span>En primer lugar, en lugar de dibujar siempre en la posición (50, 50) definiremos un punto de inicio en la parte central inferior del lienzo en las variables llamadas x e y, a continuación, las utilizaremos para definir la posición en la que se dibuja el círculo.</span><br> +<br> +<span>Primero, agrega las dos líneas siguientes a la función draw (), para definir x e y:</span></span></div> +</div> + +<p> </p> + +<pre class="brush: js">var x = canvas.width/2; +var y = canvas.height-30; +</pre> + +<p> </p> + +<p>A continuación actualiza la función <code>draw()</code> para usar las variables x e y en el método {{domxref("CanvasRenderingContext2D.arc()","arc()")}}, como se muestra en la siguiente línea resaltada:</p> + +<pre class="brush: js; highlight:[3]">function draw() { + ctx.beginPath(); + ctx.arc(x, y, 10, 0, Math.PI*2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); +} +</pre> + +<p><span id="result_box" lang="es"><span>Ahora viene la parte importante: queremos añadir un valor pequeño a x e y después de que cada fotograma se haya dibujado para que parezca que la pelota se está moviendo.</span> <span>Definamos estos valores pequeños como dx y dy, y establezcamos sus valores en 2 y -2 respectivamente.</span> <span>Agrega lo siguiente debajo de sus definiciones de variables x e y:</span></span></p> + +<pre class="brush: js">var dx = 2; +var dy = -2; +</pre> + +<p><span id="result_box" lang="es"><span>Lo último que hay que hacer es actualizar x e y con nuestras variables dx y dy en cada fotograma, de modo que la bola será pintada en la nueva posición en cada actualización.</span> <span>Agrega las dos nuevas líneas</span></span><span lang="es"><span> siguientes indicadas a continuación a la función draw ():</span></span></p> + +<pre class="brush: js; highlight:[7,8]">function draw() { + ctx.beginPath(); + ctx.arc(x, y, 10, 0, Math.PI*2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); + x += dx; + y += dy; +}</pre> + +<p><span id="result_box" lang="es"><span>Guarda el código de nuevo y pruébalo en tu navegador.</span> <span>Esto funciona bien, aunque parece que la bola está dejando un rastro detrás de ella:</span></span></p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/10430/ball-trail.png" style="display: block; height: 320px; margin: 0px auto; width: 480px;"></p> + +<h2 id="Borrar_el_lienzo_antes_de_cada_fotograma">Borrar el lienzo antes de cada fotograma</h2> + +<div id="gt-res-content"> +<div class="trans-verified-button-small" dir="ltr" id="gt-res-dir-ctr"><span id="result_box" lang="es"><span>La bola está dejando un rastro porque estamos pintando un nuevo círculo en cada fotograma sin borrar el anterior.</span> <span>No te preocupes, porque hay un método para borrar todo el contenido de lienzo: {{domxref ("CanvasRenderingContext2D.clearRect ()", "clearRect ()")}}.</span> <span>Este método tiene cuatro parámetros: las coordenadas x e y de la esquina superior izquierda de un rectángulo y las coordenadas x e y de la esquina inferior derecha de un rectángulo.</span> En todo el área definida por ese rectángulo se borrará cualquier cosa que se haya pintado antes<span>.</span></span></div> +</div> + +<div id="gt-res-tools"> +<div id="gt-res-tools-l"> +<div id="gt-pb-star"> </div> +</div> +</div> + +<p>Añade la siguiente nueva línea resaltada a la función draw():</p> + +<pre class="brush: js; highlight:[2]">function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.beginPath(); + ctx.arc(x, y, 10, 0, Math.PI*2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); + x += dx; + y += dy; +} +</pre> + +<p><span id="result_box" lang="es"><span>Guarda tu código y vuelve a probarlo. Esta vez verás el movimiento de la bola sin dejar rastro.</span> <span>Cada 10 milisegundos se borra todo el lienzo, se dibuja el círculo azul (nuestra pelota) en una posición determinada y los valores x e y se actualizan para el siguiente fotograma.</span></span></p> + +<h2 id="Limpiar_el_código">Limpiar el código</h2> + +<p><span id="result_box" lang="es"><span>Vamos a añadir más y más comandos a la función draw () en los próximos artículos, por lo que es bueno mantenerlo lo más simple y limpio posible.</span> <span>Comencemos moviendo el código de dibujo de la bola a una función separada.</span><br> + <br> + <span>Reemplaza la función draw() con las dos funciones siguientes:</span></span></p> + +<pre class="brush: js">function drawBall() { + ctx.beginPath(); + ctx.arc(x, y, 10, 0, Math.PI*2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); +} + +function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + drawBall(); + x += dx; + y += dy; +}</pre> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p><span id="result_box" lang="es"><span>Puedes comprobar el código terminado de este artículo en la demostración en vivo a continuación, y jugar con ella para entender mejor cómo funciona:</span></span></p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","415")}}</p> + +<div class="summary"> +<p>Ejercicio: intenta cambiar la velocidad de la bola en movimiento o la dirección hacia la que se mueve.</p> +</div> + +<h2 id="Siguientes_pasos">Siguientes pasos</h2> + +<p>Hemos dibujado nuestra bola y hemos hecho que se mueva, pero cuando supera el borde del canvas, desaparece. En el tercer capítulo exploraremos como hacer que <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls">rebote en las paredes</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Create_the_Canvas_and_draw_on_it", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html new file mode 100644 index 0000000000..81403423c7 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html @@ -0,0 +1,130 @@ +--- +title: Control de la pala y el teclado +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Control_pala_y_teclado +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/es/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego")}}</p> + +<div class="summary"> +<p>Este es el cuarto de los 10 pasos del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Tutorial de Canvas para el desarrollo de juegos</a>. Puedes encontrar el código fuente como debería quedar después de completar la lección en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson04.html">Gamedev-Canvas-workshop/lesson4.html</a>.</p> +</div> + +<p> </p> + +<p><span class="seoSummary">La bola está rebotando en las paredes libremente y puedes estar mirándola toda la vida, pero, ahora mismo, no hay interactividad. ¡No es un juego si no puedes controlarlo! Vamos a añadirle la interacción del usuario: una paleta.</span></p> + +<h2 id="Definir_una_paleta_para_golpear_la_bola">Definir una paleta para golpear la bola</h2> + +<p>Necesitamos una paleta para golpear la bola. Empezamos por definir variables para conseguirlo. Añade las variables siguientes en la parte de arriba de tu código, junto a las que ya tenías:</p> + +<pre class="brush: js">var paddleHeight = 10; +var paddleWidth = 75; +var paddleX = (canvas.width-paddleWidth)/2;</pre> + +<p>paddleHeight servirá para definir la altura de la paleta, paddleWidth la anchura y paddleX la posición en el eje X en la que empieza a dibujarse. Definimos una función que dibujará la paleta en la pantalla. Añade este código justo después de la función <code>drawBall()</code>:</p> + +<pre class="brush: js">function drawPaddle() { + ctx.beginPath(); + ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + ctx.closePath(); +}</pre> + +<h2 id="Permitir_que_el_usuario_controle_la_paleta">Permitir que el usuario controle la paleta</h2> + +<p>Podemos dibujar la paleta donde queramos, pero debería responder a las acciones del usuario. Ha llegado la hora de implementar algunos controles de teclado. Vamos a necesitar:</p> + +<ul> + <li>Dos variables para guardar la información sobre si se ha pulsado el botón izquierdo o el derecho.</li> + <li>Dos funciones (event listeners) que respondan a los eventos <code>keydown</code> y <code>keyup</code> (pulsar tecla, liberar tecla). Queremos que se ejecute algún código para manejar la paleta cuando se pulsen los botones.</li> + <li>Dos funciones que manejen los eventos <code>keydown</code> y <code>keyup</code> que se ejecutarán cuando se pulsen los botones.</li> + <li>La habilidad de mover la paleta a la izquierda y a la derecha</li> +</ul> + +<p>Empezaremos por definir las variables que nos dirán si se ha pulsado un botón. Añade estas líneas donde has definido las demás variables:</p> + +<pre class="brush: js">var rightPressed = false; +var leftPressed = false;</pre> + +<p>Las dos las inicializamos con el valor <code>false</code> porque al principio no están pulsados los botones. Para "escuchar" las pulsaciones de las teclas necesitamos definir dos "escuchadores de eventos" (event listeners). Añade las líneas siguientes justo antes de <code>setInterval()</code> al final de tu código:</p> + +<pre class="brush: js">document.addEventListener("keydown", keyDownHandler, false); +document.addEventListener("keyup", keyUpHandler, false);</pre> + +<p>Cuando ocurra el evento <code>keydown</code> al pulsar cualquier tecla del teclado, la función <code>keyDownHandler()</code> se ejecutará. Cuando se liberará la tecla pulsada, se ejecutará la función <code>keyUpHandler()</code>. Añade esto después de las líneas del <code>addEventListener()</code> que acababas de escribir:</p> + +<pre class="brush: js">function keyDownHandler(e) { + if(e.keyCode == 39) { + rightPressed = true; + } + else if(e.keyCode == 37) { + leftPressed = true; + } +} + +function keyUpHandler(e) { + if(e.keyCode == 39) { + rightPressed = false; + } + else if(e.keyCode == 37) { + leftPressed = false; + } +}</pre> + +<p>Cuando pulsamos una tecla se ejecuta keyDownHandler(e), que pone en la variable "e" los datos que necesitamos. Efectivamente, e.keyCode nos va a decir qué tecla se ha pulsado. Si vale 37 es porque se ha pulsado la "flecha izquierda" del teclado. El código 39 representa a la "flecha derecha".</p> + +<p>Pues bien, cuando se pulsará la "flecha izquierda" pondremos leftPressed a true.</p> + +<p>Cuando se liberará la "flecha izquierda" pondremos leftPressed a false.</p> + +<p>De igual forma procederá el programa con la "flecha derecha", detectando el código 39 y dando los valores oportunos a la variable rightPressed.</p> + +<h3 id="La_lógica_del_movimiento_de_la_paleta">La lógica del movimiento de la paleta</h3> + +<p>Ya tenemos las variables que contienen la información sobre las teclas pulsadas, los escuchadores de eventos y las funciones relevantes. Ahora vamos a ocuparnos del código que utilizará todo eso y moverá la paleta en la pantalla. Dentro de la función <code>draw()</code> comprobaremos si está pulsada la flecha izquierda o la derecha cada vez que se dibuje un fotograma. Nuestro código podría tener este aspecto:</p> + +<pre class="brush: js">if(rightPressed) { + paddleX += 7; +} +else if(leftPressed) { + paddleX -= 7; +}</pre> + +<p>Si se pulsa la flecha izquierda, la paleta se moverá 7 píxeles a la izquierda. Si se pulsa la flecha derecha, se moverá 7 píxeles a la derecha. Aunque esto funciona bien, la paleta desaparece en los laterales del terreno de juego si mantenemos pulsada una tecla demasiado tiempo. Podemos mejorar esto para que se mueva dentro de los límites del canvas, cambiando el código así:</p> + +<pre class="brush: js">if(rightPressed && paddleX < canvas.width-paddleWidth) { + paddleX += 7; +} +else if(leftPressed && paddleX > 0) { + paddleX -= 7; +}</pre> + +<p>La posición paddleX que estamos utilizando variará entre 0 para la lado izquierdo y <code style="font-style: normal; font-weight: normal;">canvas.width-paddleWidth</code> para el lado derecho, que es justo lo que queremos.</p> + +<p>Añade el código anterior dentro de la función <code>draw(), al final</code>, justo antes de la llave que cierra.</p> + +<p>Lo único que nos falta por hacer es llamar a la función <code>drawPaddle()</code> desde dentro de la función <code>draw()</code> para que dibuje la paleta dentro en la pantalla. Añade la línea siguiente dentro de <code>draw(), justo antes de la línea que llama a la función</code> <code>drawBall()</code>:</p> + +<pre class="brush: js">drawPaddle(); +</pre> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Aquí está el código que funciona, para que lo compares con el tuyo:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/tgn3zscj/","","320")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: haz que la paleta se mueva más deprisa o más despacio, o cambia su tamaño.</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>Ahora mismo tenemos algo que parece un juego. El único problema es que todo lo que puedes hacer es golpear la bola con la paleta toda la vida (en realidad, ni siquiera la golpeas). Todo esto cambiará en el quinto capítulo, <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego">Fin del juego</a>, cuando añadiremos un estado de "Game Over".</p> + +<div> </div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Bounce_off_the_walls", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Fin_del_juego")}}</p> diff --git a/files/es/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html b/files/es/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html new file mode 100644 index 0000000000..b67a730e94 --- /dev/null +++ b/files/es/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html @@ -0,0 +1,92 @@ +--- +title: Poner un contador y terminar ganando +slug: Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Track_the_score_and_win +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win +--- +<div>{{GamesSidebar}}</div><div>{{IncludeSubnav("/en-US/docs/Games")}}</div> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton")}}</p> + +<div class="summary"> +<p>Este es el octavo capítulo de 10, del <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Gamedev Canvas tutorial</a>. Puedes encontrar el código fuente como debería quedar tras este capítulo en <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson08.html">Gamedev-Canvas-workshop/lesson8.html</a>.</p> +</div> + +<p><span class="seoSummary">Destruir los ladrillos mola, pero para que el juego sea aún mejor, podría dar puntos cada vez que el jugador rompe un ladrillo, y mostrar un contador.</span></p> + +<h2 id="El_contador">El contador</h2> + +<p>Si puedes ver el contador mientras juegas, puede que consigas impresionar a tus amigos. Necesitas una variable para guardar el contador. Añade esto a tu JavaScript, después de las otras definiciones de variables:</p> + +<pre class="brush: js">var score = 0;</pre> + +<p>También necesitas una función <code>drawScore()</code> para enseñar el contador por pantalla. Añade esto después de la función <code>collisionDetection()</code>:</p> + +<pre class="brush: js">function drawScore() { + ctx.font = "16px Arial"; + ctx.fillStyle = "#0095DD"; + ctx.fillText("Score: "+score, 8, 20); +}</pre> + +<p>Dibujar texto en el <canvas> es similar a dibujar un círculo o cualquier otra figura. La definición del tipo de letra (fuente) se hace igual que en CSS, puedes fijar el tamaño y fuente con el método {{domxref("CanvasRenderingContext2D.font","font()")}} method. Despúes utilizas {{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}} para fijar el color y {{domxref("CanvasRenderingContext2D.fillText","fillText()")}} para escribir el texto y el lugar en el que se va a dibujar. El primer parámetro es el texto en si y los otros dos son las coordenadas.</p> + +<p>Para sumar un punto cada vez que se rompe un ladrillo, añade la línea que está marcada aquí debajo:</p> + +<pre class="brush: js; highlight:[9]">function collisionDetection() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var b = bricks[c][r]; + if(b.status == 1) { + if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) { + dy = -dy; + b.status = 0; + score++; + } + } + } + } +}</pre> + +<p>Llamando a <code>drawScore()</code> (dibujar contador) desde la función <code>draw()</code> hace que se muestre el contador actualizado en la pantalla. Añade la línea siguiente en <code>draw()</code>, justo debajo de la llamada a <code>drawPaddle()</code>:</p> + +<pre class="brush: js">drawScore();</pre> + +<h2 id="Mostrar_un_mensaje_de_victoria_cuando_se_hayan_destruido_todos_los_ladrillos">Mostrar un mensaje de victoria cuando se hayan destruido todos los ladrillos</h2> + +<p>Lo de sumar puntos funciona, pero tiene un final. ¿Qué ocurrirá cuando no queden ladrillos? Precisamente ese es el principal objetivo del juego, tendrás que dibujar un mensaje de victoria. Añade las líneas marcadas a tu función <code>collisionDetection()</code>:</p> + +<pre class="brush: js; highlight:[10,11,12,13]">function collisionDetection() { + for(c=0; c<brickColumnCount; c++) { + for(r=0; r<brickRowCount; r++) { + var b = bricks[c][r]; + if(b.status == 1) { + if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) { + dy = -dy; + b.status = 0; + score++; + if(score == brickRowCount*brickColumnCount) { + alert("YOU WIN, CONGRATULATIONS!"); + document.location.reload(); + } + } + } + } + } +}</pre> + +<p>Gracias a esto, los jugadores pueden ganar cuando rompen todos los ladrillos, que es muy importante. La función <code>document.location.reload()</code> vuelve a cargar la página y el juego empieza de nuevo, una vez se hace clic sobre el botón del alert().</p> + +<h2 id="Compara_tu_código">Compara tu código</h2> + +<p>Puedes comparar tu código con este:</p> + +<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/mvfkcydz/","","320")}}</p> + +<div class="note"> +<p><strong>Ejercicio</strong>: añade más puntos por ladrillo y muestra el contador cuando salga el alert() del final del juego con victoria.</p> +</div> + +<h2 id="Pasos_siguientes">Pasos siguientes</h2> + +<p>El juego, ahora mismo, ya tiene buena pinta. En la siguiente lección conseguirás que sea más atractivo porque añadirás el <a href="https://developer.mozilla.org/es/docs/Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton">Control del ratón</a>.</p> + +<p>{{PreviousNext("Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Deteccion_colisiones", "Games/Workflows/Famoso_juego_2D_usando_JavaScript_puro/Controles_raton")}}</p> diff --git a/files/es/games/tutorials/html5_gamedev_phaser_device_orientation/index.html b/files/es/games/tutorials/html5_gamedev_phaser_device_orientation/index.html new file mode 100644 index 0000000000..135193ec50 --- /dev/null +++ b/files/es/games/tutorials/html5_gamedev_phaser_device_orientation/index.html @@ -0,0 +1,437 @@ +--- +title: >- + Introducción al Desarrollo de Juegos en HTML5 con Phaser y la API de + Orientación a Dispositivos +slug: Games/Workflows/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 +--- +<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><canvas></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"><!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <title>Cyber Orb</title> + <style> body { margin: 0; background: #333; } </style> + <script src="src/phaser.min.js"></script> + <script src="src/Boot.js"></script> + <script src="src/Preloader.js"></script> + <script src="src/MainMenu.js"></script> + <script src="src/Game.js"></script> +</head> +<body> +<script> +(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'); +})(); +</script> +</body> +</html></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><head></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><body></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><canvas></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><canvas></code>. Si no hay nada especificado en el último argumento o el elemento no es encontrado, el <code><canvas></code> será añadido a la etiqueta <code><body></code>. Sin el <em>framework </em>para añadir el elemento canvas hubieses tenido que escribir algo como esto dentro de la etiqueta <code><body></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"><</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">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>canvas</span><span class="punctuation token">></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"><</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"><</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">>=</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> diff --git a/files/es/games/tutorials/index.html b/files/es/games/tutorials/index.html new file mode 100644 index 0000000000..3a0807cc77 --- /dev/null +++ b/files/es/games/tutorials/index.html @@ -0,0 +1,10 @@ +--- +title: Workflows for different game types +slug: Games/Workflows +tags: + - NeedsTranslation + - TopicStub +translation_of: Games/Tutorials +--- +<div>{{GamesSidebar}}</div><p>This page will contain links to different article series covering different workflows for effectively creating different types of web games, whether you want to create a 2D or 3D game from scratch, or port a C++ or Flash game over to open web technologies.</p> +<p>For example, a <a href="/en-US/docs/Games/Workflows/HTML5_Gamedev_Phaser_Device_Orientation">2D maze game with Phaser and the Device Orientation API</a>.</p> |