martes, 7 de agosto de 2012

HTML5 - Canvas

Buenas a todos!

[Advertencia: este tutorial es de iniciación en HTML5]

Lo más importante antes de comenzar a pintar objetos y animaciones sobre un canvas es obtener una instancia del elemento <canvas> situado en el DOM de nuestro html, a través de esta instancia obtendremos el contexto de ese canvas y podremos pintar.

Para que ningún novato se pierda os pongo directamente el código html de la página:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>HTML5 Tutorial 1</title>
</head>
<body style="margin:0px;background-color:#ffffff">
<canvas id='c'></canvas>
<script languaje="JavaScript">
  var can;
  var ctx;  

  var backgroundStars_img = new Image();
  backgroundStars_img.src = "back_stars.png";  

  function init() {
    can          = document.getElementById("c");
    ctx          = can.getContext("2d");
    can.width    = 480;
    can.height   = 320;
    ctx.drawImage(backgroundStars_img,0,0,480,320,0,0,480,320);      
  }  

 window.onload = init;

</script>
</body>
</html>


En resumen el código anterior hace lo siguiente, obtiene de la página el elemento canvas con id 'c' sobre la variable 'can', a partir de esta variable obtenemos el contexto 2D del canvas sobre la variable 'ctx'. Hecho esto, configuramos el ancho y alto del canvas (en píxeles). Y finalmente pintamos una imagen sobre el canvas, empleando la función drawImage que pertenece al contexto.

Primero de todo tenemos la creación del elemento canvas como parte del cuerpo de la página, lo más importante es indicar una id para ese elemento, esto nos permitirá recogerlo desde el código javascript.

En el código javascript, primero creamos 3 variables, 'can', 'ctx' y 'backgroundStars_img'.
Inicializamos la variable backgroundStars_img como un objeto imagen y indicamos que la imagen que va a cargar es "back_stars.png".

Seguidamente se declara la función init(). Esta función configurará el canvas y pintará la imagen en su interior.

La sentencia final "window.onload = init", indica que cuando la página se haya cargado por completo, se ejecutará la función "init()".

En la función init, primero inicializamos la variable can, asignando el elemento del DOM canvas, mediante el uso de su id.

  can = document.getElementById("c");

Seguidamente asignamos el contexto 2D del canvas a la variable ctx.

  ctx = can.getContext("2d");

El siguiente paso es configurar las dimensiones del canvas, indicando su ancho y alto:

  can.width    = 480;
  can.height   = 320;


Finalmente pintamos la imagen en el canvas, a través del objeto ctx, que es el que contiene la referencia al contexto 2D del canvas.

ctx.drawImage(backgroundStars_img,0,0,480,320,0,0,480,320);  

La función drawImage permite, dada una imagen, seleccionar una sección de esta, para mostrar únicamente esa sección recortada.

     drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

img: es una instancia de un objeto de tipo Image que contiene la imagen a pintar.
sx: es la coordenada x dentro de la imagen a partir de la que empezamos a recortar.
sy: es la coordenada y dentro de la imagen a partir de la que empezamos a recortar.
swidth: el ancho en píxeles del recorte que haremos a la imagen.
sheight: el alto en píxeles del recorte que haremos a la imagen.
x: la coordenada x dentro del canvas donde pintaremos la imagen.
y: la coordenada y dentro del canvas donde pintaremos la imagen.
width: el ancho que tendrá la imagen final.
height: el alto que tendrá la imagen final.

Hasta aquí este tutorial, espero que haya sido un tutorial claro y que os ayude a dar un primer paso para programar sobre el canvas de HTML5.

Aquí tenéis la imagen que he pintado sobre el canvas:


Un saludo!

lunes, 30 de julio de 2012

Redondeos en JavaScript

