martes, 10 de diciembre de 2013

CraftyJS: Animación del movimiento

IMPORTANTE: Los métodos de animación en CraftyJS cambiaron a partir de la versión 0.6, con lo que este artículo es sola válido a partir de dicha versión (y hasta nuevo cambio)  :-)

En el artículo anterior ya habíamos finalizado nuestro laberinto, sólo nos quedaba el detalle del personaje principal que era un cuadrito amarillo y que ahora substituiremos por un personaje animado.

Esto implica que tendremos una serie de frames (al que llamaremos reel) que crearán los efectos de movimiento a la derecha, izquierda ,arriba y abajo. Para ello cargaremos el mapa de sprites con el que ya habíamos trabajado en el artículo anterior y cogeremos el frame que queremos que muestre nuestro personaje al aparecer en pantalla (antes de moverse):

Crafty.sprite(32, 'assets/furniman.png', { ladron:        [00]  });




Ya podemos imaginar que con el mapa de sprites anterior crearmos cuatro reels que irán cambiando cuando cambie la dirección de nuestro personaje. Por lo que lo primero que tenemos que preguntarnos es ¿Cómo saber hacia que dirección se mueve nuestro prota?

NewDirection

De esto no hemos hablado, pero CraftyJS lanza una serie de eventos que podemos interceptar mediante el comando .bind.  Cuando una entidad que usa el componente Fourway (o multiway) cambia de dirección, lanza el evento global NewDirection que interceptaremos y al que le preguntaremos hacia qué lado vamos.
Este evento devuelve una clase con los atributos x e y cuyo signo puede ser positivo y negativo.

Todo esto lo definiremos en nuestro componente:

Crafty.c('Personaje', {
    init: function() {
       
   this.bind('NewDirection', function(direccion) {
  
         if (direccion.x > 0) {this.animate('derecha',    -1);} else
        if (direccion.x < 0) {this.animate('izquierda',  -1);} else
         if (direccion.y > 0) {this.animate('abajo',       -1);} else
        if (direccion.y < 0) {this.animate('arriba',      -1);} 
        else {this.pauseAnimation();}
      })
}); 

Vemos que este trozo de código es harto intuitivo.  Si vamos a la derecha, animamos la derecha, si vamos a la izquierda animamos la izquierda... y si no nos movemos, detenemos la animación. Si no hiciéramos esto nuestro muñeco seguiría moviéndose a pesar de estar parado.  O_o

Decir que animate lo que hace es crear un 'reel' (o serie de frames) para la animación de ese componente y definir el número de veces que imprimirá la secuencia. (Es fácil imaginar que -1 significa hasta el infinito y más allá). - Jolín, mira que me repatea la gente que dice esa gilipollez y ahora estoy yo aquí con lo mismo -).

El caso es que tenemos el reel, pero el reel no tiene nada...

Reel

Un reel básicamente lo que debería contener es una secuencia de frames que conforman la animación. (vamos, el concepto del zoótropo).

Sintaxis:

