lunes, 30 de julio de 2012

Aprendiendo Scala con el desafío Factorion de Solveet

Últimamente he estado aprendiendo un poquito de Scala y me parece un lenguaje bastante interesante. Me recuerda a mis tiempos de la facultad en la asignatura de Programación Declarativa con Ocaml. Buscando por YouTube, encontré una charla de introducción bastante buena, el que subió el video lo tituló Why Scala? ...by a hilarious Indian guy, y acertó de pleno. Quizá no sea el mejor para aprender, pero la hora y media que dura se hace extremadamente amena.

Mi primer desarrollo en Scala no es muy funcional que digamos, pero me ha servido para tomar un poco de contacto con algunos conceptos básicos. Se trata de uno de los desafíos propuestos en Solveet titulado Factorion. Si lees el enunciado verás que es el típico ejercicio de codificación de un algoritmo matemático. La primera versión tardaba unos 10s pero conseguí reducirlo a poco más de 2,5s precalculando los factoriales y evitando la conversión del número a string para recorrer los dígitos. ¡Se agradece algún comentario!

object Calculator extends App { val factors = scala.collection.mutable.Map[Int, Int]() // Turns the number into an array of digits def getDigits(number :Int):Array[Int] = { var total = number var n = total.toString.length var digits = new Array[Int](n) for (x <- 1 until n+1) { digits(x-1) = total%10 total = (total - total%10) / 10 } return digits } def isFactorion(number :Int):Boolean = { var digits = getDigits(number) digits = digits.map( x => factors(x) ) var total = 0 digits foreach (total += _) if (number == total) { return true } return false } // Precalculate factorials factors(0) = 1 for (i <- 1 until 10) { factors(i) = factors(i-1) * i } // Calculate factorions var start = System.nanoTime for (i <- 0 until 2500001) { if (isFactorion(i)) { println(i) } } var end = System.nanoTime println("-- "+ (end-start)/1000000+ " ms") }

miércoles, 9 de mayo de 2012

Plataformas de clasificaciones para juegos

Para que un juego triunfe, el pilar fundamental es la competitividad. Ya sea entre dos contrincantes, contra un número variable de jugadores, contra otro equipo o contra uno mismo. La gente juega para divertirse y ser mejor que otros en algo, divierte. Y mucho. Ya no hablamos de ser EL MEJOR.

Hace poco hablaba del Juego de volley-ball 2D con JavaFX I que estaba haciendo. Una vez que terminé la mecánica de juego básica, el siguiente paso era obvio: sistema de clasificación. En un primer momento se me ocurrió montar un sistema básico de nombre-puntuación, un simple script en PHP serviría y, como el juego no lo va a usar prácticamente nadie, a lo mejor ni siquiera usaría base de datos. Rápidamente deseché esa idea.

Vivimos en el mundo de internet everywhere, ¡alguien tenía que haberlo hecho ya!. Efectivamente, una simple búsqueda en Google de games score platform dio el resultado esperado. Scoreoid ofrece una API REST con todo tipo de funcionalidades básicas para elaborar clasificaciones para gran parte de juegos. Se basa en tres conceptos principales: Juego (Game), Puntuación (Score) y Jugador (Player).

Con esta plataforma (gratuita), ya tenía un sistema completo de puntuaciones para añadir a mi juego sin preocuparme de lógicas complejas, persistencia de las puntuaciones, gestión de jugadores, etc. y todo a un GET de distancia. Sin embargo, podría ser más sencillo todavía.

Si estoy haciendo un juego de volley ball, no quiero tener que preocuparme del protocolo de red a utilizar, de si la conexión es o no segura, de si los parámetros de mi petición son GET o POST, etc. El API ofrecida es extraordinariamente sencilla, pero precisamente por serlo y estar abierta a un uso por parte de cualquier plataforma o lenguaje de programación, requiere algo de integración. Una librería que me abstraiga de todo eso sería genial. Como jTwitter, POI,... o ¡JDBC!

La única pega era que no existía, así que... me he puesto a crearla.

viernes, 4 de mayo de 2012

Juego de volley-ball 2D con JavaFX II

La verdad es que debería haber escrito algo sobre este tema hace unos días. Viendo el blog parece que ya he abandonado el miniproyecto, pero nada más lejos de la realidad. A día de hoy la funcionalidad básica que garantiza la mínima jugabilidad está desarrollada. Antes de lo que esperaba, para ser sincero.



Resumiendo un poco el proceso de desarrollo, los puntos más complejos han sido:

  • Detección de intersecciones: el framework JavaFX, que yo sepa, no proporciona ningún método directo para realizar este cálculo. Si existe, se agradece el apunte en un comentario y podréis reír y hacer escarnio de mi trabajo en vano sin problemas.
  • Cálculo de velocidad y dirección de rebote en el choque bola-slime: no se el nivel de trigonometría de la mayoría, pero el mío no daba para obtener la trayectoria de una bola que choca contra una superficie curva en un ángulo φ.
En cuanto al tema de las intersecciones, opté por escribir diferentes métodos para cada una de las intersecciones posibles: bola-pared, bola-suelo, bola-slime, slime-pared, slime-suelo. Nótese que llamo pared a los objetos que frenan la velocidad del eje X (laterales y red) y suelo al objeto que frena el movimiento en el eje Y. A continuación, la implementación del método de la clase que representa al slime y detecta la intersección con la bola:

public class Slime extends javafx.scene.shape.Arc { /* ...Class code... */ private boolean intersects(Ball ball) { double dx = ball.getX() - getX(); double dy = ball.getY() - getY(); double dist = Math.sqrt(dx * dx + dy * dy); return dist < ball.getAsCircle().getRadius() + this.getAsArc().getRadiusX(); } }

En cada refresco de pantalla, se chequean las colisiones de todos los objetos evaluando si intersecan unos con otros y tomando las acciones oportunas. El método de la clase Slime que gestiona una colisión bola-slime y actualiza la velocidad (tanto Vx como Vy) es el siguiente:


public class Slime extends javafx.scene.shape.Arc { /* ...class code... */ private void collide(Ball ball) { if (intersects(ball)) { if (!isIgnoreCollisionWith(ball)) { double dx = ball.getX() - this.getX(); double dy = ball.getY() - this.getY(); double dist = Math.sqrt(dx * dx + dy * dy); double something = (dx * ball.getVx() + dy * ball.getVy()) / dist; ball.setVx(ball.getVx() + getVx() - 2 * dx * something / dist); ball.setVy(ball.getVy() + getVy() - 2 * dy * something / dist); addIgnoreCollisionWith(ball); } } else { removeIgnoreCollisionWith(ball); } } }


Como se puede ver, primero se comprueba que realmente haya intersección con el método explicado anteriormente y, si la hay, se realizan los cálculos de las nuevas velocidades con las que la bola saldrá del choque. A mayores, se ha añadido código que comprueba que el objeto no esté siendo ignorado por una colisión anterior, esto tiene una explicación muy sencilla: puede ocurrir que la velocidad resultante del choque no sea suficiente para que en el siguiente refresco los objetos ya no intersequen, pero realmente no queremos que  se vuelva a calcular nada en ese momento. El último else garantiza que en cuanto esos objetos no se toquen, dejará de ignorarse esa colisión.

Aprovechando que las aplicación JavaFX son de fácil despliegue en un navegador, he subido lo que hay hecho hasta ahora y, previa descarga de las librerías que no están incluidas con la JRE, es perfectamente jugable:

domingo, 22 de abril de 2012

Juego de volley-ball 2D con JavaFX I

A qué viene todo esto

A 6 días de que se cumpla un año de la última entrada de esta enésima microaventura bloguera, regreso interesado en el tema de físicas de juegos en dos dimensiones. Todo ha surgido a raíz del descubrimiento, a través de un compañero de trabajo, de un antiguo, simple, descuidado, cutre y tremendamente adictivo juego llamado Slime Volley. Buscando en Google, pueden encontrarse múltiples versiones pero creo que la original es la enlazada previamente. Incluso publica parte del código de la versión multijugador (supongo que de ahí proceden tantos clones del mismo juego).

Cómo lo haremos

Como digo en el título, la idea es realizar un clon de la mecánica de Slime Volley empleando el framework JavaFX. Ni más, ni menos. Los principales retos que se me plantean a la hora de realizar este proyecto son los siguientes:

