Actualización sobre la versión 1.1 anterior en la que se ha añadido la aparición aleatoria de los clásicos «items» que caen por la ventana cuando se rompen algunos ladrillos y proporcionan más puntos e incluso bolas extras cuando se capturan con la paleta.
Modificaciones realizadas
Resumen de las modificaciones realizadas en el código fuente JavaScript de la versión 1.1 del juego Arkanoid para obtener la versión 1.2:
– Añadidos dos tipos de «items» que aparecen de forma aleatoria al romper algunos ladrillos. Por una parte los marcados con una letra «P» que proporcionan más puntos. Y por otra parte los marcados con una letra «B» que proporcionan una bola extra.
Código fuente
Al ser un programa escrito completamente en JavaScript, todo el código fuente se encuentra embebido dentro de la propia página HTML desde la que se ejecuta el juego, por lo que para acceder al mismo basta con seleccionar la opción «ver código fuente de la página» del navegador.
Cambios en la clase Board
Para incluir los items dentro del tablero de juego se ha añadido el atributo items a la clase Board.
this.items = new Array();
Y para permitir que haya más de una pelota al mismo tiempo en juego se ha cambiado el atributo ball original de la clase por el array balls.
this.balls = new Array();
Los items se crean aleatoriamente cuando se destruye un ladrillo mediante la función createItem, que limita a tres el número de items presentes en la ventana a un mismo tiempo.
this.createItem = function(left, top) { if ( (this.items.length < 3) && (Math.random() < 0.5) ) { var id = "item" + String( new Date().getTime() ); this.items.push( new Item(this, this.createDiv(id, "item", left, top, 10, 8) ) ); this.divBoard.appendChild(this.items[this.items.length - 1].div); } }
El ID asignado a cada uno de los items se compone concatenando a la palabra «item» la hora actual del sistema con el propósito de que cada item tenga un identificador distinto. Evidentemente, si se crean dos items distintos en el mismo segundo entonces ambos tendrán el mismo ID.
El método destroyItems por su parte se encarga de realizar el proceso contrario, de destruir los items creados cuando se cambia de nivel de nivel o se inicia una partida nueva. Su código, como el de otras funciones nuevas añadidas para la gestión de los items, es muy similar a los ya existentes para el resto de elementos del juego y no creo que requieran mayor explicación.
this.destroyItems = function() { for (var i in this.items) this.divBoard.removeChild(this.items[i].div); this.items.length = 0; }
Para conseguir el efecto de caida por la ventana de los items se ha modificado el método onTimer para que además de reenviar los eventos de reloj a la pelota los reenvie también a los items.
this.onTimer = function() { for (var i in this.balls) this.balls[i].onTimer(); for (var i in this.items) this.items[i].onTimer(); }
Tal y como se aprecia en el método anterior, se han modificado las funciones para que en vez de realizar su proceso considerando como hasta ahora una única pelota tengan en cuenta que puede haber más de una pelota en juego. El cambio ha sido igual para todas, así que sirva de muestra el método displayBalls.
El código de la versión anterior era el siguiente:
this.displayBall = function() { if (this.ball) this.divBoard.appendChild(this.ball.div); }
Y el código de la nueva versión es ahora este:
this.displayBalls = function() { for (var i in this.balls) this.divBoard.appendChild(this.balls[i].div); }
El resto de cambios realizados en la clase Board son puramente estéticos. Se ha cambiado el nombre de los métodos sustituyendo ball por su plural balls. Por ejemplo, destroyBall ahora es destroyBalls, y ballOut ahora es ballsOut.
Items
La clase que representa los items es muy sencilla y muy similar a las ya existentes anteriormente para representar los ladrillos, la paleta y la pelota.
En los atributos board y div de esta clase se guardan las referencias a los objetos HTML que se le pasan como parámetros en el constructor. En left, top, width y height la posición y tamaño del item. En el atributo speed la velocidad de caida. En broken se indica si el item ha sido capturado por la paleta, se inicializa a false para indicar que está cayendo libremente y se cambia a true para borrarlo del tablero cuando es capturado por la paleta. Y por último, en el atributo effect se almacena la letra «P» o «B», elegida de forma aleatoria, y que identifica el efecto que provoca el item.
function Item(board, div) { this.board = board; this.div = div; this.left = pxToNumber(this.div.style.left); this.top = pxToNumber(this.div.style.top); this.width = pxToNumber(this.div.style.width); this.height = pxToNumber(this.div.style.height); this.speed = 2; this.broken = false; this.effect = (Math.random() < 0.75)? "P": "B"; this.div.innerHTML = this.effect;
El efecto de caida por la ventana de los items se consigue cambiando su posición a intervalos regulares de tiempo. El método onTimer, que recibe los eventos de reloj, se limita a llamar al método move de la clase.
this.onTimer = function() { this.move(this.speed); }
El código de los métodos que se utilizan para mover el item es prácticamente igual al que se explicó para la paleta en versiones anteriores del Arkanoid, con la única diferencia que los items se mueven verticalmente en vez de horizontalmente. Es decir, en vez de actualizar el atributo left se actualiza el atributo top.
this.move = function(speed) { var top = this.top; var newTop = this.top; var deltaTop = this.getNewTop(speed) - this.top; var delta = Math.abs(deltaTop); for (var i = 0; i < delta; ++ i) { top += (deltaTop / delta); if ( this.board.checkHitStick(this.left, top, this.width, this.height) ) { this.broken = true; break; } newTop = top; } this.moveTop(newTop); } this.getNewTop = function(delta) { var newTop = Math.max(this.top + delta, this.board.minTop); return( Math.min(newTop, this.board.maxTop - this.height) ); } this.moveTop = function(newTop) { if (this.top != newTop) { this.top = newTop; this.div.style.top = String(this.top) + "px"; } }
El último método del que consta la clase es getPoints, que retorna el número de puntos que hay que sumar a la puntuación actual cuando se captura el item con la paleta.
this.getPoints = function() { return(23); } }
Se ha escogido el valor 23 como puntuación por ser un número primo que genera puntuaciones dificiles de adivinar como se han generado cuando crecen un poco. Una puntuación que va creciendo de 5 en 5 o una cantidad similar no suele resultar actrativa.
CSS
Se ha añadido una nueva clase CSS para los items. Lo único reseñable de esta nueva clase con respecto a todas las anteriores ya existentes es que establece un tamaño de fuente fijo de 7 pixeles para que se visualicen correctamente las letras dentro de los items.
.item { position: absolute; overflow: hidden; color: #000000; background: #FF9900; font-size: 7px; text-align: center; }
Puntos de Mejora
La principal mejora que se podría hacer al juego es aumentar su jugabilidad o incluir algún aspecto novedoso dentro del mismo. Arkanoid es un juego muy popular y conocido por todo el mundo, por lo que para conseguir que alguien juegue a una nueva versión se debe ofrecer algo más que una versión simplificada del original.
Un cambio importante y no muy difícil de realizar sería la inclusión de distintos tipos de item aparte de los dos ya existentes. Las posibilidades en este aspecto son inmensas: paletas extras, cambios en el tamaño de la paleta, lasers o algún otro tipo de arma incrustada en la paleta que disparasen contra los ladrillos, cambios en el tamaño de la pelota, ladrillos invisibles o indestructibles por un tiempo limitado, y así un largo etcétera.
Otro cambio importante a realizar sería modificar el control que se tiene sobre la pelota, ya que actualmente el jugador se limita a poner la paleta en su trayectoria y esperar que se produzca el rebote sobre la misma. Este comportamiento se podría mejorar haciendo que los rebotes se vieran afectados por la velocidad y dirección en la que se mueve la paleta.
La inclusión de sonido también podría hacer más atractivo el juego. Aunque esta opción presenta el problema de que JavaScript no ofrece nativamente funciones de sonido, por lo que el funcionamiento del programa en este aspecto debería hacerse depender de cada navegador en particular. Además, incluir ficheros de sonido aumentaría considerablemente el tiempo de descarga.
En lo que al código fuente se refiere, a poco que se examine con un mínimo de detalle el mismo, es claro que se presentan muchas oportunidades para simplificar y reducir el tamaño de los fuentes haciendo una clase genérica, llamémosla Token, de la que hereden todos los elementos que intervienen en el juego. Resulta muy claro que tanto los ladrillos como la paleta y la pelota tienen atributos y métodos muy similares. En la clase Board, en vez de tener un atributo por cada uno de estos tipos de elemento, habría que tener un único array de esta nueva clase Token y tratar a todos los elementos por igual. Esto permitiría además implementar de forma fácil otros tipos de efectos, como tener ladrillos que se moviesen horizontalmente por ejemplo, haciendo más variadas y entretenidas las partidas.