.reel( nombre, duración, posX, posY, númeroDeFrames)
  • La duración se expresa en milisegundos.
  • La posX y posY son la fila y columna que ocupa el primer frame (fila y columna relativa, medida en frames y no es píxeles.  (más datos aquí)
  • El número de frames es eso. Los cogerá de manera secuencial. (Si ponemos este parámetro en negativo iremos marcha atrás).
Así que ahora que crearemos la entidad, le indicaremos que es una animación de sprites, definiremos su imagen de inicio (definida anteriormente al cargar el mapa)  y daremos contenido a los reel.

    Crafty.e('2D, Canvas, Fourway, SpriteAnimation, Personaje, ladron)
     .attr({ x: 100, y: 10, w: 32, h: 32 })
     .fourway(4)
     .reel('arriba',     500, 0, 0, 2)
     .reel('abajo',      500202)
     .reel('derecha',  500, 2, 1, 2)
     .reel('izquierda', 500, 0, 1, 2);

Fijaos que le hemos dicho a Crafty que la entidad que estamos creando tiene el comportamiento SpriteAnimation y que su Sprite antes de moverse es el que habíamos definido para ladrón.

Y ya no necesitamos nada más... nuestro muñeco se moverá ahora con plena libertad...

Veamos como queda aquí.

El código es éste:




Y es más... veamos como quedaría todo esto si lo aplicamos a nuestro juego del laberinto aquí.
Además podemos bajarnos el código aquí o aquí



lunes, 25 de noviembre de 2013

CraftyJS: Sprites

Mmm... creo que el tutorial se está haciendo muy farragoso y al final no se entenderá nada, así que voy a tratar el contenido de este tema de manera independiente: El fantabuloso mundo de los

Sprites

Retomemos nuestro laberinto, pero ahora démosle color:


Como veis he dividido el mapa en cuadritos (que corresponden con el array que definíamos aquí). Como veis cada cuadrado tiene un dibujo que es una simple imagen (jpg, png...).  Pues bien, el dibujo en sí mismo, es lo que llamamos sprite. En la imagen sólo sale el escenario, pero es fácil deducir que nuestro personaje será también un sprite o una sucesión de ellos para crear el efecto de la animación.

Mapa de Sprites

Hemos dicho que los sprites son archivos gráficos que podemos cargar uno a uno o bien todos de golpe metidos en un archivo. Al contenido del archivo le llamaremos mapa de sprites y será algo de este tipo (tan grande como queramos):



Crafty.sprite

En CraftyJS la sintaxis para definir un sprite es esta:

Crafty.sprite( tamaño de la celdafichero, {mapa}, interespaciado)

Tamaño de la celda (opcional):

Medido en pixels, podemos darle sólo la anchura (x) o bien la anchura y la altura (x,y). Esto implicará que a la hora de definir el mapa nos referiremos a él en posición absoluta o relativa, ejemplo:

Como se indica, este parámetro es opcional. Si no definimos el tamaño, y quisiéramos referirnos al cofre en el ejemplo de arriba deberíamos acceder a la posición [64,64] (teniendo en cuenta que cada celda es de 32x32 pixels). Si definimos el tamaño (32,32) accederemos al cofre en la posición [2,2]. (La primera posición es el 0).

Por otro lado vemos que podemos especificar sólo la anchura (en cuyo caso se asumirá que la celda es cuadrada) o la anchura y la altura, lo que sugiere que aunque es menos habitual las celdas no tienen porque ser cuadradas.

Fichero: No tiene más historia. La ruta en la que se encuentra nuestro sprite o mapa de sprites.

Mapa:  Aquí está el meollo de la cuestión. El formato es:

 {nombre del mapa: [columna, fila, ancho, alto]}

Ejemplo para acceder al cofre sin haber definido tamaño de celda:
       Crafty.sprite('/dir/nombrefich.ext', {cofre: [64,64,32,32]});

Ejemplo para acceder al cofre habiendo definido tamaño de celda:
      Crafty.sprite(32,'/dir/nombrefich.ext', {cofre: [2,2]});

Ejemplo para acceder a todos los dibujos de Rajoy habiendo definido tamaño de celda:
 
     Crafty.sprite(32,'/dir/nombrefich.ext', {rajoyx8: [0,0,4,2]});      

 NOTA: Cuidadito aquí, aunque hemos cogido 8 casillas, estas se redimensionarán al tamaño de nuestra entidad que puede ser de 32x32 o cualquier otro tamaño.

Ejemplo para coger varios sprites a la vez:
     Crafty.sprite(32,'/dir/nombrefich.ext',{
            arriba:[0,0],
            abajo: [2,0],
            dcha:  [2,1],
            izda:   [0,1]
     });


Interespaciado: (opcional). Definimos interespaciado como el espacio que hay entre celda y celda, vamos, algo así como el margen. Podemos definir sólo las x o bien las x,y. Si no ponemos nada se asumirá que es 0. Si no ponemos las y se asumirá que coincide con las x.

Y oiga, ¿Todo esto como se usa?

Es muy sencillo. Al fin y al cabo, lo que arriba hemos denominado 'nombre del mapa'  no es más que un componente, así que, como tal, se usa.

    Crafty.e('2D, Canvas, Fourway, cofre')
      .attr({
              x: 100,
              y: 10,
              w: 100,
              h: 100
            });

Un ejemplito por el amor de dios...


Si queréis ver como queda, se podría ver aquí. Notad que aunque el tamaño de las celdas del mapa de sprites sea de 32x32, nuestro componente es de 100x100.

Si aterrizáis por primera ve por aquí quizá deseéis saber cómo ejecutar esto.

Retomando el juego...

Ahora vamos a trasladar todo esto a nuestro juego y vamos a seguir desde aquí.

Tomaremos el mapa de sprites que hay al principio de este documento y lo guardaremos en la carpeta /assets con el nombre de furniman.png. 

Ahora sólo debemos cargarlo y asignar cada sprite a un componente que será usado cuando creemos las entidades. ¿Y dónde lo haremos? ¿Recordáis la escena 'Loading' que espera a que esté todo cargado para iniciar el juego?

Crafty.scene('Loading', function(){

  Crafty.e('2D, DOM, Text')
    .text('Cargando...')
    .attr({ x: 110, y: 140 })
    .textFont({size:'13px'});

  Crafty.load(['assets/furniman.png'], function(){

   Crafty.sprite(32, 'assets/furniman.png', {
spr_muro:   [0, 2],
        spr_suelo:   [1, 2],
spr_tesoro: [2, 2]
    });
  Crafty.scene('Game');
  })
});

Ahora haremos que en el fichero de los componentes, éstos hereden los sprites que hemos definido, sin embargo si recordáis, teníamos entidades para los muros, pues nos interesaba que se detectara la colisión contra ellos, pero no teníamos nada para el suelo. Ahora el suelo deberá tener un dibujito y por tanto también tendrá que ser una entidad. 

Crafty.c('MuroMarron', {
   init: function( ) {
      this.requires('Actor, Pared, spr_muro');
  },
});

Crafty.c('Suelo', {
   init: function( ) {
      this.requires('Actor, spr_suelo');
  },
});

Crafty.c('Tesoro', {
  init: function() {
    this.requires('Actor, spr_tesoro')
  },
 
  /* ...  */

});

Ya sólo queda pintarlos en la escena del juego. Fijaos especialmente en el tesoro que cuando lo cojamos y desaparezca debajo tendrá que tener un suelo!!!

Crafty.scene('Game', function() {

// Colocamos cada cosa en su lugar
  for (var x = 0; x < mapa[0].length; x++) {
    for (var y = 0; y < mapa.length; y++) {
        
      if (mapa[y][x]==0) {  Crafty.e('Suelo').en(x,y);             }        
      if (mapa[y][x]==1) {  Crafty.e('MuroNegro').en(x,y);    }
      if (mapa[y][x]==2) {  Crafty.e('MuroMarron').en(x,y);  }

      if (mapa[y][x]==3) {
         Crafty.e('Suelo').en(x,y);
         Crafty.e('Tesoro').en(x,y);
       }
    }
  }

//Colocamos el personaje principal en el mundo.
 Crafty.e('Politico').en(1, 8);

});

Y con esto ya lo tenemos todo!

Si queréis ver el resultado pinchad aquí.
Si queréis bajaros los fuentes pinchad aquí o aquí

miércoles, 20 de noviembre de 2013

Apuntes de Fonaments físics de la informàtica (UOC)

Actualizado Enero 2017

Sí, lo sé.  Mis apuntes están de puta madre. Sin embargo esta vez voy a compartir unos que empiezan muy bien, pero que flojean en el último tema: 'òptica i fotónica'.  La verdad es que iba tan apurado de tiempo que tuve que dedicarme al escaneo manual con boli y libreta de apuntes, y sinceramente... eso paso de colgarlo.


El caso es que os comparto los documentos de 'Fonaments físics de la informàtica' (05.611del 'Grau d'Enginyeria Informàtica' de la UOC (Universitat Oberta de Catalunya), por si queréis aprovecharlos. De hecho, no estaría mal que si alguien los completa, me los comparta aquí para que pueda colgarlos. Supongo que lo agradeceríamos todos. La verdad es que bastante gente se descarga mis apuntes, lo cual me llena de una hondo orgullo y satisfacción y ruptura de cadera.




Además podéis descargaros PAC's de la asignatura aquí

También exámenes resueltos aquí

Por cierto, si queréis colaborar en tener un buen repositorio para la asignatura, mandadme vuestras PAC's y Exámenes corregidos y los iré incluyendo en beneficio de los futuros estudiantes.

Debéis mandar un correo a   furnimanQUITAESTO@terra.com  (evidentemente quitando el QUITAESTO) :-)

jueves, 7 de noviembre de 2013

CraftyJS - Escenas

En este punto, podríamos decir que ya hemos programado todo nuestro juego. Sin embargo es un poco triste, que después de sufrir financiando nuestro partido, una vez lo consigamos no salga ni un triste mensaje.

Una solución sería poner un mensaje felicitándonos sobreimpresionada. Esto ya lo sabemos hacer, lo vimos aquí, pero sería más elegante tener una pantalla nueva.

Los juegos se componen de menús, pantallas y créditos. Incluso hay juegos que las pantallas difieren mucho unas de otras (tanto que pueden ser un juego nuevo). Es cada uno de estos casos estamos hablando de:

Escenas

Así pues, vamos a dividir lo que teníamos hecho en tres escenas:
  • Una inicial de carga por si nuestro juego tarda mucho en cargarse y que ya os anuncio que ni la vamos a ver...   :-)
  • La propia pantalla del juego
  • La pantalla de fin de juego, albricias y felicitaciones.
Estas escenas las crearemos en un fichero nuevo llamado scenes.js que NO deberemos olvidar incluir en nuestro index.html:

<!DOCTYPE html>
<html>
<head>
    <script src="lib/crafty.js"></script>
    <script src="src/game.js"></script>

    <script src="src/componentes.js"></script>

    <script src="src/scenes.js"></script>
    <script>
       window.addEventListener('load', Game.start);
    </script>
</head>
<body>
</body>
</html>

Pantalla Final

Yo creo que con esto queda la escena autoexplicada:

Crafty.scene('Victory', function() {

//Ponemos el texto
  Crafty.e('2D, Canvas, Text')
    .attr({ x: 10, y: 150 })
    .textFont({size:'13px'})
    .text('Felicidades! Has conseguido financiar tu partido!');
  this.restart_game = this.bind('KeyDown', function() {
// Llamamos a la escena del juego
      Crafty.scene('Game');
  });
}, function() {
    this.unbind('KeyDown');
});

Como se puede intuir esto pone el mensaje y espera a que se pulse una tecla para mandarnos a la escena 'Game'.

----------------------------

Pantalla 'Game'

// Escena principal 'Game':  Crea las entidades del mapa y del político.

Crafty.scene('Game', function() {

// Colocamos cada cosa en su lugar
  for (var x = 0; x < mapa[0].length; x++) {
    for (var y = 0; y < mapa.length; y++) {
            
      if (mapa[y][x]==1) {
          Crafty.e('MuroNegro').en(x,y);
      }
      
      if (mapa[y][x]==2) {
         Crafty.e('MuroMarron').en(x,y);
      }

      if (mapa[y][x]==3) {
         Crafty.e('Tesoro').en(x,y);
       
      }
    }
  }

//Colocamos el personaje principal en el mundo.
    Crafty.e('Politico').en(1, 8);
});

Como se ve, aquí dibujamos el mapa y plantamos el personaje en el mismo. No tenemos nada más que hacer ya que todos los comportamientos están definidos en las entidades.

----------------------------

Pantalla Loading...

Crafty.scene('Loading', function(){
  Crafty.e('2D, DOM, Text')
    .text('Cargando...')
    .attr({ x: 110, y: 140 })
    .textFont({size:'13px'})

  Crafty.scene('Game');
});

Y esta es la pantalla de carga que no veremos nunca...  :-)