Buenas a todos!!
Todos los que hemos trabajado con operaciones numéricas en el navegador, nos hemos encontrado con el problema de los redondeos. No es un problema que únicamente se encuentre en aplicaciones de gestión para realizar operaciones entre campos de un formulario, también es muy común tener que realizar redondeos en los juegos, sobretodo para calcular nuevas coordenadas de posición, o vectores, etc.

Existen diferentes problemas:
- Tengo un número decimal y quiero transformarlo en un número entero!
- Tengo un número decimal y quiero quitarle decimales, pero que estos decimales queden redondeados!
- Tengo un número decimal y quiero quitarle decimales, pero que el decimal final no quede redondeado!

Redondeo: convertir número decimal a número entero

Tenemos dos opciones, emplear la función Math.round o el desplazamiento de bits (bit shifting),
actualmente el bit shifting es la opción que presenta un mejor rendimiento en la mayoría de navegadores, así que es la que recomiendo utilizar.

Bit shifting:
var a = 14.678;
var b = (0.5 + (a)) << 0;

Math.round():
var a = 14.678;
var b = Math.round(a);

Ambos métodos obtienen el mismo resultado, la variable b contiene el valor 15.

Redondeo: redondear un número decimal a un número de decimales concreto

Supongamos que quiero únicamente quedarme con 2 decimales:
Math.round():
var a = 14.678;
var b = Math.round(a*100)/100;

number.toFixed(x):
var a = 14.678;
var b = parseFloat(a.toFixed(2));

Con esto, la variable b contiene el valor 15.68.

Es importante que indique, que la función toFixed(x) es una función para dar formato a un número decimal y que el valor que retorna no es un valor númerico, es un String, por esa razón si queremos realizar operaciones con la variable b, es necesario hacer el casting a float, con parseFloat().

Mucha gente se encuentra con el problema de que está trabajando con toFixed, y que al realizar operaciones con un número convertido usando toFixed, el número resultante es el temido NaN (Not a Number), miran en el log o realizan alerts, y ven que el número es correcto!, tras varios siglos volviéndose locos se dan cuenta de que era un STRING!!

Eliminar decimales de un número sin redondearlo

Ahora no deseamos que se realice ese redondeo final en los decimales:
Bit shifting:
var a = 14.678;
var b = ((a*100) << 0) / 100;

La variable b contiene el valor 15.67.

Bien! Espero haber resuelto dudas sobre este tema!
Un saludo a todos!!


jueves, 29 de marzo de 2012

Classes in javascript

Hola a todos!! Llevaba ya mucho tiempo sin escribir!

El caso es que estoy enfrascado en la implementación de un framework en JavaScript para la creación de juegos en HTML5.
Algo esencial para conseguir que el framework sea lo suficientemente general, reutilizable y flexible, es que esté basado en clases!

Para no extenderme! Las clases en javascript son un recurso impresionante!! son fáciles de implementar, ahorran tiempo, y obtenemos un código limpio, fácil de leer y modificar.

En los lenguajes para la parte del servidor web como Java y PHP la palabra clave para definir una clase es "class"! En JavaScript la palabra clave es la ya conocida function!

Así es! las clases en JavaScript son funciones!

Imaginemos que vamos a hacer un programa web en JS, (si digo JS digo JavaScript que nadie se vuelva loco!), el programa tendrá muchos robots, podrán ser de muchos colores y cada robot tendrá unas coordenadas de posición 'x' e 'y'.
La clase sería como sigue:

function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
}

La palabra this, nos permite definir las propiedades y métodos propios de la clase.

Ya tenemos la clase creada!, ¿cómo creamos un objeto de tipo robot?

var robot1 = new Robot();
De esta forma hemos conseguido definir una variable llamada "robot1" de tipo Robot!!
Lo que ha pasado es lo siguiente, se ha ejecutado la función Robot() (llamada función constructora de la clase), al emplearse la palabra clave "new" el intérprete de JS ha guardado en memoria una instancia concreta de Robot, que contiene 3 espacios de memoria donde están definidos los valores de "x", "y", "color", que son las propiedades definidas como propias de la clase, gracias al uso de la palabra clave "this".

