Single Tech Games

prototype7 single tech games

Libgdx y Box2D, parte 1

Ha pasado muuuucho tiempo desde que escribía sobre programación, ya venia siendo hora, es por eso que hoy se me ocurrió hablar sobre física en videojuegos y en especial el engina de física que viene con Libgdx, Box2D
¿Que es Box2D?, bueno wikipedia me ayudara con el concepto, lo cierto es que con Box2D puedes hacer esos efectos geniales de rebotar un balón, lanzarlo, tirar aves, lanzar frutas, todo lo que hay en los juegos casuales mas geniales en el mundo de los móviles.

Mundo
Lo primero que definiremos en LibGDX es el mundo donde funcionara el juego, para esto en el método Create añadimos:

//Definimos la variable
private World mundo;
-
-
-
public void create() {
-
mundo=new World(new Vector2(0, -10), true);



Donde new Vector2 define las gravedades, en el eje X 0 (Viento) y en el eje Y -10 (Gravedad). El siguiente valor es un booleano que se conoce como allowSleep o permitir dormir, lo que ayuda a ahorrar procesador cuando los objetos no se están usando, usualmente se coloca true.
Cuerpo y Fixture
En box2d existen dos partes en un objeto físico, un cuerpo y un fixture. El cuerpo es la parte invisible que tiene información como la posición, velocidad, ángulo, etc. Y el Fixture es la forma física que se adjunta al cuerpo para darle propiedades como la masa, la fricción, la restitución, etc.
Cuerpo
Box fue hecho con las unidades MKS (Metros, kilos y segundos) en mente, y no es una buena practica, hacer equivaler un metro a 1 pixel, es por eso que creamos un convertidor:

//Definimos la variable
static final float MUNDO_A_BOX=0.01f;
static final float BOX_DEL_MUNDO=100f;
-
-
-
private float convertirABox(float x){
return x*MUNDO_A_BOX;
}



Asi convertimos unidades de pixeles en unidades físicas.
Para crear un cuerpo necesitamos definirlo, es por eso que creamos el Objeto BodyDef primero, el cual guarda las propiedades como posición, angulo, etc. Y luego lo referenciamos al objeto mundo:

private void crearCuerpo(World mundo,Vector2 pos,float angulo){
BodyDef defCuerpo = new BodyDef();
defCuerpo.type = BodyType.DynamicBody;;
defCuerpo.position.set(convertirABox(pos.x),convertirABox(pos.y));
defCuerpo.angle=angulo;
cuerpo = mundo.createBody(defCuerpo);
}



Fixture/Formas
Ahora que el cuerpo fue definido es hora de agregarle una forma física, un Fixture. Primer definimos PolygonShape y le damos dimensiones de ancho y altura.  Como solo necesita las mitad del ancho y altura para definirse del tamaño correcto, lo dividimos entre dos, para luego crear el objeto FixtureDef que tendrá información como densidad, restitución( esta constante define si la colisión es elástico o solido donde los valores van desde 0.0 hasta 1.0, donde 1.0 es elástico y darle un valor mas alto da resultados extraños), forma, etc. e igual que con BodyDef lo referenciamos al objeto mundo.

private void hacerFixtureRectangular(float ancho,float alto,BodyDef.BodyType tipoCuerpo,
float densidad,float restitucion, Vector2 pos,float angulo){
PolygonShape formaCuerpo = new PolygonShape();
float w=convertirABox(ancho/2f);
float h=convertirABox(alto/2f);
formaCuerpo.setAsBox(w,h);
FixtureDef defFixture=new FixtureDef();
defFixture.density=densidad;
defFixture.restitution=restitucion;
defFixture.shape=formaCuerpo;
cuerpo.createFixture(defFixture);
formaCuerpo.dispose();
}



Podemos crear un forma circular también, solo que ya no definimos PolygonShape, sino CircleShape, y le pasamos el radio, ya no el ancho y altura:

private void hacerFixtureCircular(float radio,BodyDef.BodyType tipoCuerpo,
float densidad,float restitucion, Vector2 pos,float angulo){
FixtureDef defFixture=new FixtureDef();
defFixture.density=densidad;
defFixture.restitution=restitucion;
defFixture.shape=new CircleShape();
defFixture.shape.setRadius(5.0f);
cuerpo.createFixture(defFixture);
defFixture.shape.dispose();
}



Actualización del Mundo
De esta forma, un cuerpo puede ser creado y se le puede agregar un fixture. Finalmente para actualizar la física llamamos a la función step, para actualizar con el tiempo delta:

static final float BOX_PASO=1/120f;
static final int  BOX_VELOCIDAD_ITERACIONES=8;
static final int BOX_POSICION_ITERACIONES=3;
private float acumulador;
-
-
-
private void actualizar(float tiempoDelta) {
acumulador+=tiempoDelta;
while(acumulador>BOX_PASO){
mundo.step(BOX_PASO,BOX_VELOCIDAD_ITERACIONES,BOX_POSICION_ITERACIONES);
acumulador-=BOX_PASO;
}
}



Puedes combinar lo valores anteriores con otros valores, para ver cual funciona mejor para ti. Es bueno usar un valor constante para actualizar la física, porque usualmente el renderizado es mas lento que la física y los frames por segundo podrían variar dependiendo de que esta siendo dibujado en la pantalla. Entonces lo que se hace es tener un tiempo de actualización constante para la física la cual es, usualmente, mayor al tiempo de actualización del renderizado. Entonces el tiempo de cada frame lo agregamos a una variable llamada acumulador y hace un ciclo de física un numero de veces menor al tiempo de actualización normal del juego.
El resultado
Ejecutamos el código y chan chan chan chaaaan! no hay nada u_u’ eso es porque no agregamos ninguna texturas a los cuerpos.
Eso lo haremos en la siguiente parte del tutorial.
Gracias a Rotating Canvas por el post original y dejarme traducirlo. Todo el codigo fuente pueden encontrarlo en la siguiente pagina.
Nuevo Juego! Metanse en la piel de un futbolista y sean los heroes de su país con este excitante juego de fútbol de la copa mundial brasil 2014
brazil 2014 soccer fantastic world cup
Euro 2012 Penalty Game
 
Suerte!
pd-> No se olviden bajarse mi juego hecho con LibGDX 🙂 http://singletechgames.com/category/juegos/

Páginas: 1 2

0 0 votes
Article Rating
Subscribe
Notify of
guest
5 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
YaYo Arellano

Otra pagina muy interesante para aprender box2d y totalmente en español
http://box2despanol.blogspot.mx/

[…] y lo malogro, no aprendo nada en programación, así que utilizando lo que aprendimos en el primer tutorial y mirando en la web, podemos crear el más basico de todos los ejemplos, una pelota […]

Atlantis Road

Esta información es muy útil para los que estamos empezando a desarrollar en Android…gracias 🙂