sábado, 24 de mayo de 2014

Zombi Killer : Juego de plataformas.

Recientemente estuve trabajando en este juego llamado Zombi Killer que consiste en ir matando zombies, recolectar items, comprar mejoras para tu arma, etc. Como se han de imaginar para este juego utilize Libgdx asi como Box2D, Tiled, Scene2D entre otros.

Descargen el juego y no olviden calificarlo. Si quieren que haga un tutorial sobre como se creo alguna parte del juego lo comentan aqui en el blog. Aqui estan algunas capturas.

 



 Google Play App store


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


jueves, 8 de mayo de 2014

7.- Fuerzas, impulsos y velocidad lineal.

Como sabemos en Box2d existen fuerzas que cuando las aplicamos a los cuerpos crean una simulación real, esto nos permite mover los cuerpos, lanzar pájaros con una resortera, disparar, saltar, etc. 

Para aprender sobre las diferentes fuerzas vamos a crear 3 pelotas como se ve en la siguiente imagen.






Necesitamos un arreglo en donde almacenar los cuerpos de nuestras 3 pelotas al que llamare arrPelotas.

Como pueden ver se crea el arreglo arrPelotas en el constructor así como el vector velocidad, este ultimo es la fuerza "velocidad" que aplicaremos a nuestras 3 pelotas. Así que suponemos que las 3 pelotas se moverán de la misma forma, a la misma velocidad, pero no es así.

Tambien tenemos 4 funciones que son crearPiso(), crearPelotaIzquierda(), crearPelotaCentro() y crearPelotaDerecha(). Como su nombre lo indica la primera crea el piso y las otras crean las pelotas, en este tutorial omitiré la explicación de crear el piso ya que en tutoriales anteriores se ha explicado.

La creación de las pelotas es muy sencilla y si han seguido los tutoriales anteriores no tendrán ningún problema. Primero creamos un BodyDef donde asignamos la posición y el tipo de cuerpo que en este caso es dinamico. Después creamos una figura circular con CircleShape con un radio de .25 metros.
A continuación una fixtura con una densidad de 15 kgm/s^2 (kilogramo * metro / segundo ^2), fricción de .5 y elasticidad de .5.

Noten que guardamos el cuerpo en el arreglo de la siguiente manera arrPelotas[0] = oBody;

Para las 2 pelotas restantes es lo mismo lo unico que se modifica es la posición en X.


Por ultimo no hay que olvidar llamar la función step de nuestro mundo oWorld.step(delta, 8, 6); y tambien dibujar en pantalla los cuerpos del mundo renderer.render(oWorld, oCamBox2D.combined):.

Como pueden ver en la función draw()  tambien dibujamos los Frames por segundo de nuestra aplicación.

Aplicando las fuerzas

Se preguntaran que pasara si corremos la aplicación en este momento. La respuesta es nada ya que no hemos aplicado las fuerzas a las pelotas. Esto lo haremos dentro del constructor después de haberlas creado de la siguiente manera:
Recuerdan que habíamos guardado los cuerpos en el arreglo, esto para poder aplicar las fuerzas.
Si corremos la aplicación vemos que las pelotas no se mueven de la misma forma:


  • La primera a simple vista no hace nada
  • La segunda se mueve solo un poco
  • La tercera se mueve muy arriba


Se preguntaran que es lo que esta pasando. Vamos a analizar cada una de las funciones:

applyForceToCenter: Aplica una fuerza al centro comúnmente en Newtons en este caso hacia arriba, un ejemplo real seria bajarte de tu automóvil y empujarlo por un instante con una fuerza de 50 Newtons. ¿Que distancia recorrería? Normalmente no lo empujarías ni 3 metros. Aplicar una fuerza depende del tiempo y en el caso de nuestra pelota solo lo hacemos un instante por lo que la pelota nisiquiera se levanta.

applyLinearImpulse: Aplica una fuerza comúnmente en Newtons-segundos esto modifica instantáneamente la velocidad del cuerpo en el caso de nuestra pelota hacia arriba, como ejemplo real si empujamos nuestro automóvil con un fuerza de 50 Newtons-segundo ¿Que distancia recorrería?. Pero que pasa si empujamos una caja de carton con la misma fuerza ¿Que distancia recorrería nuestra caja?, La caja de carton alcanzaría una distancia muy grande ya que su masa es muy pequeña. Como podemos ver aplicar un impulso depende de la masa de nuestro cuerpo. 

Como ejercicio modifica la densidad de la pelota del centro, actualmente la densidad es de 15,  ¿Que pasa cuando pones una densidad menor?

setLinearVelocity: Por ultimo esta función cambia la velocidad del objeto sin depender del tiempo ni de la masa del cuerpo. En pocas palabras no importa si modificamos la densidad, la pelota siempre va alcanzar la misma altura.

Nota:

A nuestras pelotas las fuerzas siempre fueron aplicadas a su centro, en caso de que aplicáramos la fuerza en un lugar diferente existiria una rotación de los cuerpos.

---

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

lunes, 5 de mayo de 2014

Codigo fuente tutoriales Box2D

A partir de hoy, subire el código fuente de cada uno de los tutoriales que veamos a lo largo de este blog. Lo pueden descargar y modificar a su gusto. 

Una vez que tengan importen el proyecto a eclipse lo pueden correr y tendrán una aplicación como esta donde podrán probar cada uno de los tutoriales.


Instrucciones

- Si no carga la aplicación utiliza Google chrome o algún navegador con soporte WebGL
- Presiona la tecla ESC para regresar al menu principal.



Descarga el código fuente  


¡Atención!

Este proyecto esta basado en el nuevo sistema Gradle adoptado por LibGdx