Acceder a la lectura de las propiedades del objeto es tan fácil como esto:


var coordenadax = robot1.x;
var coordenaday = robot1.y;
var color = robot1.color;



Y modificar sus propiedades es tan simple como esto:


robot1.x = 10;
robot1.y = 2;
robot1.color = "#112233";

La clase que hemos definido tan sólo contiene propiedades, pero algo vital en las clases son las funciones!!
Supongamos que tenemos 3 robots en el programa y necesitamos pintar las coordenadas de cada robot siguiendo un formato en concreto:
"x:valor,y:valor"
Podríamos hacer lo siguiente:

document.write("x:"+robot1.x+",y:"+robot1.y);
document.write("x:"+robot2.x+",y:"+robot2.y);
document.write("x:"+robot3.x+",y:"+robot3.y);

Este caso es simple, pero y si la función de pintado requiriera ejecutar un proceso más complejo, con condicionales, bucles, etc? Deberíamos repetir todas esas líneas de código por cada robot!!

Esto en cambio es más fácil!!


function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
this.paintCoords = function(){
document.write("x:"+this.x+",y:"+this.y);
}

}

De la misma forma que definíamos las propiedades de la clase, usando la sintaxis "this.nombre_funcion = function(){...}" definimos los métodos propios de la clase.

Ahora podemos llamar al método paintCoords de cada objeto!

robot1.paintCoords();
robot2.paintCoords();
robot3.paintCoords();

Hay algo IMPORTANTE que he comentado antes! Cuando definimos algo dentro de la función mediante la palabra "this", el intérprete crea en memoria un espacio determinado para esa variable propia de la clase, ya sea una propiedad o método!! Es decir, que por cada variable que creemos de tipo Robot, estaremos copiando el código de las funciones que estén definidas mediante "this"!! QUÉ DESPILFARRO DE MEMORIA!!

Por suerte, JavaScript tiene un recurso: prototype
Como indica la palabra, prototype nos permite definir el prototipo de la clase, es decir, definir la propiedad o función que estará disponible para todas y cada una de las instancias de la clase. Así pues solamente existirá una copia de dicha propiedad o función en memoria, independientemente del número de instancias o variables de clase que creemos.

Vamos a redefinir el método "paintCoords"! Ahora lo incluiremos en el prototipo de la clase!

function Robot(){
this.x = 0;
this.y = 0;
this.color = "#112233";
}
Robot.prototype.paintCoords = function(){
document.write("x:"+this.x+",y:"+this.y);
}

Como podéis ver, la sintaxis es:
NombreClase.prototype.nombreFuncion = function(){...}
Para incluir una propiedad compartida por todas las intancias sería:
NombreClase.prototype.nombrePropiedad = valor;

Una vez definidos tanto métodos como propiedades propios de la clase, su método de empleo es el mismo que para los que están definidos mediante this:

robot1.paintCoords();

Con todo esto, ya podéis crear de forma eficiente vuestras clases propias y usarlas además de una forma eficiente sin consumir en exceso la memoria de los navegadores!

Con esto termina el tutorial sobre la creación de Classes in JavaScript. Espero que os sea de gran ayuda!
Un saludo a todos!!

martes, 10 de enero de 2012

Dog Eastwood

Aquí va una foto!
Una mañana cuando iba a tomarme el café al bar de siempre, me encontré a este perro al más puro estilo Harry Callahan (Clint Eastwood).

Eso es lucir unas gafas.

martes, 16 de agosto de 2011

JQuery games 2

Hola a todos!

Siguiendo el post JQuery games, donde se tratan los temas básicos para empezar con GameQuery, en este tutorial trataremos lo que yo creo que son los puntos básicos para hacer cualquier juego 2D simple o mínimamente complejo para una web:

- Añadir sprites dinámicamente a un group.
- Capturar eventos del mouse con Jquery.
- Mover todos los sprites de una misma clase css.
- Detectar colisiones entre sprites.
- Eliminar sprites de un group.

Para aprender estos puntos, realizaremos un pequeño minijuego en el que irán cayendo burbujas desde arriba y con el mouse podremos poner burbujas donde queramos.
Cuando una burbuja que caiga de arriba toque a alguna que hayamos añadido, ambas desapareceran.


Aquí tenéis los archivos necesarios para realizar el tutorial:
bluesky.png
burbuja.png

JQuery GAMES: Estructura del juego

Seguimos exactamente con la misma estructura que expliqué en el post JQuery Games, con un apartado nuevo, EVENTOS:

$(window).load(function(){

//DECLARACIÓN DE CONSTANTES
//DECLARACIÓN DE VARIABLES

//MAIN FUNCTION//
$(function(){
//CARGA DE IMÁGENES
//CONFIGURACION DEL PLAYGROUND
//INICIALIZACIÓN DE LAS CAPAS DEL PLAYGROUND
//DEFINICIÓN DE LAS CALLBACK FUNCTIONS
//EVENTOS
//INICIAR EL JUEGO : $.playground().startGame();
});
});

JQuery GAMES: Imágenes y Playground

Las variables que almacenaran los sprites de imágenes son:

var background1;
var burbuja = new Array();

Carga de las imágenes:

background1 = new $.gameQuery.Animation({imageURL: "bluesky.png"});
burbuja["normal"] = new $.gameQuery.Animation({imageURL: "burbuja.png"});

La estructura del playground estará compuesta por 3 groups o capas, una capa para el background, una para las burbujas que genera el juego dinámicamente y otra para las burbujas que genera el usuario clicando en la pantalla.

$.playground()
.addGroup("background", {width: PLAYGROUND_WIDTH,
height: PLAYGROUND_HEIGHT})
.addSprite("background1", {animation: background1,
width: PLAYGROUND_WIDTH,
height: PLAYGROUND_HEIGHT})
.end()
.addGroup("bubbleCPULayer", {width: PLAYGROUND_WIDTH,
height: PLAYGROUND_HEIGHT})
.end()
.addGroup("bubblePlayerLayer", {width: PLAYGROUND_WIDTH,
height: PLAYGROUND_HEIGHT});

JQuery GAMES: generar dinámicamente sprites

Para crear dinámicamente sprites cada cierto tiempo, vamos a crear una callback function que se ejecute cada 1000 milisegundos.

/**CALLBACK BUBBLE GENERATOR**/
$.playground().registerCallback(function(){
var name = "bubbleCPU"+Math.ceil(Math.random()*1000);
$("#bubbleCPULayer").addSprite(name, {animation: burbuja["normal"], posx: Math.random()*PLAYGROUND_WIDTH, posy: 0, width: 33, height: 33 });
$("#"+name).addClass("bubbleCPU");
}, 1000);

Primero creamos el nombre que tendrá la nueva burbuja, el nuevo sprite que añadiremos:
var name = "bubbleCPU"+Math.ceil(Math.random()*1000);

Seguidamente añadimos un nuevo sprite al group "bubbleCPULayer" del playground, esto lo hacemos mediante un selector Jquery por id:
$("#bubbleCPULayer").addSprite(name, {.. atributos ..});

Atributos:
animation - imagen que vamos a cargar
posx - posición x donde aparecerá el sprite, es relativa al group en el que se añade
posy - posición y donde aparecerá el sprite, es relativa al group en el que se añade
width - ancho de la imagen que se mostrará
height - alto de la imagen que se mostrará

Esto es IMPORTANTÍSIMO:
Añadimos una clase css a la burbuja que hemos creado dinámicamente:

$("#"+name).addClass("bubbleCPU");

