martes, 27 de diciembre de 2011

Detectar pulsaciones dentro de un rectangulo en modo apaisado. libGDX

Si tenemos el dispositivo en modo apaisado, detectar donde se ha pulsado no es tan facil. Las coordenadas del rectangulo que queremos comprobar no nos sirven. Hay que tener en cuenta siempre que el eje Y va de abajo hacia arriba con las libGDX. Yo lo he "solucionado" cambiando la coordenada y despues de haber creado el rectangulo con las coordenadas sacadas del photoshop.
/** @Pasa de un rectangulo con la posicion y normal a  uno con el eje girado y modo landscape
  * 
  * @param rect el rectangulo a cambiar
  * @return
*/
 private Rectangle CambiarEjeYLandscape(Rectangle rect)
 {  
  return new Rectangle(rect.x, (Configuracion.ALTO_VIEWPORT - rect.y - rect.height), rect.width, rect.height);
 }

miércoles, 21 de diciembre de 2011

Comprobar que se ha pulsado dentro de un rectangulo libGDX

Sacado de el ejemplo SuperJumper que viene con libGDX
  import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public class ComprobadorSuperposicion {
 public static boolean SuperposicionRectangulos (Rectangle r1, Rectangle r2) {
  if (r1.x < r2.x + r2.width && r1.x + r1.width > r2.x && r1.y < r2.y + r2.height && r1.y + r1.height > r2.y)
   return true;
  else
   return false;
 }

 public static boolean puntoEnRectangulo (Rectangle r, Vector2 p) {
  return r.x <= p.x && r.x + r.width >= p.x && r.y <= p.y && r.y + r.height >= p.y;
 }

 public static boolean puntoEnRectangulo (Rectangle r, float x, float y) {
  return r.x <= x && r.x + r.width >= x && r.y <= y && r.y + r.height >= y;
 }
}
 

martes, 20 de diciembre de 2011

Meter archivos en la sd card

Pongamos que queremos, por ejemplo, meter un archivo de configuración.
¿Como se hace? ¿Como meto un archivo en la sdcard del emulador?
Lo suyo es abrir en Eclipse la perspectiva DDMS y  en mmnt->sdcard pulsar el icono que hay arriba a la derecha en el que aparece un flechita apuntando hacia un teléfono.
Pero te puede salir como a mi:
   Failed to push selection: Read-only file system
¿Que hacer?
Te vas a la linea de comandos y luego a : (en Windows XP)
   C:\Documents and Settings\TuUsuario\android-sdks\tools
allí pones:
    mksdcard -l mysdcard 128M sdcard.img
y creas la imagen de la tarjeta sd

Vuelves al Eclipse boton derecho en el proyecto android y “Run configurations…”
En el target , en additional Emulator Command line Options  hay que indicarle que use la imagen de la tarjeta
sd que previamente hemos creado, así:
   -sdcard "sdcard.img"

Volvemos a abrir en Eclipse la perspectiva DDMS y  en mmnt->sdcard pulsar el icono que hay arriba a la derecha en el que aparece un flechita apuntando hacia un telefono. Elegimos el archivo a subir a la sd
y listo.

[Image]

viernes, 16 de diciembre de 2011

TextureAtlas

Esto se usa para explotar las texturas que ha empaquetado el TexturePacker y poderlas pintar con el programa.
Ejemplo de uso:
TextureAtlas atlas;
atlas = new TextureAtlas(Gdx.files.internal("packedimages/pack"));

Lo que hace  TextureAtlas es leer el fichero de texto "pack" y cargar todas las paginas de imagenes que el "pack" referencia.

Y luego para explotarlo y pintar tenemos varias opciones, podemos usar TextureAtlas.AtlasRegions  que son TextureRegions que es un trozo de textura.
AtlasRegion region = atlas.findRegion("imagename");//findRegion ES MUY LENTO  es mejor guardar el valor devuelto.
The coordinate system used has its origin in the upper left corner with the x-axis pointing to the right and the y axis pointing downwards."

Otra opción es usar Sprites.
Sprite sprite = atlas.createSprite("otherimagename");//instancia un nuevo sprite
Si destruimos  el textureAtlas tambien nos cargamos todas las paginas de texturas.

http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=2679


Como hacer cosas especificas de Android

Usando libgdx tenemos tres proyectos pero todo el codigo lo metemos en uno de ellos.
En ese proyecto podemos usar las librerias de Java y las de libgdx.
¿Pero y si queremos usar algo especifico de android?

En el proyecto principal: (donde esta la chicha)
Creas un interface . Aqui meteremos la declaración de los métodos que usaremos en Android.
En la clase que implemente ApplicationListener (en la "main" por decirlo así) deberá extender  el interface que hemos declarado.
En el proyecto android:
Creas una clase que implemente ese interface en el proyecto de Android. Aqui ya metes todo
lo especifico de Android.

Todo esto esta mejor explicado en inglés aqui:
http://code.google.com/p/libgdx-users/wiki/IntegratingAndroidNativeUiElements3TierProjectSetup#Steps_in_loose_order



TexturePacker

Es una utilidad para crear SpriteSheets que tienen la gracia de que no tendremos que estar cargando distintas texturas. Cosa que enlentece el juego.
Usaremos esta utilidad  para recortar "trozos" de una textura grande donde estan mapeadas
varias imagenes mediante un fichero de texto.
Tiene una gui que te puedes bajar o bien lo puedes usar directamente en tu programa importando lo siguiente:
 import com.badlogic.gdx.tools. imagepacker.TexturePacker;
 import com.badlogic.gdx.tools. imagepacker.TexturePacker.Settings;


Como se usa:
En el main de el proyecto de escritorio, el Jogl o el Lwjgl metemos lo siguiente:

        Settings settings = new Settings();
        settings.padding = 0;
        settings.minHeight = 256;//estos tamaños a elegir
        settings.minWidth = 256;
        settings.maxWidth = 1024;
        settings.maxHeight = 1024;
        settings.incremental = true;
       
        TexturePacker.process(
                settings, 

 "C:/tuworkspace/Nombredelproyecto/assets/data/directorio_inputa_empaquetar/"                          "C:/tuworkspace/Nombredelproyecto/assets/data/directorio_output_empaquetado/");

      /*  Y aqui ya iría:
      new JoglApplication(...
      */

Con esto nos crea varios SpriteSheets y un fichero de texto llamado pack que contiene algo así:
    nombrespritesheet.png
    format: RGBA8888
    filter: Nearest,Nearest
    repeat: none
    nombreimagen
        rotate: false
        xy: 0, 0
        size: 76, 76
        orig: 76, 76
        offset: 0, 0
        index: -1
        ....

http://code.google.com/p/libgdx/source/browse/trunk/extensions/gdx-tools/src/com/badlogic/gdx/tools/imagepacker/TexturePacker.java

miércoles, 7 de diciembre de 2011

Como comunicarse con la red local usando UDP II Cola bloqueante en Java

La idea es cada vez que se reciba un mensaje meterlo en una cola de mensajes recibidos.
Y otro hilo irá sacandolos de allí y haciendo lo que tenga que hacer segun el mensaje que haya llegado. En esta web lo explican:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while(true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }
 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while(true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }
 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

Como comunicarse con la red local usando UDP I

Para poder hacerlo hay que usar hilos ya que si no estariamos bloqueando la ejecución del programa.
Por lo tanto no hay mas huevos que usar hilos. Como no tengo ni puta idea de como se usan los hilos en Java ni en Android porque vengo de .NET  C# me toca empollarmelo.
http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html
Ejemplo:
public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}