___________________________________________________________________

Victoria!!!!

Hay un tema que queda pendiente. Y es cómo llamamos a la escena de victoria. 

Aquí vimos como hacer que el tesoro se destruyera al pasar por encima de él. Lo que haremos ahora será preguntar si queda algún tesoro y si no queda ninguno llamaremos a la escena de victoria. Por lo tanto modificaremos el componente Tesoro en el fichero componentes.js.

Crafty.c('Tesoro', {
  init: function() {
    this.requires('Actor, Color')
        .color('yellow');
  },
    
  recogido: function() {
     this.destroy();

     // Si no queda ningún tesoro ya hemos terminado.
     if (!Crafty('Tesoro').length) {  
Crafty.scene('Victory');
     }  
  } 
});

__________________________________________________

Código completo

Sólo queda explicar el fichero inicial game.js.  Lo único que hace es definir el tamaño del canvas y llamar a la escena 'Loading'. Hago en él una cosa rara y es sacar fuera la tabla del mapa como global, para que se a accesible también desde el fichero de escenas, ya que la escena 'Game' la usa. Ya se que no es muy ortodoxo, pero es lo que tiene saltomatacaballear.




Ah se me olvidaba...  si queréis ver como queda....  PINCHAD AQUÍ!!!!



lunes, 30 de septiembre de 2013

