domingo, 11 de mayo de 2014

8 .- Cuerpos y sprites (imagenes)

En este tutorial vamos a aprender como dibujar una imagen en nuestro cuerpo, por ejemplo si tenemos un cuerpo circular que representa una pelota dibujaremos una imagen de una pelota junto con nuestro cuerpo. Vemos la siguiente imagen:



Podemos observar que tenemos dos tipos de cuerpos uno circular para las pelotas y uno cuadrado para las cajas. Es necesario almacenar la información de los cuerpos para saber exactamente donde vamos a dibujar los sprites para esto he creado una clase interna llamada Figura donde voy a guardar el tipo, la posición y el ángulo actual del cuerpo.

La clase Figura es muy sencilla, en el constructor asignamos el valor de la posición así como el tipo de la figura, la función update recibe un cuerpo de donde tomaremos la posición y actualizaremos la de nuestro objeto así como el ángulo.  Es importante recordar que para cada caja o pelota que vemos en la imagen se necesita un objeto de la clase Figura.
La clase cuenta con dos constantes que nos servirán para determinar que tipo de figura es TIPO_PELOTA TIPO_CAJA. Tambien existe un vector donde almacenaremos la posición en X y en Y así como una variable llamada angleDeg para guardar el ángulo actual de la figura en grados.

En el constructor solo creamos el objeto position así como asignamos el tipo. Por ultimo en la función update() recibimos como parametro un cuerpo de donde tomaremos la posición y el ángulo y actualizaremos nuestras variables.

Después de crear la clase Figura continuamos con definir las variables que utilizaremos. Para comenzar definimos los objetos renderer y oWorld. Enseguida tenemos una lista que almacenara todos los cuerpos que existan en el mundo así como una para guardar todos los objetos de la clase Figura. Tambien tenemos dos objetos de la clase TextureRegion que prácticamente son las imágenes que vamos a dibujar en los cuerpos.

En el constructor creamos los objetos y las listas, cargamos las imágenes,  creamos el piso y agregamos una pelota y una caja con las funciones crearPelota() y crearCaja().

Las funciones crearPelota() y crearCaja() son muy similares ya que solo difieren en unas cuantas lineas de código  por lo que solo analizaremos crearPelota() a detalle. Para comenzar se crea un objeto de la clase Figura en el constructor asignamos su posición en X y en Y así como el tipo de figura que en este caso es TIPO_PELOTA. A continuación creamos la definición del cuerpo asignamos la posición tomando los valores de X y Y de nuestro objeto obj y decimos que es un cuerpo dinámico bd.type = BodyType.DynamicBody. Enseguida creamos la forma de nuestro cuerpo que en esta caso es circular CircleShape y le asignamos un radio de .15 metros. Luego creamos una fixtura donde le asignamos la forma, densidad, fricción y elasticidad. Por ultimo creamos el cuerpo, le asignamos la fixtura, le asignamos la información al cuerpo que en este caso es el objeto obj y tambien agregamos obj a la lista de figuras arrFiguras.add(obj).

Estas dos ultimas lineas oBody.setUserData(obj) arrFiguras.add(obj) son muy importantes ya que si no las agregamos no podremos actualizar la posición del objeto Figura.


En cuanto a la función crearCaja() la unica diferencia es el tipo de la figura así como la forma que ya no sera circular sino un cuadrado.

En la función update() creamos una figura nueva cada vez que damos clic a la pantalla, hay que recordar que Gdx.input.justTouched() regresa verdadero si la pantalla se acaba de tocar.  Se llama a la función oWorld.step(delta, 8, 6) para que se lleve a cabo la simulación.  Tambien vamos a iterar entre cada uno de los cuerpos que existen en el mundo, para esto primero es necesario obtener los cuerpos que existen esto se hace con la función oWorld.getBodies(arrBodies) que recibe como parametro nuestra lista que habíamos definido antes. Después ya estando dentro del ciclo obtenemos una cuerpo de la lista y la guardamos Body body = i.next() en el objeto body, vemos si la información del cuerpo es de la clase Figura en caso de que sea verdadero llamamos la función update de la figura almacenada en el user data del cuerpo.

Nota: En este ejemplo todos los cuerpos tienen como user data un objeto de la clase Figura y no era necesario hacer la condición if (body.getUserData() instanceof Figura) pero lo hicimos porque es buena practica.

Para finalizar tenemos la función draw() que explicare en dos partes.
En la primera parte actualizamos la cámara de la UI (Interfaz grafica) le asignamos la matriz de proyección a nuestro SpriteBatch (batcher) y dibujamos en pantalla una cadena de texto y los frames por segundo.

En la segunda parte actualizamos la cámara del mundo oCamBox2D asignamos la matriz de proyección al SpriteBatch, y llamamos la función drawFiguras() que explicare mas adelante,  y por ultimo dibuja los cuerpos con la función renderer.render(oWorld, oCamBox2D.combined)


Para finalizar el tutorial tenemos la función drawFiguras() que es la encargada de dibujar las imágenes sobre los cuerpos.
Es necesario iterar entre cada uno de los elementos de nuestra lista arrFiguras dependiendo del tipo de cada objeto vamos a dibujar o una caja o una pelota para esto creamos un objeto keyframe  y lo inicializamos de acuerdo al tipo de objeto. Y con nuestro batcher dibujamos el objeto keyframe.


---

Con esto finalizamos el tutorial 8. Recuerden que pueden descargar el código fuente


2 comentarios:

  1. Hola muy buenas, para aplicar el drag and drop sobre una de esas cajas por ejemplo como lo harías? un saludo y gracias de antemano.

    ResponderEliminar