  • Empezar y terminar: muchas veces nos proponemos cosas pero, poco a poco, se pierde interés, se pierde el objetivo que era la motivación inicial, etc.
  • Aprender las características básicas de JavaFX.
  • Escribir el código como me gustaría leer el de los demás.
  • Recordar fundamentos de física necesarios para dotar al juego de un mínimo realismo.
En un principio, lo básico será programar las leyes de nuestro Slime Universe, las principales cosas a tener en cuenta serán los rebotes en los objetos de la pantalla y la gravedad que hará que nuestra pelota de volley-ball caiga. Para el tema de rebotes, podría optarse por dos posibilidades:
  • Los objetos están dibujados pero no interactúan: es decir, la pelota se moverá por la pantalla y solo cambiará de dirección en base a la posición (x,y) que alcance. Los objetos se pintan para hacer el efecto de choque, pero sin ninguna lógica.
  • Los objetos están dibujados e interactúan: se detectan colisiones entre bola, paredes, suelo, red, slimes,... requiere más lógica y matemáticas pero también es más divertido y escalable.

Un poco de física

Para conseguir posicionar la pelota en la pantalla correctamente en todo momento y que la sensación de caída y rebote sea real, debemos aplicar las típicas fórmulas de cinemática que todos vimos en el instituto y recordamos por el típico problema de la bala de cañón.

y = y0 + v0y·t + g·t2/2
vy = v0y + g·t

Posición en el eje Y y velocidad de la bola en el momento t.

x = v0x + vx·t
vx = v0x

Posición en el eje X y velocidad de la bola en el momento t.

Previsualización

Añadiendo a los jugadores y un par de gestión de eventos de para detectar pulsaciones en el teclado, ya tenemos una pantalla rudimentaria con una bola rebotando por su cuenta, ya que todavía no está implementado el rebote en jugadores, solamente en suelo y paredes. Podría añadirse el efecto de rozamiento con aire y paredes modificando levemente las ecuaciones anteriores.



Por último, mencionar que me ha sido de gran ayuda para plantear el esqueleto del juego el blog de Carl, en el que está haciendo una serie sobre implementar un juego con Java FX y es de donde yo saqué la idea de realizar esta serie de entradas.

jueves, 28 de abril de 2011

Distancia entre dos puntos geográficos

Para calcular la distancia entre dos posiciones geográficas dadas por el par (latitud, longitud), se puede emplear como aproximación la Fórmula de Haversine.

martes, 15 de febrero de 2011

Gestión de configuración de la aplicación

Commons Configuration provides a generic configuration interface which enables a Java application to read configuration data from a variety of sources. Commons Configuration provides typed access to single, and multi-valued configuration parameters.

One of the strength of Commons Configuration is its ability to mix configurations from heterogeneous sources, this section will introduce you to the different configurations available and will show you how to combine them.

Link: http://commons.apache.org/configuration

viernes, 21 de enero de 2011

Usar Facebook como sistema de autenticación exclusivo o complementario

Empleando el API de Facebook Connect, se puede conseguir relacionar la cuenta de un usuario de Facebook con otra en nuestra aplicación, de esta forma, evitamos obligar al usuario a registrarse.