Cambiar la versión de .NET Framework de un proyecto existente (VS 2010)

Esto me ha pasado por ejemplo instalando Crystal Reports para Visual Studio:

Empecé un proyecto en Framework 4 Client Profile y al usar el componente de Crystal me daba un error puesto que éste debe correr en la versión completa.

Para cambiar la versión del .NET Framework debemos:

  • 1) Ir al Explorador de soluciones (CTRL + ALT + L) y pulsar con el botón derecho del ratón sobre el nombre del proyecto seleccionando la opción de Propiedades.

  • 2) En la opción de compilar, seleccionaremos Opciones de compilación Avanzadas

  • 3) Seleccionamos la versión del Framework deseada e incluso nos descargamos una nueva.

  • Aceptamos y cruzamos los dedos para que no surjan incompatibilidades.
NOTA:  Especialmente si tenemos imágenes como recurso o usamos el archivo de configuración del proyecto, pueden darse incompatibilidades. Microsoft da aquí una serie de indicaciones, pero no me preguntéis porque no me he tenido que pelear con ello.


martes, 6 de agosto de 2013

Apuntes de Iniciació a les matemàtiques per a l'enginyeria (UOC)

Siguiendo la tónica de compartir mis apuntes por si a alguien le facilita la vida las horas que he invetido, comparto esta vez los apuntes  (en lengua catalana) de la asignatura Iniciació a les matemàtiques per a l'enginyeria (05.614) que se imparte como asignatura optativa en diversos grados de la UOC (Universitat Oberta de Catalunya), así como en su @teneu universitari.

Espero que le valgan a alguien!   :-)

Descargar en formato PDF
Descargar en formato MSWord

Si optáis por la descarga en formato Word, pensad que se abrirá una sesión del Google Docs, que entre otras cosas es incompatible con las fórmulas de Word y no se verán. Se soluciona descargando el archivo.

Si no usáis MS Office, descargaros el PDF o tendréis el mismo problema.

domingo, 4 de agosto de 2013

CraftyJS: Texto

Para escribir textos con Crafty usamos el componente text.

Una entidad con ese componente será sólo texto, eso significa que no podemos poner texto en una imagen, debemos tener dos entidades, una para cada cosa. Sin embargo podemos usar un par de trucos como la propiedad z-index del componente 2D que permite definir qué esta encima y qué está debajo o el método .attach( ) también del componente 2D que permitirá pegar ambas entidades a fin de moverlas o rotarlas conjuntamente.

Por otro lado, trabajando en DOM (que no en Canvas), podremos usar la propiedades .css para definir elementos como la alineación del texto, aunque se ignorará la fuente y el color ya que lo controla el componente Text.

Método .text

Tiene un único parámetro que bien puede ser una cadena de texto o una llamada a una función que devuelva el texto. Veamos el ejemplo:

    Crafty.e('2D, Canvas, Text')
      .attr({ x: 20, y: 50 })
      .text("Odio los hola mundos");

    Crafty.e('2D, Canvas, Text')
      .attr({ x: 20, y: 100 })
      .text(function () { return "Mi posición es " + this._x +"," + this._y });