Sin este paso, sin añadir la clase no podremos recoger fácilmente el grupo de todas las burbujas que añadamos dinámicamente, a no ser que vayamos apuntando las id's (algo engorroso si pensamos en que se irán creando y destruyendo).

JQuery GAMES: capturar eventos del mouse

Los eventos del mouse los capturamos mediante una función estándar de JQuery.
Como queremos que cuando cliquemos en la pantalla, se genere dinámicamente una nueva burbuja en la capa o group "bubblePlayerLayer", emplearemos la función click:

/**EVENTOS**/
$("#playground").click(function(e){
mousex = e.pageX;
mousey = e.pageY;
var newx = mousex-20;
var newy = mousey-20;
var name = "bubble_"+Math.ceil(Math.random()*1000);
$("#bubblePlayerLayer").addSprite(name, {animation: burbuja["normal"], posx: newx, posy: newy, width: 33, height: 33 });
$("#"+name).addClass("bubblePlayer");
});

e.pageX - Indica la posición del eje x relativa al div que dispara el evento.
e.pageY - Indica la posición del eje y relativa al div que dispara el evento.

Cuando hemos recogido las coordenadas x e y del mouse, restamos o sumamos los píxels de desplazamiento del sprite, para que quede centrado en el punto donde clicamos. Y seguidamente añadimos un nuevo sprite dinámicamente, de la misma forma que en el punto anterior, pero indicando la capa "bubblePlayer".

JQuery GAMES: mover todos los sprites de una misma clase css

Ahora por cada segundo que pasa se está creando una nueva burbuja en la parte superior del playground, y si clicamos sobre el playground se crean burbujas donde indicamos con el mouse.
Para hacer que las burbujas vayan cayendo tenemos que crear una nueva callback function que gestione lo siguiente:

"Por cada sprite de la clase css 'bubbleCPU' incrementa su posición y"

Esta callback function queda de la siguiente forma:

$.playground().registerCallback(function(){
$(".bubbleCPU").each(function(){
var posy = parseInt($(this).css("top"))+5;
$(this).css("top",""+posy+"px");
});
}, REFRESH_RATE);

Por cada sprite de la clase css 'bubbleCPU':
$(".bubbleCPU").each(function(){.........});

incrementa su posición y:
var posy = parseInt($(this).css("top"))+5;
$(this).css("top",""+posy+"px");

JQuery GAMES: detectar colisiones entre sprites

Para detectar las colisiones entre dos sprites, emplearemos la función "collision()" de gameQuery.
Esta función retorna la lista de elementos que han colisionado con el elemento que invoca la función:
Como parámetro podemos añadirle un filtro, identificador de elemento, clase css de elemento con el que queremos ver si ha colisionado:
Por ejemplo:
var collided = $("#elementoA").collision("#elementoB,.group");

Aquí vemos si un elemento con id "elementoA" ha colisionado con un elemento con id "elementoB", para ello comprobaremos que la variable collided <-- (recuerdo que es una lista), tiene más de 0 elementos:

if(collided.length > 0)

Bien, ahora vamos a seguir con nuestro ejemplo, veamos como detectamos que sprites de la clase "bubbleCPU" ha colisionado con un sprite de la clase "bubblePlayer":

Para ello modificamos la callback function que controla el movimiento de caída de las burbujas:

$.playground().registerCallback(function(){
$(".bubbleCPU").each(function(){
var posy = parseInt($(this).css("top"))+5;
$(this).css("top",""+posy+"px");
if(posy > PLAYGROUND_HEIGHT){
$(this).remove();
return;
}
var idBubbleCPU = $(this).attr('id');
var collided = 0;
$(".bubblePlayer").each(function(){
collided = $(this).collision("#"+idBubbleCPU+",.group");
if(collided.length > 0){
$(this).remove();
}
});

if(collided.length > 0){
$(this).remove();
}
});
}, REFRESH_RATE);


Lo primero que hacemos es crear una "colisión" con el suelo, es decir, que las burbujas desaparezcan al llegar al suelo:

