martes, 3 de abril de 2012

Journey, sin palabras ...


jueves, 29 de marzo de 2012

Un editor html WISIWING con JQuery.

Aquí dejo el código de una pequeña prueba para hacer un editor de html (ver código fuente del enlace). Aunque para mis necesidades no es necesario que fuese WISIWING (lo que ves es lo que tienes) si quería ver cómo podría hacer algo que diese una imagen real del resultado final.
Ahora mismo con JQuery (simplifica el trabajo de javascript), con los nuevos navegadores (esto no funcionara en cualquiera si no estamos actualizados), lo tenemos más fácil aunque tenemos que pasar por el aro de trabajar con javascript. Manipulando el dom de la página podemos agregar y eliminar elementos, podemos introducir contenedores (div, párrafos, tablas, …), podemos modificar las propiedades css de los elementos y podemos jugar con sus atributos mientras vemos el resultado directamente en pantalla. Lo mejor, es que el código apenas llega a las 100 líneas e introducir el resto de propiedades y atributos para completar el editor es tremendamente sencillo. 
El enlace al editor:
Una imagen:

Para introducir los elementos en un contenedor, seleccionaremos el elemento y pulsaremos dentro del contenedor. Si, por ejemplo, queremos introducir un botón como el de la imagen, pondremos un elemento input (por defecto se incluye de tipo texto), pulsaremos sobre él, e iremos a los atributos y cambiaremos a tipo "button". Despues en el value podemos poner el texto a mostrar.

sábado, 31 de diciembre de 2011

Colisiones y sonido

Ver artículo anterior de esta serie
Puff, poco tiempo para estas cosas y con el peque ya dándole a la psp y a la ps3. Llego tarde.
Dejo aquí un ejemplillo sobre cómo montar las colisiones (muy burdamente pero suficientes si se ajustasen mejor los rectángulos) y sobre cómo incluir los sonidos. Algo curioso es que si un sonido esta en uso hay que esperar a que termine antes de que se puede volver a utilizar. Para resolver esto hay que tener en el código distintas variables apuntando al mismo sonido. En el caso de las flechas tengo dos variables así que si uno esta sonando se utiliza el otro. Si se dispara muy rápido serian necesarias más variables.
Para probar esto lo mejor es ir a la segunda pantalla y dedicarse a cazar al pájaro. Una vez que se le ha dado con una flecha, cambia el estado del sprite para que este caía hasta donde corresponda en función de la pantalla, al llegar al suelo se convierte en "premio" y cuando el soldado colisiona con el premio se lo lleva.
El ejemplo:

jueves, 3 de noviembre de 2011