Método .textcolor

Dos parámetros, el primero de ellos especifica el color y el segundo la opacidad que es un valor que va de 0 a 1, siendo 0 transparente y 1 totalmente opaco.

    Crafty.e('2D, Canvas, Text')
      .attr({ x: 20, y: 150 })
      .text("Color #FF0000")
      .textColor('#FF0000');

    Crafty.e('2D, Canvas, Text')
      .attr({ x: 20, y: 200 })
      .text("Color #FF0000 opacidad 0.6")
      .textColor('#FF0000', 0.6);

Método .textfont

Define la fuente, el ejemplo es autoexplicativo:

    Crafty.e('2D, Canvas, Text')
      .attr({ x: 20, y: 250 })
      .text("20 px, negrita, cursiva, Courier New")
      .textFont({ size: '20px', weight: 'bold', type: 'italic', family: 'Courier New'});

NOTA: Por defecto CraftyJS usa un tamaño de 10 px y la fuente 'sans-serif'.

Para muestra un botón:

Vamos a recoger todo esto en un único fuente:

Y veamos como queda:



Para ejecutarlo referiros al primer capítulo de esta serie donde se explica que se necesita para correr CraftyJS.

Nada más por hoy.

miércoles, 24 de julio de 2013

CraftyJS: Eventos

Hasta ahora hemos ido desarrollando un sencillo juego de laberintos apto para políticos cuya última versión se encuentra aquí.

Quizá sea el momento de dotar de sentido al juego poniendo un objetivo. Y en fin, creo que nuestro político podría hacer lo que mejor sabe hacer que es financiar su partido.

Para ello crearemos un nuevo componente llamado Tesoro que no difiere en nada de los muros que hemos creado hasta ahora salvo en dos aspectos:
  1. No nos interesa que nuestro político se detenga al colisionar con el tesoro, con lo que eliminaremos el componente 'Pared' que usábamos para detectar la colisión y,
  2. Le dotaremos de un comportamiento especial al que llamaremos 'recogido' y que lo que hará es destruir el tesoro. Este comportamiento (evento) lo dispararemos cuando detectemos que nuestro político colisiona con el tesoro.
Veamos el código:

Crafty.c('Tesoro', {
  init: function() {
    this.requires('Actor, Color')
      .color('yellow');
  },

  recogido: function() {
    this.destroy();
  }
});

Para colocarlos usaremos nuestra tabla de mapa y pondremos un nuevo objeto tipo 3.

  var mapa = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                      [1, 3, 2, 2, 3, 2, 3, 2, 2, 1],
                      [1, 0, 0, 2, 0, 2, 0, 0, 0, 1],
                      [1, 2, 0, 2, 0, 2, 2, 2, 0, 1],
                      [1, 2, 0, 0, 0, 0, 0, 2, 0, 1],
                      [1, 2, 2, 2, 0, 2, 0, 2, 0, 1],
                      [1, 0, 0, 0, 0, 2, 0, 2, 0, 1],
                      [1, 0, 2, 2, 0, 2, 0, 2, 0, 1],
                      [1, 0, 2, 2, 3, 2, 0 ,0 ,3, 1],
                      [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];

Y dibujaremos los tesoros en la misma parte que creábamos los muros y de la misma manera:

      if (mapa[y][x]==3) {
         Crafty.e('Tesoro').en(x,y);
      }

Eventos


 Nos faltaría ver que hacemos con el político:

Lo que haremos es preguntar si colisiona con un Tesoro y lanzar un procedimiento que llame al evento 'recogido' que habíamos definido en el tesoro:

// Esta componente será nuestro jugador, añadimos código para la colisión.
Crafty.c('Politico', {
  init: function() {
    this.requires('Actor, Fourway, Color, Collision')
      .fourway(4)
      .color('rgb(20, 75, 40)')
      .onHit('Pared', this.detenerMov)
      .onHit('Tesoro', this.recogerTesoro);
  },

  // detiene el movimiento
  detenerMov: function() {
            ...
    },
 
  recogerTesoro: function(datos) {

    datos[0].obj.recogido();      // Disparamos el evento recogido en el tesoro
  }
});

Y con esto ya está.   Os pongo el código completo.   Recordad que para que funcione debéis tener en cuenta todo esto.

Respecto a si funciona, pues podemos verlo aquí

martes, 23 de julio de 2013

CraftyJS: Colisiones

Tratar las colisiones en Crafty es muy sencillo, básicamente tenemos que reconocer contra qué nos las pegamos y cómo reaccionamos.

Para ello recuperaremos el laberinto apto para políticos.

Contra qué nos la pegamos

Recordemos que teníamos dos tipos de muro. Definiremos que son de tipo 'Pared'.
Crafty.c('MuroNegro', {
init: function( ) {
this.requires('Actor, Color, Pared');
this.color('black');
},
});
Crafty.c('MuroMarron', {
init: function( ) {
this.requires('Actor, Color, Pared');
this.color('brown');
},
});
Como veis, no hemos definido anteriormente 'Pared' en ningún lado. Podemos poner el palabro que queramos. Lo que haremos con posterioridad es preguntar si hemos colisionado con algo de tipo 'Pared'. De eso se deduce que si quisiéramos que el personaje de nuestro videojuego reaccionara de manera distinta en cada tipo de muro, deberíamos definir un palabro para cada tipo de muro.