if(posy > PLAYGROUND_HEIGHT){
$(this).remove();
return;
}

remove() elimina el sprite del playground y de todo el DOM, así ya no lo procesaremos más.

Seguidamente para crear la colisión entre objetos de dos clases css, tenemos que tener dos .each anidados, lo que queremos decir es:
"por cada objeto de tipo A mira si ha colisionado con algún elemento de tipo B"

$(".bubbleCPU").each(function(){
...
var idBubbleCPU = $(this).attr('id');
var collided = 0;
$(".bubblePlayer").each(function(){
collided = $(this).collision("#"+idBubbleCPU+",.group");
if(collided.length > 0){
$(this).remove();
}
});
if(collided.length > 0){
$(this).remove();
}
});

Como vemos, dentro del segundo each(), para ver si alguna burbuja creada por el usuario ha colisionado con la burbuja que estamos tratando en la iteracción actual, empleamos la idBubbleCPU, que hemos recogido antes de entrar en el .each() mediante:
var idBubbleCPU = $(this).attr('id');

Si la variable collided es mayor que cero, se ha producido una colisión, y debemos eliminar ambas burbujas!!

Con esto termina el tutorial 2!

Aquí tenéis el link al ejemplo funcionando!
Bubbles!!

viernes, 12 de agosto de 2011

JQuery CSS

Hola a todos!!
Vamos a cambiar el estilo css de un elemento cualquiera de una página html!!

Lo más importante es que el elemento en cuestión esté vinculado a una clase css, si no es así, la función css no tendrá efecto.

Por ejemplo vamos a cambiar el color del texto de un div y a ponerlo en negrita al clicar sobre él:
Para ello es necesario crear primero la clase que asignaremos al div:

<style type='text/css'>
.classA{
color: #01587B;
}
</style>

Para crear el div, como siempre, para que podamos seleccionar el div con facilidad le asignaremos una id, en este caso "clic", y le asignamos la class css "classA":

<div id="clic" class="classA">Click!</div>

Ahora desde cualquier función javascript, podemos cambiar el color del texto que contiene el div y ponerlo en negrita mediante la siguiente función:

$('#clic').css({'color':'#017B13', 'font-weight':'bold'});

