Juego de nave espacial HTML5 - Canvas 1.- Dibujar el fondo y la nave Usa de Canvas HTML5 y JavaScript para crear un campo aleatorio de estrellas blancas y dibujar una nave espacial verde y naranja parecida a un platillo volador. Las imágenes del juego se crean con píxeles. El elemento Canvas permite colocar píxeles directamente en la pantalla mediante el modo inmediato. Esta función hace que sea muy fácil dibujar puntos, líneas y formas exactamente donde quieras y en el color que elijas. Esta muestra de código cubre las siguientes tareas que demuestran los principios básicos sobre el uso de Canvas para dibujar estos elementos de un juego: Agregar un elemento Canvas a una página web Crear un fondo negro Dibujar estrellas aleatorias en el fondo Agregar una nave espacial al fondo <!DOCTYPE html> <html> <head> <script type="text/javascript"> // This function is called on page load. function canvasSpaceGame() { // Get the canvas element. canvas = document.getElementById("myCanvas"); // Make sure you got it. if (canvas.getContext) // If you have it, create a canvas user inteface element. { // Specify 2d canvas type. ctx = canvas.getContext("2d"); // Paint it black. ctx.fillStyle = "black"; ctx.rect(0, 0, 300, 300); ctx.fill(); // Paint the starfield. stars(); // Draw space ship. makeShip(); } } // Paint a random starfield. function stars() { // Draw 50 stars. for (i = 0; i <= 50; i++) { // Get random positions for stars. var x = Math.floor(Math.random() * 299) var y = Math.floor(Math.random() * 299) Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 1 Juego de nave espacial HTML5 - Canvas // Make the stars white ctx.fillStyle = "white"; // Give the ship some room. if (x < 30 || y < 30) ctx.fillStyle = "black"; // Draw an individual star. ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } } function makeShip() { // Draw saucer bottom. ctx.beginPath(); ctx.moveTo(28.4, 16.9); ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0); ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9); ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8); ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9); ctx.closePath(); ctx.fillStyle = "rgb(222, 103, 0)"; ctx.fill(); // Draw saucer top. ctx.beginPath(); ctx.moveTo(22.3, 12.0); ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3); ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0); ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7); ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0); ctx.closePath(); ctx.fillStyle = "rgb(51, 190, 0)"; ctx.fill(); } </script> </head> <body onload="canvasSpaceGame()"> <h1> Canvas Space Game </h1> <canvas id="myCanvas" width="300" height="300"> </canvas> </body> </html> Código del cuerpo La etiqueta del cuerpo usa la función de carga para llamar a la función canvasSpaceGame al cargar la página. La etiqueta de Canvas es parte del cuerpo. Se especifican el ancho y alto iniciales de Canvas, así como el atributo de Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 2 Juego de nave espacial HTML5 - Canvas identificador. Hay que especificar el identificador para poder agregar el elemento de Canvas al modelo de objetos de la página. Código de script Función canvasSpaceGame Esta función se llama al cargar la página. Obtiene el elemento Canvas mediante el Id. de este elemento en el código del cuerpo. Después se genera el contexto del elemento Canvas y se prepara para aceptar el dibujo. Después de inicializar el contexto como Canvas 2D, el elemento Canvas se pinta de negro con la propiedad fillStyle y los métodos rect y fill. Función stars Esta función se invoca desde canvasSpaceGame. Usa for loop para generar 50 posiciones posibles de estrellas en una superficie x,y, y usa fillStyle para crear un color blanco. A continuación, se realiza una comprobación para ver si las coordenadas "x" e "y" están demasiado cerca de la esquina superior izquierda. Si una estrella está demasiado cerca de la esquina superior izquierda, se cambia fillStyle a negro para que no interfiera con la nave espacial. Después se dibuja cada estrella con el método arc y se usa el color de relleno apropiado. Función makeShip Esta función se invoca desde canvasSpaceGame. Al usar una serie métodos beginPath, moveTo, bezierCurveTo, closePath, fillStyle y fill, se dibuja una nave espacial simple. Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx de 3 Juego de nave espacial HTML5 - Canvas 2.- Mover la nave Se indica cómo mover la nave espacial en el campo de estrellas. El elemento Canvas usa el modo inmediato para crear imágenes en movimiento. Se necesitan dos pasos para implementar esta función en el programa de juegos. En primer lugar, volver a dibujar la imagen cada vez que se la mueve. En segundo lugar, restaurar el fondo que se destruyó cuando se dibujó la nave espacial sobre él. Esta muestra de código cubre las siguientes tareas que demuestran los principios básicos sobre el uso de Canvas para mover un objeto por un fondo detallado: Establecer un bucle de juego para procesar los eventos principales del juego Capturar pulsaciones de teclas para determinar si la nave debe moverse a continuación Guardar el fondo adonde se moverá la nave Mover la nave a su nueva posición Restablecer el fondo anterior que la nave estaba cubriendo <!DOCTYPE html> <html> <head> <script type="text/javascript"> // Global variables var shipX = 0; // X position of ship var shipY = 0; // Y position of ship var canvas; // canvas var ctx; // context var back = new Image(); // storage for new background piece var oldBack = new Image(); // storage for old background piece var ship = new Image(); // ship var shipX = 0; // current ship position X var shipY = 0; // current ship position Y var oldShipX = 0; // old ship position Y var oldShipY = 0; // old ship position Y // This function is called on page load. function canvasSpaceGame() { // Get the canvas element. canvas = document.getElementById("myCanvas"); // Make sure you got it. if (canvas.getContext) // If you have it, create a canvas user inteface element. { // Specify 2d canvas type. ctx = canvas.getContext("2d"); // Paint it black. ctx.fillStyle = "black"; ctx.rect(0, 0, 300, 300); ctx.fill(); // Save the initial background. back = ctx.getImageData(0, 0, 30, 30); // Paint the starfield. stars(); Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 4 Juego de nave espacial HTML5 - Canvas // Draw space ship. makeShip(); } // Play the game until the until the game is over. gameLoop = setInterval(doGameLoop, 16); // Add keyboard listener. window.addEventListener('keydown', whatKey, true); } // Paint a random starfield. function stars() { // Draw 50 stars. for (i = 0; i <= 50; i++) { // Get random positions for stars. var x = Math.floor(Math.random() * 299); var y = Math.floor(Math.random() * 299); // Make the stars white ctx.fillStyle = "white"; // Give the ship some room by painting black stars. if (x < 30 || y < 30) ctx.fillStyle = "black"; // Draw an individual star. ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); // Save black background. oldBack = ctx.getImageData(0, 0, 30, 30); } } function makeShip() { // Draw saucer bottom. ctx.beginPath(); ctx.moveTo(28.4, 16.9); ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0); ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9); ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8); ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9); ctx.closePath(); ctx.fillStyle = "rgb(222, 103, 0)"; ctx.fill(); // Draw saucer top. ctx.beginPath(); ctx.moveTo(22.3, 12.0); ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3); Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 5 Juego de nave espacial HTML5 - Canvas ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0); ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7); ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0); ctx.closePath(); ctx.fillStyle = "rgb(51, 190, 0)"; ctx.fill(); // Save ship data. ship = ctx.getImageData(0, 0, 30, 30); // Erase it for now. ctx.putImageData(oldBack, 0, 0); } function doGameLoop() { // Put old background down to erase shipe. ctx.putImageData(oldBack, oldShipX, oldShipY); // Put ship in new position. ctx.putImageData(ship, shipX, shipY); } // Get key press. function whatKey(evt) { // Flag to put variables back if we hit an edge of the board. var flag = 0; // Get where the ship was before key process. oldShipX = shipX; oldShipY = shipY; oldBack = back; switch (evt.keyCode) { // Left arrow. case 37: shipX = shipX - 30; if (shipX < 0) { // If at edge, reset ship position and set flag. shipX = 0; flag = 1; } break; // Right arrow. case 39: shipX = shipX + 30; if (shipX > 270) { // If at edge, reset ship position and set flag. shipX = 270; flag = 1; } break; Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 6 Juego de nave espacial HTML5 - Canvas // Down arrow case 40: shipY = shipY + 30; if (shipY > 270) { // If at edge, reset ship position and set flag. shipY = 270; flag = 1; } break; // Up arrow case 38: shipY = shipY - 30; if (shipY < 0) { // If at edge, reset ship position and set flag. shipY = 0; flag = 1; } break; } // If flag is set, the ship did not move. // Put everything back the way it was. if (flag) { shipX = oldShipX; shipY = oldShipY; back = oldBack; } else { // Otherwise, get background where the ship will go // So you can redraw background when the ship // moves again. back = ctx.getImageData(shipX, shipY, 30, 30); } } </script> </head> <body onload="canvasSpaceGame()"> <h1> Canvas Space Game </h1> <canvas id="myCanvas" width="300" height="300"> </canvas> </body> </html> Código del cuerpo El código del cuerpo es el mismo que el código del contenido de la primera tarea de este escenario: "Dibujar el fondo y tu vehículo". Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 7 Juego de nave espacial HTML5 - Canvas Código de script Se invocan variables globales cuando se carga la página. Se invoca la función canvasSpaceGame desde el atributo onload de la etiqueta del contenido. Se llama al resto de las funciones desde la función canvasSpaceGame. Variables globales Este programa usa una variable global para los datos a los que se obtendrá acceso desde diferentes funciones. Las variables las incluyen en la siguiente lista: canvas y context: es posible que desees que estas variables sean globales para la mayoría de los programas de Canvas, ya que obtendrás acceso a ellas desde muchas funciones. back, oldBack: imágenes que almacenan las instantáneas de 30 x 30 píxeles del fondo anterior y nuevo. ship: imagen que almacena los píxeles para la nave espacial. shipX, shipY: las coordenadas x e y para la nave espacial. oldShipX, oldShipY: las coordenadas x e y de la última posición de la nave espacial. Función canvasSpaceGame Esta función se basa en la misma función de la primera tarea de este escenario: "Dibujar el fondo y tu vehículo". Se realizaron las siguientes modificaciones: Se creó una instantánea de 30 x 30 píxeles usando el método getImageData y guardándolo en la variable back. Esta variable se usa más tarde cuando se mueve la nave. Una llamada a setInterval, que ejecuta la función doGameLoop cada 16 milisegundos. Este intervalo se cancelará al final del juego usando gameLoop. Se establece un controlador de eventos usando addEventListener. Esto llama a la función whatKey cada vez que se produce el evento keydown. Función stars Esta función es la misma que la función stars de la primera tarea: "Dibujar el fondo y tu vehículo". La única diferencia es que se guarda una instantánea de 30 x 30 píxeles del fondo en la imagen de la variable oldBack con el fin de usarla más adelante. Función makeShip Esta función es la misma que la función makeShip de la primera tarea de este escenario: "Dibujar el fondo y tu vehículo". La única diferencia es que se guarda una instantánea de 30 x 30 píxeles de la nave en la imagen del ship con el fin de usarla más adelante. Función doGameLoop El temporizador gameLoop invoca esta función cada 16 milisegundos. Los bucles de juegos son muy comunes en los juegos porque realizan tareas básicas de animación a intervalos regulares. El bucle de juego invoca dos tareas de animación: Erasing the ship : si la nave se mueve y deja la marca de la nave en el fondo, debes restaurar la imagen anterior del fondo. Esto usa el método putImageData. Si no realizas esta acción, cada vez que muevas la nave, quedará la imagen anterior de la nave. Debes saber qué había debajo de la nave antes de que se moviera y copiar la imagen para borrar la imagen de la nave anterior y reemplazarla por la imagen del fondo que estaba allí anteriormente. Moving the ship: debes copiar la imagen de la nave en su nueva posición. Dado que esto destruirá cualquier imagen que había allí anteriormente, debes guardar el fondo antes de destruirlo. Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 8 Juego de nave espacial HTML5 - Canvas Función whatKey Se invoca esta función cada vez que se presiona una tecla. Determina a dónde desea el jugador que se mueva la nave. Es importante tener en cuenta que la nave no se mueve realmente en esta función. El movimiento se calcula, pero la acción de dibujar la nueva nave se realiza en la función doGameLoop. La función whatKey contiene las siguientes acciones: Se usará una marca para determinar qué sucede si la nave llega al borde de la pantalla. Antes de que se mueva, debes guardar las posiciones de x e y de la nave, y guardar el fondo que se encuentra debajo de la nave. Esto es necesario porque el modo inmediato no guarda automáticamente ningún píxel en la pantalla. A continuación, una instrucción switch procesa el evento y busca el código de tecla del evento. Los códigos de tecla corresponden a las teclas izquierda, derecha, arriba y abajo del teclado. Para cada caso relevante de código de tecla, se calculan las nuevas posiciones de x e y. Si la nueva posición de la nave la movería fuera del lienzo, se cancela y se marca como establecida. Si la marca está establecida, las variables de la nave y el fondo vuelven a su estado original. En caso contrario, se usa el método getImageData para guardar la instantánea de fondo actual. Animación de Canvas Canvas tiene dos maneras para crear animaciones. La primera es la forma de animación más común, en la que la pantalla se vuelve a dibujar completamente para obtener cada movimiento. Esto funciona mejor si tienes una pequeña superficie de dibujo de lienzo y un equipo rápido. Sin embargo, no se recomienda para animaciones más grandes o más complejas. La segunda manera en que Canvas crea animaciones se indica en la muestra de código incluida en este tema. Este método se recomienda para los casos en que hay animaciones de Canvas más grandes y más complejas. Este estilo de animación es más avanzado. Si bien requiere un código más grande para establecerlo, se ejecuta mucho más rápido que el estilo de animación más común. Se ejecuta más rápido porque solo se cambian unos pocos píxeles individuales en cada movimiento, no toda la pantalla de píxeles. El estilo de animación más rápido que se muestra aquí usa los siguientes pasos. Estos pasos se repiten de forma cíclica para cada movimiento. Borra la nave al dibujar arriba de ella una instantánea de 30 x 30 píxeles con la imagen del fondo anterior. Obtén una nueva instantánea del fondo que se cubrirá cuando se mueva la nave. Dibuja la nave en su nueva posición. Dado que este bucle circular sucede cada 16 milisegundos, el ojo humano no ve que la nave se borra; solo ve que la nave se mueve. Esto disminuye el riesgo de que la pantalla parpadee entre cada movimiento, dado que solo se dibuja una pequeña parte de la pantalla en cada ocasión. Puedes cargar el juego y con las flechas del teclado puedes mover la nave. Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 9 Juego de nave espacial HTML5 - Canvas 3.- Detectar colisiones Se explica detectar si la nave espacial colisiona contra un asteroide rojo o contra la base central azul. Esta muestra indica cómo usar Canvas para hacer un seguimiento de cada píxel en la pantalla. Debido a que usa el modo inmediato, Canvas cuenta con la capacidad para definir la posición y el valor de color de cada píxel. Debido a que Canvas te permite leer y escribir cada píxel, puedes crear animaciones detalladas que se ejecutan de forma rápida y eficiente. Esta muestra de código te indica cómo asignar valores específicos de color a los píxeles para crear asteroides rojos y una base central azul. Podrás detectar colisiones al tomar instantáneas de la pantalla para examinar objetos en color que la nave espacial debe sortear. Esta muestra de código cubre las siguientes tareas que demuestran los principios básicos sobre el uso de Canvas para detectar el color de diferentes objetos. Dibujar asteroides y una base central con colores específicos para su detección posterior. Tomar instantáneas de lo que la nave espacial tiene enfrente. Examinar instantáneas para detectar objetos en color y mostrar mensajes. <!DOCTYPE html> <html> <head> <script type="text/javascript"> // Global variables var shipX = 0; // X position of ship var shipY = 0; // Y position of ship var canvas; // canvas var ctx; // context var back = new Image(); // storage for new background piece var oldBack = new Image(); // storage for old background piece var ship = new Image(); // ship var shipX = 0; // current ship position X var shipY = 0; // current ship position Y var oldShipX = 0; // old ship position Y var oldShipY = 0; // old ship position Y // This function is called on page load. function canvasSpaceGame() { // Get the canvas element. canvas = document.getElementById("myCanvas"); // Make sure you got it. if (canvas.getContext) // If you have it, create a canvas user inteface element. { // Specify 2d canvas type. ctx = canvas.getContext("2d"); // Paint it black. ctx.fillStyle = "black"; ctx.rect(0, 0, 300, 300); ctx.fill(); // Save the initial background. back = ctx.getImageData(0, 0, 30, 30); Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 10 Juego de nave espacial HTML5 - Canvas // Paint the starfield. stars(); // Draw space ship. makeShip(); // Draw asteroids. drawAsteroids(); } // Play the game until the until the game is over. gameLoop = setInterval(doGameLoop, 16); // Add keyboard listener. window.addEventListener('keydown', whatKey, true); } // Paint a random starfield. function stars() { // Draw 50 stars. for (i = 0; i <= 50; i++) { // Get random positions for stars. var x = Math.floor(Math.random() * 299); var y = Math.floor(Math.random() * 299); // Make the stars white ctx.fillStyle = "#EEEEEE"; // Paint the star but not if too close to ship. if (x > 40 && y > 40) { // Draw an individual star. ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } else--i; } // Save black background. oldBack = ctx.getImageData(0, 0, 30, 30); } function makeShip() { // Draw saucer bottom. ctx.beginPath(); ctx.moveTo(28.4, 16.9); ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0); ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9); ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8); ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9); ctx.closePath(); ctx.fillStyle = "rgb(222, 103, 0)"; Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 11 Juego de nave espacial HTML5 - Canvas ctx.fill(); // Draw saucer top. ctx.beginPath(); ctx.moveTo(22.3, 12.0); ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3); ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0); ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7); ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0); ctx.closePath(); ctx.fillStyle = "rgb(51, 190, 0)"; ctx.fill(); // Save ship data. ship = ctx.getImageData(0, 0, 30, 30); // Erase it for now. ctx.putImageData(oldBack, 0, 0); } function doGameLoop() { // Put old background down to erase shipe. ctx.putImageData(oldBack, oldShipX, oldShipY); // Put ship in new position. ctx.putImageData(ship, shipX, shipY); } // Get key press. function whatKey(evt) { // Flag to put variables back if we hit an edge of the board. var flag = 0; // Get where the ship was before key process. oldShipX = shipX; oldShipY = shipY; oldBack = back; switch (evt.keyCode) { // Left arrow. case 37: shipX = shipX - 30; if (shipX < 0) { // If at edge, reset ship position and set flag. shipX = 0; flag = 1; } break; // Right arrow. case 39: shipX = shipX + 30; if (shipX > 270) { Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 12 Juego de nave espacial HTML5 - Canvas // If at edge, reset ship position and set flag. shipX = 270; flag = 1; } break; // Down arrow case 40: shipY = shipY + 30; if (shipY > 270) { // If at edge, reset ship position and set flag. shipY = 270; flag = 1; } break; // Up arrow case 38: shipY = shipY - 30; if (shipY < 0) { // If at edge, reset ship position and set flag. shipY = 0; flag = 1; } break; default: flag = 1; alert("Please only use the arrow keys."); } // If flag is set, the ship did not move. // Put everything back the way it was. if (flag) { shipX = oldShipX; shipY = oldShipY; back = oldBack; } else { // Otherwise, get background where the ship will go // So you can redraw background when the ship // moves again. back = ctx.getImageData(shipX, shipY, 30, 30); } collideTest(); } function collideTest() { // Collision detection. Get a clip from the screen. var clipWidth = 20; var clipDepth = 20; var clipLength = clipWidth * clipDepth; // alert(clipLength); var clipOffset = 5; Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 13 Juego de nave espacial HTML5 - Canvas var whatColor = ctx.getImageData(shipX + clipOffset, shipY + clipOffset, clipWidth, clipDepth); // Loop through the clip and see if for (var i = 0; i < clipLength * 4; if (whatColor.data[i] == 255) { alert("red"); break; } // Second element is green but we if (whatColor.data[i + 2] == 255) alert("blue"); break; } // Fourth element is alpha and we } you find red or blue. i += 4) { don't care. { don't care. } function drawAsteroids() { // Draw asteroids. for (i = 0; i <= 20; i++) { // Get random positions for asteroids. var a = Math.floor(Math.random() * 299); var b = Math.floor(Math.random() * 299); // Make the asteroids red ctx.fillStyle = "#FF0000"; // Keep the asteroids far enough away from // the beginning or end. if (a > 40 && b > 40 && a < 270 && b < 270) { // Draw an individual asteroid. ctx.beginPath(); ctx.arc(a, b, 10, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } else--i; } // Draw blue base. ctx.fillStyle = "#0000FF"; ctx.beginPath(); ctx.rect(270, 270, 30, 30); ctx.closePath(); ctx.fill(); } </script> </head> <body onload="canvasSpaceGame()"> <h1> Canvas Space Game </h1> Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 14 Juego de nave espacial HTML5 - Canvas <canvas id="myCanvas" width="300" height="300"> </canvas> </body> </html> Código del cuerpo El código del cuerpo es igual al del tema “mover la nave”. Código de script Se invocan variables globales cuando se carga la página. Se llama a la función canvasSpaceGame desde el atributo onload de la etiqueta del contenido. Se llama al resto de las funciones desde la función canvasSpaceGame. Función canvasSpaceGame Esta función es muy similar a la que aparece en la segunda tarea de este escenario: "Cómo mover el vehículo". La única modificación consiste en agregar una llamada a la función drawAsteroids, que dibuja los asteroides y la base central en la pantalla. Función stars Esta función es muy similar a la función stars en la segunda tarea de este escenario: "Cómo mover el vehículo". La única diferencia es que el color de la estrella (star) recibe un valor de color diferente. En la función stars de la segunda tarea de este escenario: "Mover la nave", el color de la estrella era "blanco". (El valor de cuatro bytes es 100% rojo, azul, verde y alfa, o “#FFFFFF”.) Pero en esta tarea, las estrellas reciben el valor de color de “#EEEEEE”, que es casi blanco (los valores de cuatro bytes son 94% rojo, verde, azul y alfa). El valor parece blanco porque muestra solamente un indicio de color. Es necesario mostrar un indicio de color cuando se examina la pantalla para detectar colisiones, ya que el uso del blanco puro causa problemas. Cuando examinas la pantalla en búsqueda de colisiones y buscas un objeto que sea 100% rojo, es posible que obtengas un falso positivo para una estrella blanca, porque una estrella "blanca" es 100% roja en su interior. Si trabajas con porcentajes precisos de rojo, verde, azul y alfa, podrás realizar detecciones de colisiones muy precisas y sutiles. Esto es de suma importancia, ya que casi todos los juegos Arcade requieren la detección de colisiones en el juego. Otro beneficio que se obtiene al usar los colores precisos es que se puede mantener el tamaño pequeño de la instantánea y llevar a cabo exámenes rápidos de los valores de color, lo que hace que la detección de colisiones sea aún más rápida. Función makeShip Esta función es similar a la función makeShip en la segunda tarea de este escenario: "Cómo mover el vehículo". La única diferencia es que se guarda una instantánea de 30 x 30 píxeles del barco en la imagen del barco con el fin de usarla más adelante. Función whatKey Esta función tiene un código muy similar al de la función whatKey en la segunda tarea de este escenario: "Cómo mover el vehículo". La única diferencia es que se agrega una llamada a la función collideTest después de que se procesan los eventos clave. Esto sucede porque cada vez que se presiona una tecla, se puede originar una colisión. Por lo tanto, debes ver lo que sucedió. Hasta que el barco se mueva, no es necesario que desperdicies ciclos para detectar colisiones, ya que, en este juego, no se mueve nada más. Función collideTest Esta nueva función determina si la nave ha colapsado contra un asteroide o contra la base central. Esta acción se lleva a cabo en dos pasos. El primer paso consiste en tomar una instantánea de la pantalla en el punto donde el barco se está por mover. La función whatKey ya ha calculado esta ubicación. Los datos de la instantánea constituyen una matriz simple y lineal de valores de color de cuatro bytes, que comienza en la esquina izquierda superior y continúa de izquierda a derecha en filas y después continúa por cada fila hasta la esquina derecha Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 15 Juego de nave espacial HTML5 - Canvas inferior. El tamaño de la matriz es 4 veces (por el valor de color de 4 bytes) el tamaño de la longitud y el ancho. Para una instantánea de 20 x 20, el tamaño sería 4 x 20 x 20 o 1600. El segundo paso consiste en examinar los datos de la instantánea, cuatro bytes a la vez. Intenta ver si un valor 100% rojo (255) está en el primer byte. Si es así, hay un asteroide. Asimismo, intenta ver si un valor 100% azul (255) está en el tercer byte. Si es así, has aterrizado en la base central. El segundo y el tercer byte no son importantes en este ejemplo, ya que no buscas un valor verde o alfa. Si un valor 100% rojo está en el primer byte, se muestra un cuadro de alerta que te informa que has encontrado "rojo". De manera similar, si un valor 100% azul está en el tercer byte, un cuadro de alerta te informa que has encontrado "azul". En la próxima tarea de este escenario, aprenderás cómo encontrar el valor rojo o azul finaliza el juego, pero en esta tarea del escenario, puedes continuar después de cerrar el cuadro de alerta. Esta simple tarea de tomar una instantánea y examinar los datos para bytes específicos de color puede resultar efectiva para detectar colisiones. Es posible que las instantáneas grandes no sean eficientes. No obstante, un diseño cuidadoso de su arte te permitirá detectar los objetos en pantalla de forma rápida y efectiva. Es muy rápido el examen de una matriz de 1600 bytes cada vez que presionas la tecla. Colores de los píxeles del lienzo Para leer o escribir píxeles de color en la pantalla, debes asignar un valor de color a cada píxel. Este valor está compuesto por cuatro partes: rojo, verde, azul y alfa. Por ejemplo, un píxel blanco está formado por 100% rojo, 100% verde, 100% azul y 100% alfa. (Alfa se refiere a la cantidad de transparencia que muestra un color). Cada valor de color de píxel del lienzo se almacena como una matriz de cuatro bytes. Los cuatro bytes corresponden al porcentaje de rojo, verde, azul y alfa en cada píxel. (Los bytes van de 0 a 255 para los números decimales y de #0 a #FF para los números hexadecimales). Para obtener más información acerca de los nombres y valores numéricos de colores específicos, consulta http://msdn.microsoft.com/en-us/library/ms531197(VS.85).aspx. Los diseñadores web normalmente usan los nombres de los colores ("rojo") o los valores hexadecimales (“#FF0000”) para definir los colores. Canvas usa esos sistemas de notación, pero también usa la función rgb para indicar los primeros tres bytes de color, o la función rgbasi necesitas definir el valor alfa. Si el valor alfa no se define, se asume que es 100%. Por ejemplo, rojo sería rgb (255,0,0). Ten en cuenta que la función rgb se usó para definir colores cuando dibujaste el barco original, que aparece anteriormente en este tema, con la funciónmakeShip. El código en esta muestra detalla cómo Canvas usa el modo inmediato para leer los colores de píxeles para detectar colisiones entre los objetos. Canvas hace esto al leer un bloque de píxeles en la pantalla y determinar qué partes del bloque contienen un valor de color particular. Por ejemplo, si deseas que tu programa de juegos reconozca si el asteroide rojo está cerca de tu barco, puedes tomar una instantánea de la pantalla y examinarla para determinar si contiene rojo. Si es así, tu programa reconoce que hay un asteroide. Como consecuencia, el programa ya está preparado para reaccionar ante la acción del jugador. Si el jugador bombardea al asteroide, este estalla. Si el jugador se estrella contra un asteroide, la nave espacial del jugador estalla. Función drawAsteroids Esta función es nueva. Es muy similar a la función stars en la segunda tarea de este escenario: "Mover la nave". La función drawAsteroids emplea la misma lógica que la función stars, pero hace que el tamaño de cada asteroide sea más grande en el método arc de Canvas y hace fillStyle “#FF0000”, que es rojo puro. Definir el color asegura que la rutina de detección de colisiones, cuando buscas 255 en el primer byte del valor de color en la función collideTest, encuentre siempre "rojo". El bucle del dibujo se asegura de que el asteroide no esté demasiado cerca de la ubicación inicial del barco o de la base central. Si los asteroides se dibujan demasiado cerca o el bucle no dibuja un asteroide, el recuento aumenta y el bucle circula una vez más. La función drawAsteroids también dibuja la base azul. Usa el valor de color de “#0000FF”, que es "azul" puro. La base es un simple rectángulo. Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 16 Juego de nave espacial HTML5 - Canvas 4.- Quitar obstáculos y realizar el seguimiento de las puntuaciones Se explica cómo crear estas rápidas acciones animadas al cambiar los píxeles individuales directamente en la pantalla. Esta técnica se puede usar de forma eficaz para mover o modificar objetos durante el juego. Esta muestra de código indica cómo modificar píxeles para lanzar bombas verdes desde la nave espacial para destruir los asteroides rojos. Cuando las bombas golpean a los asteroides, los asteroides se rompen y la nave espacial puede volar de forma segura para llegar a la base central. Esta muestra de código cubre las siguientes tareas que demuestran los principios básicos sobre el uso de Canvas para quitar obstáculos y llevar la puntuación: Capturar pulsaciones de tecla para lanzar bombas Modificar píxeles para mover objetos y simular explosiones Crear una segunda pantalla de lienzo para mostrar la puntuación Realizar un seguimiento de las acciones para calcular las puntuaciones <!DOCTYPE html> <html> <head> <script type="text/javascript"> // Global variables var shipX = 0; // X position of ship var shipY = 0; // Y position of ship var canvas; // canvas var ctx; // context var back = new Image(); // storage for new background piece var oldBack = new Image(); // storage for old background piece var ship = new Image(); // ship var bomb = new Image(); // neutralizer ray field var shipX = 0; // current ship position X var shipY = 0; // current ship position Y var oldShipX = 0; // old ship position Y var oldShipY = 0; // old ship position Y var direction = "R"; // direction of ship movement var score = 0; // score // This function is called on page load. function canvasSpaceGame() { // Get the main canvas element. canvas = document.getElementById("myCanvas"); // Get the score canvas element. canvas2 = document.getElementById("myScore"); // Initialize the score element. if (canvas2.getContext) // If you have it, create score element. { // Specify score 2d canvas type. ctx2 = canvas2.getContext("2d"); } // Initialize main element. if (canvas.getContext) Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 17 Juego de nave espacial HTML5 - Canvas // If you have it, create a canvas user inteface element. { // Specify main 2d canvas type. ctx = canvas.getContext("2d"); // Paint it black. ctx.fillStyle = "black"; ctx.rect(0, 0, 300, 300); ctx.fill(); // Save the initial background. back = ctx.getImageData(0, 0, 30, 30); // Paint the starfield. stars(); // Draw space ship. makeShip(); // Draw asteroids. drawAsteroids(); } // Play the game until the until the game is over. gameLoop = setInterval(doGameLoop, 16); // Add keyboard listener. window.addEventListener('keydown', whatKey, true); } // Paint a random star field. function stars() { // Draw 50 stars. for (i = 0; i <= 50; i++) { // Get random positions for stars. var x = Math.floor(Math.random() * 299); var y = Math.floor(Math.random() * 299); // Make the stars white ctx.fillStyle = "#EEEEEE"; // Paint the star but not if too close to ship. if (x > 40 && y > 40) { // Draw an individual star. ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } else--i; } // Save black background. oldBack = ctx.getImageData(0, 0, 30, 30); } Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 18 Juego de nave espacial HTML5 - Canvas function makeShip() { // Draw saucer bottom. ctx.beginPath(); ctx.moveTo(28.4, 16.9); ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0); ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9); ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8); ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9); ctx.closePath(); ctx.fillStyle = "rgb(222, 103, 0)"; ctx.fill(); // Draw saucer top. ctx.beginPath(); ctx.moveTo(22.3, 12.0); ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3); ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0); ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7); ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0); ctx.closePath(); ctx.fillStyle = "rgb(51, 190, 0)"; ctx.fill(); // Save ship data. ship = ctx.getImageData(0, 0, 30, 30); // Erase it for now. ctx.putImageData(oldBack, 0, 0); } function doGameLoop() { // Put old background down to erase shipe. ctx.putImageData(oldBack, oldShipX, oldShipY); // Put ship in new position. ctx.putImageData(ship, shipX, shipY); } // Get key press. function whatKey(evt) { // Flag to put variables back if we hit an edge of the board. var flag = 0; // Get where the ship was before key process. oldShipX = shipX; oldShipY = shipY; oldBack = back; switch (evt.keyCode) { // Left arrow. case 37: shipX = shipX - 30; Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 19 Juego de nave espacial HTML5 - Canvas if (shipX < 0) { // If at edge, reset ship position and set flag. shipX = 0; flag = 1; } direction = "L"; break; // Right arrow. case 39: shipX = shipX + 30; if (shipX > 270) { // If at edge, reset ship position and set flag. shipX = 270; flag = 1; } direction = "R"; break; // Down arrow case 40: shipY = shipY + 30; if (shipY > 270) { // If at edge, reset ship position and set flag. shipY = 270; flag = 1; } direction = "D"; break; // Up arrow case 38: shipY = shipY - 30; if (shipY < 0) { // If at edge, reset ship position and set flag. shipY = 0; flag = 1; } direction = "U"; break; // A key for drawing neutralizer field case 65: // Using this increases your score. score = score + 20; // The ship isn't moving. flag = 1; // Draw the neutralizing ray which will let you pass. neutralize(); break; // If any other keys were presssed default: Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 20 Juego de nave espacial HTML5 - Canvas flag = 1; // Don't move the ship. alert("Please only use the arrow keys."); } // If flag is set, the ship did not move. // Put everything back the way it was. // Reduce score since the ship did not move. if (flag) { shipX = oldShipX; shipY = oldShipY; back = oldBack; score = score - 1; } else { // Otherwise, get background where the ship will go // So you can redraw background when the ship // moves again. back = ctx.getImageData(shipX, shipY, 30, 30); } // Increase score. score = score + 1; // Draw score on scoreboard. ctx2.clearRect(0, 0, 300, 300); ctx2.font = "20 point Ariel"; ctx2.fillText("Score", 20, 15); ctx2.fillText(score, 100, 15); // Did we collide? collideTest(); } function collideTest() { // Collision detection. Get a clip from the screen. // See what the ship would move over. var clipWidth = 20; var clipDepth = 20; var clipLength = clipWidth * clipDepth; var clipOffset = 5; var whatColor = ctx.getImageData(shipX + clipOffset, shipY + clipOffset, clipWidth, clipDepth); // Loop through the clip and see if for (var i = 0; i < clipLength * 4; if (whatColor.data[i] == 255) { direction = "P"; break; } // Second element is green but we if (whatColor.data[i + 2] == 255) direction = "B"; break; you find red or blue. i += 4) { don't care. { Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 21 Juego de nave espacial HTML5 - Canvas } // Fourth element is alpha and we don't care. } // Did we hit something? if (direction == "P") bang(); if (direction == "B") youWin(); } function bang() { // You lose. alert("Game over! You hit an asteroid."); // Stop game. clearTimeout(gameLoop); window.removeEventListener('keydown', whatKey, true); } function youWin() { // You win. alert("Game over! You made it to home base."); // Stop game. clearTimeout(gameLoop); window.removeEventListener('keydown', whatKey, true); } function drawAsteroids() { // Draw asteroids. for (i = 0; i <= 20; i++) { // Get random positions for asteroids. var a = Math.floor(Math.random() * 299); var b = Math.floor(Math.random() * 299); // Make the asteroids red ctx.fillStyle = "#FF0000"; // Keep the asteroids far enough away from // the beginning or end. // Draw an individual asteroid. ctx.beginPath(); ctx.arc(a, b, 10, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } // Draw green for neutralizer. ctx.fillStyle = "#00FF00"; ctx.beginPath(); ctx.rect(270, 270, 30, 30); ctx.closePath(); ctx.fill(); // Save it for later. bomb = ctx.getImageData(270, 270, 30, 30); Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 22 Juego de nave espacial HTML5 - Canvas // Draw blue base. ctx.fillStyle = "#0000FF"; ctx.beginPath(); ctx.rect(270, 270, 30, 30); ctx.closePath(); ctx.fill(); // Make some room at beginning. ctx.putImageData(back, 0, 30); ctx.putImageData(back, 30, 0); ctx.putImageData(back, 30, 30); // Make some room at end. ctx.putImageData(back, 240, 240); ctx.putImageData(back, 270, 240); ctx.putImageData(back, 240, 270); } // Create neutralizer field. function neutralize() { // Which way was the ship going? // Put down a neuralizer field that way. switch (direction) { case "D": ctx.putImageData(bomb, shipX, shipY + 30); break; case "U": ctx.putImageData(bomb, shipX, shipY - 30); break; case "L": ctx.putImageData(bomb, shipX - 30, shipY); break; case "R": ctx.putImageData(bomb, shipX + 30, shipY); break; default: } } </script> </head> <body onload="canvasSpaceGame()"> <h1> Canvas Space Game </h1> <canvas id="myCanvas" width="300" height="300"> </canvas> Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 23 Juego de nave espacial HTML5 - Canvas <canvas id="myScore" width="300" height="300"> </canvas> </body> </html> Código del cuerpo La mayor parte del código del cuerpo es el mismo que el código del cuerpo del tema Detección de colisiones. Sin embargo, se incorpora una segunda etiqueta de Canvas que se usará para crear un segundo elemento de lienzo para mostrar el puntaje. Código de script El código de script comienza con el mismo código de script que el tema Detección de colisiones. Sin embargo, modifica casi todos los bloques y agrega varios códigos nuevos. El código de script de esta muestra consta de los siguientes elementos: Variables globales Función canvasSpaceGame Función makeShip Función whatKey Función collideTest Función drawAsteroids Función bang Función youWIn Función neutralize Se invocan variables globales cuando se carga la página. Se invoca la función canvasSpaceGame desde el atributo "onload" de la etiqueta del contenido. Se llama al resto de las funciones desde la función canvasSpaceGame. Variables globales Se agregan dos nuevas variables globales: Direction hace un seguimiento de la dirección en que se está moviendo la nave. Cuando la nave choca con un objeto, esta variable también se usa para determinar cómo finaliza el juego. Score hace un seguimiento del puntaje. Cada vez que se mueve la nave, el puntaje aumenta un punto. Si usas una bomba para destruir un asteroide, se suman 20 puntos al puntaje. El objetivo del juego es volar por el campo de asteroides para llegar a la base central con el menor puntaje posible. Esto se puede lograr al tomar decisiones cuidadosas acerca de si se desea moverse alrededor de los asteroides o si se desea lanzarles bombas. Función canvasSpaceGame Esta función es casi la misma que la función canvasSpaceGame de la tercera tarea de este escenario, "Detección de colisiones". Se agrega un segundo lienzo a esta función para que puedas mostrar la puntuación sin modificar el primer lienzo. Además, se realiza una llamada a la función drawAsteroids para dibujar los asteroides en la pantalla y crear la base central. Función whatKey Esta función comienza con el mismo código que la función whatKey de la tercera tarea de este escenario: "Detección de colisiones", pero se agregan varios elementos nuevos para facilitar el cálculo del puntaje y el lanzamiento de bombas. Si se presionan las teclas arriba, abajo, izquierda o derecha para mover la nave espacial, se guarda la dirección de la nave para que se la pueda usar para determinar dónde aterrizará la bomba. Si se presiona la tecla "A", esto Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 24 Juego de nave espacial HTML5 - Canvas activa la bomba y suma 20 puntos al puntaje. Se coloca la bandera para indicar que la nave no se movió y se invoca la función "neutralize" para dibujar la bomba en la pantalla. La función whatKey también se encarga del puntaje. Si la nave se mueve, se suma un punto. El puntaje se muestra en la segunda pantalla de lienzo. Para esto, primero se borra la pantalla, después se establece la fuente, se dibuja la palabra "Puntuación" y después se muestra un puntaje numérico. Si la nave no se movió, no se suma ningún punto al puntaje. Función collideTest Se modificó esta función desde la función collideTest de la tercera tarea de este escenario, "Detección de colisiones", para determinar qué hacer si ocurre una colisión. Si la nave colisiona con un asteroide, se cambia la variable direction a "P" y se la procesa más adelante. Este otro uso de la variable direction no causará problemas porque la nave ya no puede moverse y, por lo tanto, no tiene una dirección. Si la nave colisiona con la base central, cambia la variable direction a "B" y se la procesa más adelante. Después de haber procesado la instantánea, se realiza una prueba para ver si hubo una colisión. Se invoca la función bang si la nave chocó con un asteroide. Se invoca la función youWin si la nave se acopló a la base central. Función bang Se invoca esta función cuando la nave choca con un asteroide. Se muestra una alerta para indicar que se destruyó la nave y que finalizó el juego. Debes realizar dos acciones adicionales para lograr que el código deje de ejecutarse: Detener el bucle de juego al invocar la función clearTimeout con la variable original gameLoop que creaste cuando estableciste el bucle de juego. De lo contrario, este continuará ejecutándose. También debes detener el agente de escucha de eventos llamando a removeEventListener. Si no realizas esta acción, se continuarán procesando las teclas y se continuarán realizando las acciones. Función youWin Se invoca esta función si la nave se acopla a la base central. Una alerta avisa al jugador que ha ganado el juego. También debes detener el bucle de juego y el agente de escucha de eventos del teclado de la misma manera en que lo hace la función "bang". Función drawAsteroids Esta constituye una pequeña modificación de la función drawAsteroid en la tercera tarea de este escenario, "Detección de colisiones". Un cambio es dibujar un rectángulo verde (que representa los restos de la bomba) antes de dibujar la base central y guardarla para usarla más adelante. El otro cambio es dibujar imágenes negras alrededor de la ubicación inicial de la nave y la base central, mediante el uso de la variable de imagen back. Esto hará que el juego sea un poco más sencillo, ya que no habrá tantos asteroides agolpados en la ubicación de inicio o en la base central. Función neutralize Esta nueva función simplemente toma el valor de dirección y usa la instrucción switch para decidir dónde dibujar la imagen de la bomba. La variable direction determina la ubicación de la bomba. Dado que la imagen de la bomba verde no tiene color rojo ni azul, la nave podrá moverse a través de los restos de la bomba sin que haya una colisión. Esto muestra qué tan fácil es usar Canvas para modificar el comportamiento del juego al manipular los colores de los píxeles de los objetos de la pantalla. Depuración visual Al usar el elemento Canvas para detectar colisiones, puede ser útil ver una instantánea del objeto con el que estás colisionando. No puedes ver el objeto con el que estás colisionando porque la nave espacial lo está tapando. Puedes ver la instantánea de la detección de colisión al agregar esta línea a la función collideTest justo después de calcular la imagen whatColor. ctx2.putImageData(whatColor,50,100); Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 25 Juego de nave espacial HTML5 - Canvas Puedes mostrar la imagen instantánea en un elemento de lienzo separado (ctx2) para que no interfiera con el elemento de lienzo principal donde se está desarrollando el juego. Esta es una técnica valiosa para cuando se está trabajando con juegos de Canvas porque se puede ver qué imágenes se crearon o se están usando. Además, también podrías usar una segunda pantalla de lienzo para escribir datos de variables numéricas a fin de poder hacer fácilmente un seguimiento de los valores intermedios para depuración. Empezar a jugar Para comenzar a jugar, presiona una de las cuatro teclas de flecha del teclado. La nave se mueve en esa dirección. Si conduces la nave hacia un asteroide rojo, la nave se destruye, el juego termina y pierdes. Si un asteroide se encuentra en tu camino y deseas eliminarlo, presiona la tecla "A" para lanzar una bomba verde. La bomba hará explotar el asteroide y podrás volar a través del polvo verde hasta un lugar seguro. La dirección en que se lanza la bomba se basa en tu último movimiento; por ejemplo, si se mueve hacia la izquierda, la bomba se lanzará un espacio a la izquierda de tu nave. Si intentas mover tu nave fuera de la pantalla, el juego no te lo permitirá. Puntuación Durante el juego, el puntaje se muestra continuamente en un elemento de lienzo separado ubicado a la derecha del elemento de lienzo del juego. El puntaje dependerá de la cantidad de veces que muevas la nave y de la cantidad de bombas que lances. Cada movimiento de la nave suma un punto y cada lanzamiento de bomba suma veinte puntos. Tu objetivo es lograr el menor puntaje posible antes de llegar a la base central. Usa las bombas con moderación y elige tu ruta con inteligencia. Finalización del juego Cuando finaliza el juego, puedes apagarlo simplemente cerrando el explorador. Si deseas jugar de nuevo, actualiza la página del explorador para iniciar un juego nuevo. Cada vez que juegues, los asteroides y las estrellas aparecerán en nuevas posiciones aleatorias que te presentarán un nuevo desafío. Código tomado de: https://msdn.microsoft.com/es-es/library/gg589490(v=vs.85).aspx 26