Como detectamos la colisión

Realmente en nuestro laberinto no habíamos creado todavía al protagonista del videojuego: nuestro político. Es por ello que crearemos el componente Político dotándole de movilidad cómo hemos visto aquí. También le incorporaremos la lógica de la colisión:
Crafty.c('Politico', {
  init: function() {
    this.requires('Actor, Fourway, Color, Collision')
      .fourway(4)
      .color('rgb(20, 75, 40)')
      .onHit('Pared', this.detenerMov);
  },

  detenerMov: function() {
    if (this._movement) {
      this.x -= this._movement.x;
      this.y -= this._movement.y;
    }
  }
});

 Como vemos importamos el comportamiento Collision. Sin embargo lo más interesante es la llamada al método .onHit. Este método tiene tres parámetros:

El primer parámetro es el tipo de objecto contra el que preguntamos si chocamos. Vamos, lo que en la primera parte de este artículo llamábamos el palabro.

La segunda parte es el nombre de la función a la que llamaremos en el caso de colisión.

La tercera parte, que no está definida en el ejemplo, llamaría a una función que se ejecutaría en caso de que la colisión NO se produjera.

 Dotando de vida a nuestro político

No tiene más, lo tenemos perfectamente definido en nuestro fichero de componentes, por lo tanto lo llamamos:

Crafty.e('Politico').en(1, 8);

El código



¿Pero funciona?

No se, probadlo aquí

Prestashop: Combinaciones

Podemos tener el caso de que en nuestra tienda queramos vender elementos que aún siendo el mismo, puedan tener diversas configuraciones. Pondremos el caso de un WC. A pesar de que sea el mismo modelo,  puede tener  evacuación vertical u horizontal, y alimentación lateral o inferior. Además, podemos tener distintos colores para la tapa. Todo esto puede llevar una variación en el precio según configuración o incluso en la referencia. Para todo esto existen en Prestashop las combinaciones.


Atributos y valores

En el caso que hemos ejemplificado los atributos serían evacuación con sus valores vertical / horizontal, alimentación con sus valores lateral / inferior y colores con los valores que sean. Veamos dónde definir esto:

Desde el menú principal de nuestro BackOffice accedemos a las opciones Catálogo -> Atributos y valores.



Con el botón de Añadir una nueva característica, accederemos al mantenimiento y crearemos las características evacuación y alimentación. Lo verdaderamente importante aquí es seleccionar Botón de Opción en el campo Tipo de Atributo. (Los colores los veremos luego)


Al final nos quedará algo como la imagen de debajo:


Ahora crearemos los valores para cada característica. Es importante remarcar que hay que crear todos los posibles. Si tenemos una característica que puede tomar quince valores hay que definir los quince, incluso cuando nuestro artículo sólo pueda adaptar un par de ellas. Ya habrán otros artículos que las necesitarán.

Para ello pulsamos el botón Añadir un nuevo valor de característica que veis en la captura de arriba.

La pantalla que se nos ofrece es muy simple, sólo hay que seleccionar en el campo desplegable de característica el atributo al que queramos dar valor e informarlo. Seguidamente pulsamos el botón Guardar y añadir otro valor y repetimos la operación. Cuando ya hayamos definido todos nuestros valores para todos los atributos pulsamos Guardar.


Al final nos tiene que quedar algo como la captura bajo estas líneas. Fijaos que disponéis de una serie de botones para eliminar y/o editar las características y valores.


Incluir los atributos en los artículos

Esta parte se hace desde el mismo mantenimiento de los artículos, en la pestaña combinaciones. Por lo tanto creamos un artículo o modificamos uno creado y accedemos a esta pestaña:


Como vemos en la captura de arriba, lo que tenemos que hacer es escoger el par Atributo / Valor que corresponda a nuestro artículo y pulsar Añadir. Con esto ya estaríamos, a no ser que nuestro atributo tenga ciertas peculiaridades que transformen al artículo y que pasamos a ver:


La primera parte tiene a ver con las Referencias, si nuestra combinación comporta un código distinto se lo indicamos y Prestashop lo sabrá gestionar perfectamente (incluso cambiando la referencia en el momento de seleccionar la combinación si la mostramos con el artículo).

Lo mismo sucede con el resto de campos: Podemos definir un nuevo precio de mayorista (coste) en el artículo y un incremento / decremento en los precios y pesos. Eso hará por ejemplo, que cuando en nuestra tienda cambiemos de combinación también lo hará el precio.

Por último podremos ver todas las imágenes que tenemos cargadas nuestro artículo. Prestashop nos permitirá seleccionar aquellas que queramos que se muestren en el momento que alguien escoja nuestra combinación en particular.

Para gustos los colores

Al hablar de los atributos obviamos los colores. Si creamos un atributo de tipo color, al definir sus valores podremos seleccionar el color de una paleta, darle el código RGB o incluso añadir una imagen para texturas.


 Resultado Final