Como vemos el parámetro de la función css, es un array de pares (atributo, valor), y la sintaxis es la siguiente:
{'atributocss1':'valor', 'atributocss2':'valor', 'atributocss3,'valor'}

Lo mejor de esta función Jquery es que es cross-browser, funciona en todos los navegadores, a diferencia de la función addClass, que en algunos navegadores no funciona.

$('#id').addClass("classB");

Eso es todo! un saludo!

miércoles, 10 de agosto de 2011

JQuery games

Buenas a todos!

Hace unos años cuando quería hacer juegos para que funcionaran en el navegador, la única opción atractiva tanto en rendimiento como en agilidad de desarrollo era Flash, pero requería que los usuarios se instalaran plugins <- Un palo enorme!
Y escribir aplicaciones con javascript implicaba pelearse horas para que funcionaran en todos los navegadores, entonces en 2006 apareció JQUERY! (gracias John Resig!!)
JQuery es un framework que funciona sobre javascript y que simplifica el trabajo sobre documentos html (manipulación del DOM, manejo de eventos, animaciones, AJAX, entre otros). La librería js que voy a mostraros es un plugin de JQuery especializado en el desarrollo de juegos, Gamequery.

Antes de empezar aquí tenéis los enlaces de las dos imágenes que empleo en el tutorial:

JQuery GAMES: incluir librería GameQuery

Para empezar tenemos que descargarnos de http://gamequery.onaluf.org/ el .js de la librería, y incluirlo en nuestro proyecto, en caso de que no queramos alojar directamente el .js en nuestro servidor, direccionaremos al que está en http://gamequery.onaluf.org/download/jquery.gamequery-0.5.1.js

Como este game engine es un plugin de JQuery, también tenemos que agregar el .js de Jquery:

<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.2.js'></script>

<script type='text/javascript' src="http://gamequery.onaluf.org/download/jquery.gamequery-0.5.0.js"></script>

Una vez incluidos los .js, ya podemos empezar a programar el juego!

JQuery GAMES: Playground

El "playground" es el espacio de la página donde se mostrará nuestro juego.
Mediante propiedades css, defino el ancho y el alto, que en el ejemplo será de 600x350:
No hace falta decir que esto va dentro del documento html!!

<div id="playground" style="position:relative; float:left; width: 600px; height: 350px; background: black;"></div>


JQuery GAMES: Main function

Todos los recursos (imágenes de fondo, sprites, sonidos, etc) y la declaración de las funciones del juego, serán cargadas al entrar en la página.
Para conseguir esto empleo la función de JQuery:

$(window).load(function(){...aquí la chicha!...});

Esta función se ejecuta cuando la página se ha cargado completamente, es decir, cuando se han cargado todos los frames, objetos e imágenes.
Y es dentro de esta función donde definiremos la Main Function del juego!
La estructura que voy a emplear para el ejemplo es la siguiente:

$(window).load(function(){

//DECLARACIÓN DE CONSTANTES
//DECLARACIÓN DE VARIABLES

//MAIN FUNCTION//
$(function(){
//CARGA DE IMÁGENES
//CONFIGURACION DEL PLAYGROUND
//INICIALIZACIÓN DE LAS CAPAS DEL PLAYGROUND
//DEFINICIÓN DE LAS CALLBACK FUNCTIONS
//INICIAR EL JUEGO : $.playground().startGame();
});
});

JQuery GAMES: Carga de imágenes y configuración del Playground

El playground se divide en capas, que en gameQuery se llaman "Groups".
En los groups es donde introduciremos los sprites.
Un group puede contener uno o más groups y estos a su vez pueden contener más groups.

De esta forma organizamos como se mostraran los sprites en la pantalla.

En este tutorial la estructura del playground será la siguiente:


En el apartado de declaración de constantes definimos el ancho y alto que tendrá el playground:
var PLAYGROUND_WIDTH = 600;
var PLAYGROUND_HEIGHT = 350;

Y justo debajo en el apartado de definición de variables definimos la variable que contendrá la imagen del background y la variable que contendrá el sprite del bot.

var background1;
var botAnimation = new Array();

¿Porqué un array para el sprite del bot?
La razón es porqué es probable que nuestro personaje tenga varios estados diferentes durante el juego, entonces almacenaremos las diferentes animaciones (sprites) en los distintos índices del array.
En este primer tutorial solamente emplearemos un sprite.

Una vez definidas las variables que almacenan las animaciones, las cargaremos al empezar la Main Function:

//CARGA DE IMÁGENES
background1 = new $.gameQuery.Animation({
imageURL: "background_stars.jpg"});

botAnimation["normal"] = new $.gameQuery.Animation({imageURL: "bot.png"});

Una vez cargadas las imágenes tenemos que configurar el escenario de Juego el Playground!!
Indicándole el alto y ancho que tendrá, para ello usaremos las constantes definidas anteriormente:

//CONFIGURACION DEL PLAYGROUND
$("#playground").playground({
height: PLAYGROUND_HEIGHT,
width: PLAYGROUND_WIDTH,
keyTracker: true});

Hecho esto, todo está preparado para que organicemos la escena en groups y añadamos cada sprite correspondiente al group que le toca:

//INICIALIZACION DE LAS CAPAS DEL PLAYGROUND
$.playground()
.addGroup("background", {width:PLAYGROUND_WIDTH, height:PLAYGROUND_HEIGHT})
.addSprite("background1", {animation: background1, width:PLAYGROUND_WIDTH, height:PLAYGROUND_HEIGHT})
.end()
.addGroup("botLayer", {width:PLAYGROUND_WIDTH, height:PLAYGROUND_HEIGHT}) .addGroup("bot",{posx: 270, posy: 130, width: 53, height: 62})
.addSprite("botNormal", {animation: botAnimation["normal"], posx: 0, posy: 0, width: 53, height: 62});

Al añadir un grupo indicamos el nombre del grupo y sus dimensiones:

addGroup("background", {width:PLAYGROUND_WIDTH, height:PLAYGROUND_HEIGHT})

Seguidamente o bien añadimos nuevos grupos dentro de este, o bien añadimos un sprite, en este caso se añade el sprite que corresponde con la imagen de background:

.addSprite("background1", {animation: background1, width:PLAYGROUND_WIDTH, height:PLAYGROUND_HEIGHT})

En el campo "animation" indicamos la variable que contiene la imagen que hemos cargado previamente.

La función .end() indica que hemos acabado de insertar grupos o sprites dentro de un grupo determinado, y podemos añadir seguidamente otro grupo al mismo nivel que el anterior.
Los grupos que añadimos seguidamente, se verán en la escena encima de los anteriores.
Por ejemplo:

groupA.groupA1.end.groupA2.end.end.groupB.groupB1

Una secuencia de este tipo mostrará primero lo que contenga el grupo B sobre lo que contenga el grupo A. Y del grupo A, primero se mostrará lo que contenga el grupo A2 sobre el grupo A1.

JQuery GAMES: Start Game!!

Con las imágenes cargadas y el playground configurado, ya podemos mostrar algo por pantalla!! wuahha!
Solamente tenemos que llamar dentro del Main Function a la función startGame(), de la siguiente forma:

$.playground().startGame();

Ahora solamente veríamos:
Falta un poco de movimiento no?

JQuery GAMES: Añadiendo movimiento a la escena, las Callback functions

Para controlar el gameplay, la lógica de juego, tenemos que procesar información y realizar operaciones antes de mostrar cada nuevo fotograma del juego.
Lo primero que tenemos que decidir es el REFRESH_RATE, es decir, los fotogramas por segundo. En nuestro caso emplearemos 30fps.

Así que añadimos una nueva constante:

var REFRESH_RATE = 30;

Una vez declarada, vamos a incluir al playground una Callback function, esta función es la que se ejecutará 30 veces por segundo. Y se incluirá en el apartado //CALLBACK FUNCTIONS de la Main Function.
Su sintaxis es la siguiente:

$.playground().registerCallback(function(){
.... código que se ejecutará 30 veces por segundo ....
}, REFRESH_RATE);

Ahora vamos a mover al bot!
Como quiero que vaya de un lado para otro, he añadido una variable en el apartado de declaración de variables, llamado direction, si es uno va hacia la izquierda, si es 0 hacia la derecha:

var direction = 1;

Ahora en la callback function añadimos el siguiente código:

$.playground().registerCallback(function(){
var pos = parseInt($("#bot").css("left"));
if(direction == 1){
var nextpos = pos-8;
if(nextpos>50){
$("#bot").css("left", ""+nextpos+"px");
}else{
direction = 0;
}
}else if(direction == 0){
var nextpos = pos+8;
if(nextpos<500){
$("#bot").css("left", ""+nextpos+"px");
}else{
direction = 1;
}
}
}, REFRESH_RATE);

Como podemos ver, el movimiento lo hacemos simplemente alterando la propiedad css left, del group "bot", que a su vez contiene el sprite "botNormal". Así pues desplazamos todo el grupo con su contenido.

Esto es todo, espero que os sea útil!

En este enlace podéis ver el ejemplo:

En el siguiente tutorial explicaré:
- Añadir sprites dinámicamente a un group.
- Capturar eventos del mouse con Jquery.
- Mover todos los sprites de una misma clase css.
- Detectar colisiones entre sprites.
- Eliminar sprites de un group.