Un arco sin caza que cazar :(

Ver el artículo anterior de esta serie.
El ejemplo:

Esto me ha llevado un rato. De nuevo si lo hubiese pensado antes no me habría liado con la parte de apuntar con el arco. ¡Sir Arthur siempre ha tirado los cuchillos “pa lante”!.
Ahora podemos disparar pero nada de tiros parabólicos, hazte a la idea de que la flecha cae después de que sale de la pantalla o de que tienes una fuerza increíble.
Aunque he revisado el código se me ha guarreado un poco. La trayectoria de las flechas es, cómo no, y=mx+b, donde m es la pendiente de la recta, m=tangente del ángulo, y b es el punto de corte con el eje y.
En función de la escala del prota (si te vas a la tercera pantalla es más pequeño) y en función del ancho del sprite o de hacia dónde apunta hay que echar una serie de cálculos en los que no me he parado demasiado. He probado utilizando la intuición y me veo, cuando intente tratar las colisiones con objetos (siguiente paso), revisando todo el código y parándome a pensar, lápiz en mano, las trayectorias y demás. El hecho de que el eje “y” esté invertido en el canvas y de que yo no tenga muy claro hacia dónde van los ángulos complica las cosas y más si añadimos que he modificado el mapa de los sprites para que sólo aparezcan los que miran hacia la izquierda y debo, entonces, girarlos para tratar el caso de los que miran a la derecha:


Por cierto, las flechas van por el canvas intermedio y, por ejemplo, en el dibujo de arriba, si no pongo algo en el primer plano van por delante del desfiladero, ¡un efecto a lo Michael Escher!

miércoles, 26 de octubre de 2011

Subir escaleras molara pero disparar un arco muchísimo más.

Ver el artículo siguiente de esta serie.
Ver el artículo anterior de esta serie.
Primera prueba para el disparo con el arco (Sí ya sé que estas son horas para darle al Batman Arkham City pero el deber es el deber y, además, el peque se ha puesto a darle al Braid y aunque es “mu” complicado para cuando esté esto ya se es capaz de pasarse el Halo sin problemas).
La prueba es muy sencilla, una pequeña animación para ver cómo se va a mover el arco a la hora de apuntar. El mapa del “sprite” es el siguiente:
 
Primero dibujamos el brazo de atrás, girando el contexto el ángulo adecuado, luego pintamos el cuerpo del muñeco (casi a lo Johnny cogió su fusil) y, finalmente, encima de lo dibujado, volvemos a girar el contexto y pintamos el otro brazo y el arco.

El increíble hombre menguante – I.

Ver artículo siguiente de esta serie.
Ver artículo anterior de esta serie.
Lo del “I” en el título es porque después de ver el ejemplo siguiente está claro que tiene que haber un “II” para continuar con este tema y corregirlo:


Este es el primer intento para ir integrando cosas. Principalmente el cambio de pantallas y el cambio en la escala (dos “sprites”, pequeño y grande).
Poco a poco voy definiendo variables globales que se van utilizando en la mayoría de los scripts. Las más destacadas son un el “sprite”, personaje pequeño, el grande y la pantalla actual en la que tenemos definidos los puntos iniciales, finales, el recorrido posible, de dónde venimos y a donde vamos.
Uno de los cambios más destacados es “el bucle principal del juego” que se intenta ejecutar a razón de 30 frames por segundo:

this.actualizarJuego = function() {
        this.sprite.actualizarEstado();
        //
        var siguientePantalla = pantalla.hayQueCambiarDePantalla(this.sprite.posX, this.sprite.posY);
        if (siguientePantalla != 0) {
            var numPantalla = pantalla.numero;
            pantalla = getPantalla(siguientePantalla);
            if (pantalla.escalaReducida)
                this.sprite = spriteEscalaReducida;
            else
                this.sprite = spriteEscalaNormal;
            if (numPantalla < pantalla.numero)   
                this.sprite.setPosicion(pantalla.getPosicionInicial());
            else
                this.sprite.setPosicion(pantalla.getPosicionFinal());
        }
        //                       
        this.drawFrame();
}

Aquí:
  • Actualizamos el estado del sprite (si hay una tecla pulsada se actualiza la posición en función de ella si es que se puede).  
  • Comprobamos si hay que cambiar de pantalla y si es así colocamos el sprite (pequeño o grande, dependiendo de la pantalla) en su posición inicial o final si venimos de la anterior o la siguiente, respectivamente.
  • Dibujamos todo.
El otro cambio destacable es la inclusión de una función “cargarImagenesPantalla” en el script:
Esta función es la encargada de cambiar las imágenes en función de la pantalla a mostrar. Primero pondrá una ventanita de “cargando …”  y cuando se han cargado las imágenes del fondo y del primer plano (si existe ésta) las mostrará. Aquí tenemos dos problemas que creo que son sencillos de resolver:
  • Cuando la pantalla se está cargando si seguimos pulsando las teclas el muñeco se sigue moviendo y cuando se muestran el muñeco no está al principio. Esto se corrige no aceptando la pulsación de las teclas si estamos cargando.
  • La carga de las pantallas va lenta. Esto se debe corregir cargando previamente las imágenes tanto de la pantalla anterior como de la siguiente al llegar a una determinada. El navegador debería “cachear” (guardar temporalmente) la imagen y al necesitarla ya la deberíamos tener disponible en local (directorio temporal del disco duro).

martes, 25 de octubre de 2011

Controlando al personajillo II.

A un árbol me subí
donde manzanas había.
Si manzanas no comí
y manzanas no dejé...
¿cuántas manzanas había?.

El ejemplo:

Mi idea inicial era que el personaje consiguiese, en un momento determinado del juego, una cuerda que podría lanzar para poder subir y bajar. He programado el lanzamiento de la cuerda pero al ir a integrarlo con el movimiento del muñeco he visto que se complicaba mucho. ¿Cuándo recoger la cuerda? ¿Difícil acertar para que se enganche? ¿Hacia dónde está mirando el muñeco?. En definitiva, ¿qué pasa, si como en la mayoría de los juegos, dejo las cuerdas ya colocadas?. Así que descartado el lanzamiento y cuerdas colocadas. ¿Qué pasa con las cuerdas? ¿Por qué los juegos utilizan escaleras? Si engancho las cuerdas en los troncos de arriba el muñeco al subir quedará en el aire, subiendo sin cuerda, ya que no tiene sentido que las cuerdas sobresalgan por encima de los troncos. Para resolver esto nada más sencillo que poner escaleras en lugar de cuerdas ya que las escaleras sí sobresalen. En muchos juegos las escaleras se ven de frente. Después de programar esta parte está claro que esa solución es muchísimo más sencilla ya que no hay que tener en cuenta hacia qué lado mira el personaje y no hay que tener más que una animación con el muñeco de espaldas. En mi caso he dibujado la animación de subir y bajar en la escalera de la derecha (con el personaje mirando hacia la izquierda). Así las manos coinciden con la escalera. Al reflejar el personaje para que suba por el otro lado las manos ya no quedan en la escalera, si no que vuelan. Debería retocar las animaciones, cosa que no hubiera sucedido con la escalera de frente. Además si hubiésemos descartado la poca profundidad que tiene mi escenario también nos hubiésemos evitado el tener que estar mirando qué queda delante y qué queda detrás. Necesitamos poner un plano en el frente para ocultar las manos cuando se sube por la escalera detrás de los troncos.
Para manejar por donde se mueve el personaje y para definir la pantalla he creado el javascript pantalla.js. Se crean segmentos por donde se puede mover el personaje, fuera de ellos no se permite el movimiento (hay que llegar al final del segmento para poder cambiar de dirección, quizás sea necesaria una pequeña ayuda aquí). Además los segmentos verticales se marcan para saber si el personaje debe mirar  hacia la derecha o hacia la izquierda. Esta definición es automática y sólo hay que proporcionar los puntos que unen los segmentos de izquierda a derecha. En el caso de esta pantalla, el recorrido se define como:
Pantalla([0,255,180,255,180,54,546,54,546,255,736,255]); 

El recorrido a realizar es el mostrado en negro pero teniendo en cuenta la posición y el tamaño de las imágenes del sprite y que se su posición es la esquina superior izquierda, nos queda el recorrido mostrado en rojo.
Además dentro de la Pantalla hemos metido un par de métodos que nos indicarán si se llega al final del recorrido (siguiente pantalla) o si se va al inicio (pantalla anterior).
He ampliado el script “listeners” para tener en cuenta las teclas para subir y bajar. Aunque por el momento las teclas son las flechas tendré que cambiarlas ya que se utilizan para mover el scroll y si éste existe es un problema (ahora lo eliminado impidiendo en el html que aparezca).
El código de sprite.js también lo he modificado adaptándolo a los nuevos movimientos y “generalizándolo” para sprites que se mueven con el teclado en todas direcciones (¡sólo uno!).
¿El tamaño “de la cámara”? No tengo muy claro qué tamaño del personaje elegir. En las pantallas donde va haber conversación con otros personajes lo ideal es lo mostrado en los primeros ejemplos, de cerca, pero para otras pantallas, como la primera de este ejemplo, da mucho más juego poner “la cámara” más alejada. Esto nos obliga a meter más imágenes con distintos tamaños o a escalarlas en el canvas. Otra opción podría ser elegir un tamaño intermedio pero, a mí, el cambio de escala me resulta más atractivo de cara al peque.