Adjunto una captura de como quedaría nuestro artículo. En él podemos escoger la evacuación, la alimentación y el color.  Fijaos que el color incluye una textura.





jueves, 27 de junio de 2013

CraftyJS: Movimiento

Componente Fourway


Fijaos, pillamos la entidad definida aquí le añadimos el componente Fourway y definimos su velocidad.

Crafty.e('2D, Canvas, Fourway, Color')
    .attr({
       x: 100,
       y: 10,
      w: 100,
       h: 100,
     })
    .fourway(4)
    .color('yellow');

Y ya funciona. Nos movemos con W+A+S+D o bien con los cursores.

Lo podemos ver funcionando aquí.

No obstante os adjunto el código completo en el que definimos también el canvas:


Recordad que para que funcione debéis tener en cuenta esto.

Componente Multiway

Por supuesto podemos movernos con cualquier tecla y en cualquier dirección.

Crafty.e('2D, Canvas, Multiway, Color')
    .attr({
       x: 100,
       y: 10,
       w: 100,
       h: 100,
    })
   .multiway({x:3,y:1.5}, {W: -90, S: 90, D: 0, A: 180})
   .color('yellow');

Fijaos que la primera parte de la instrucció define la velocidad de movimiento en la dirección de las x y la velocidad en dirección de las y. Vemos que es lo mismo que en .fourway sólo que definimos una velocidad diferente para cada eje. Esto no es propio de .multiway, también podríamos haber definido de esta manera .fourway.
En la segunda parte definimos las teclas y la dirección en la que nos moveremos. Sí, lo sé. Las direcciones son un poco raras... pero quizá este gráfico nos ayude a entenderlas:



Por otra parte podemos definir cualquier tecla que queramos según la siguiente tabla:



BACKSPACE: 8 E: 69 NUMPAD_9: 105
TAB: 9 F: 70 MULTIPLY: 106
ENTER: 13 G: 71 ADD: 107
PAUSE: 19 H: 72 SUBSTRACT: 109
CAPS: 20 I: 73 DECIMAL: 110
ESC: 27 J: 74 DIVIDE: 111
SPACE: 32 K: 75 F1: 112
PAGE_UP: 33 L: 76 F2: 113
PAGE_DOWN: 34 M: 77 F3: 114
END: 35 N: 78 F4: 115
HOME: 36 O: 79 F5: 116
LEFT_ARROW: 37 P: 80 F6: 117
UP_ARROW: 38 Q: 81 F7: 118
RIGHT_ARROW: 39 R: 82 F8: 119
DOWN_ARROW: 40 S: 83 F9: 120
INSERT: 45 T: 84 F10: 121
DELETE: 46 U: 85 F11: 122
0: 48 V: 86 F12: 123
1: 49W: 87 SHIFT: 16
2: 50X: 88 CTRL: 17
3: 51Y: 89 ALT: 18
4: 52Z: 90 PLUS: 187
5: 53NUMPAD_0: 96 COMMA: 188
6: 54NUMPAD_1: 97 MINUS: 189
7: 55NUMPAD_2: 98 PERIOD: 190
8: 56NUMPAD_3: 99 PULT_UP: 29460
9: 57NUMPAD_4: 100 PULT_DOWN: 29461
A: 65 NUMPAD_5: 101 PULT_LEFT: 4
B: 66 NUMPAD_6: 102 PULT_RIGHT': 5
C: 67 NUMPAD_7: 103
D: 68 NUMPAD_8: 104


Componente Twoway

Este componente usa las teclas A+W+D o los correspondientes cursores.
El código debería ser algo así:

Crafty.e('2D, Canvas, Twoway, Color')
   .attr({
       x: 100,
       y: 10,
      w: 100,
      h: 100,
   })
   .twoway(4,10)
   .gravity("platform")
   .color('yellow');

El movimiento de este componente sera de velocidad 4 en la horizontal. Sin embargo al pulsar la tecla arriba, saltará a velocidad 10 hasta el infinito a no ser que declaremos la fuerza de gravedad. Una vez la fuerza de gravedad venza al salto, nuestro componente caerá hasta el infinito a menos que definamos un suelo, cosa que no sabemos hacer.
Y este capítulo llega hasta aquí. Espero que os haya sorprendido lo fácil que es controlar el movimiento de un componente en CraftyJS.
Nos vemos.

miércoles, 12 de junio de 2013

Prestashop: Añadir un campo nuevo en el artículo

Recientemente me he encontrado con que tenía que definir un código adicional en los artículos de Prestashop. Inmediatamente me vino a la cabeza que podía usar el código UPC ya que sólo lo usan Canadienses y Japoneses y mi tienda de momento, no iba a ir dirigida para ellos.

El problema con el que me encontré es que este código es sólo numérico, de una longitud determinada y encima se valida.

Así que me decidí a tunearlo.

Modificación del diccionario

Este campo se encuentra en tabla 'ps_product' y es un varchar de 12 posiciones. Si no nos vale, deberemos acceder a la base de datos, con el phpmyadmin por ejemplo, y modificar la estructura del campo.

En mi caso, el tipo del dato me valía, pero necesitaba que fuera de 14 posiciones, por lo que ejecuté la siguiente petición:

ALTER TABLE `pr_product` CHANGE `upc` `upc` VARCHAR(14) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL

Modificación del programa

Ahora sólo quedaba quitar la restricción por software al formato del campo.  Esta restricción se encuentra en el fichero    .\classes\product.php

Lo único que tenemos que hacer es ir a la línea 260 y cambiar 'isUPC' por 'isString' y en mi caso, que recordad que también cambiaba la longitud el número 12 por 14.

Este programa hace tiempo que no cambia y la línea sigue siendo la 260 en Prestashop 1.5.4., pero si algún día cambiara, lo que podéis hacer es buscar el texto:   'isUpc', 'size' => 12    Así, con comillas y todo.


Añadir campo nuevo

Esta solución que he aplicado para un caso muy relacionado con la funcionalidad original del campo, puede con un poquito de imaginación evitar el engorroso proceso de añadir un campo nuevo a la ficha del artículo de Prestashop.

Y nada más. Espero que a alguien le sirva.   :-)

E

lunes, 10 de junio de 2013

CraftJS: Componentes

*NOTA PREVIA:  En este capítulo se usa el término herencia muy a la ligera. Se ruega a los puristas del léxico que miren sólo los dibujitos y no lean el texto.

*NOTA PREVIA 2:  He observado que la plataforma que he escogido para alojar el código: Github, funciona de pena con el Chrome. A pesar de que según las estadísticas de visita a mi blog, la mayoría usáis Chrome, os recomiendo que de momento y hasta que alguien lo solucione, uséis el Explorer para verlo bien, o que pulséis sobre el enlace view rar que encontraréis bajo el código. 

En el capítulo anterior, creamos una serie de entidades que eran muy parecidas, de hecho sólo cambiaba el color:

Crafty.e('2D, Canvas, Color')
  .attr({
     x: x * Game.anchoCelda,
     y: y * Game.altoCelda,
     w: Game.anchoCelda,
     h: Game.altoCelda,
  })
  .color('black');
Crafty.e('2D, Canvas, Color')
  .attr({
     x: x * Game.anchoCelda,
     y: y * Game.altoCelda,
     w: Game.anchoCelda,
     h: Game.altoCelda,
  })
  .color('brown');

Componentes

Vamos a sacar factor común (como en mates) de estas dos entidades y las meteremos dentro de un componente llamado rejilla que define sus propiedades y/o comportamientos.

Crafty.c('Rejilla'', {
   init: function( ) {
      this.attr({
         x: x * Game.anchoCelda,
         y: y * Game.altoCelda,
         w: Game.anchoCelda,
         h: Game.altoCelda
     })
   }
 }) ;

Con esto podemos crear otros componentes que 'hereden' las propiedades de 'Rejilla':

Crafty.c('MuroNegro', {
   init: function( ) {
      this.requires('2D, Canvas, Rejilla, Color');
      this.color('black');
  },
});
Crafty.c('MuroMarron', {
   init: function( ) {
      this.requires('2D, Canvas, Rejilla, Color');
      this.color('brown');
  },
});

Es más... podemos volver a sacar factor común (lo llamaremos Actor):

Crafty.c('Actor', {
   init: function( ) {
      this.requires('2D, Canvas, Rejilla, Color');
    },
});

Crafty.c('MuroNegro', {
   init: function( ) {
      this.requires('Actor, Color');
      this.color('black');
  },
});
Crafty.c('MuroMarron', {
   init: function( ) {
      this.requires('Actor, Color');
      this.color('brown');
  },
});

Con lo que ya podemos crear nuestra entidad 'heredando' del componente Muro:

Crafty.e('MuroNegro');

Cada cosa en su fichero

Ya tenemos el código, sólo nos queda meter los componentes en un fichero llamado componentes.js, guardarlo en nuestra carpeta de fuentes (/src) y llamarlo en nuestro index.html.
Esto acarrea un problema y es que perdemos las referencias a las variables x e y que usa el componente 'Rejilla', así que debemos modificar el componente para que las pueda recibir como parámetro:

Crafty.c('Rejilla'', {
   init: function( ) {
      this.attr({
         w: Game.anchoCelda,
         h: Game.altoCelda
     })
   },
   en: function(x, y) {
      this.attr({ x: x * Game.anchoCelda, y: y * Game.altoCelda });
      return this;
   }
 });

Y lo llamaremos así:

Crafty.e('MuroNegro').en(x,y);

Veamos el código completo cada cosa en su sitio:

Sobra decir que el resultado que obtendremos es el mismo que el capítulo anterior.

Algunas consideraciones sobre los componentes

  • Las propiedades o métodos que empiezan con guión bajo se consideran privadas.
  • El método llamado init se ejecutará en el momento que añadamos el componente a la entidad.
  • Un método con el mismo nombre del componente se considerará un constructor y se usa para pasar datos.
  • A pesar de que hemos dicho que los métodos con guión bajo se consideran privados, no es más que una convención. Esto será así mientras el método sea un valor, pero si trabajamos con objetos o arrays, JavaScript tratará el objeto por referencia y en consecuencia se modificará para todos los componentes en los que se haya heredado.