Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles © 2011-2012 Depto. Ciencia de la Computación e IA Gráficos y multimedia Sesión 6: Motor de físicas y libgdx
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
© 2011-2012 Depto. Ciencia de la Computación e IA
Gráficos y multimedia
Sesión 6: Motor de físicas y libgdx
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Puntos a tratar• Motor libgdx• Módulos de libgdx• Gráficos• Escena 2D
• Motor Box2D• Objetos de Box2D• Tipos de cuerpos• Unidades de medida• Simulación física• Detección de colisiones
2
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Motor libgdx
• Framework para videojuegos en Java SE y Android
• Implementamos dos proyectos para hacerlo multiplataforma
• Proyecto Java SE• Se implementa el juego con Java genérico y libgdx• Se puede ejecutar como aplicación de escritorio
• Proyecto Android• Depende del proyecto anterior• Aporta la actividad principal que ejecuta en Android el juego
3
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Aplicación libgdx• Gestiona el ciclo OpenGL del juego• Aplicación Android
• Aplicación libgdx
4
public class MiActividad extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... }}
public class MiActividad extends AndroidApplication { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initialize(new MiApplicationListener(), false); }}
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
ApplicationListener
5
public class MiApplicationListener implements ApplicationListener { @Override public void create() { ... }
@Override public void pause() { ... }
@Override public void resume() { ... } @Override public void dispose() { ... }
@Override public void resize(int width, int height) { ... }
@Override public void render() { ... }}
Ciclo del juego:•Actualizar la escena•Renderizar gráficos
Cambio del tamaño de la pantalla (p. ej. cambio de orientación)
Liberar recursos
Reanudar el juego
Inicializar el juego
Pausar el juego (p. ej. llamada recibida)
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Módulos de libgdx
• Utilidades para el desarrollo de videojuegos• Los encontramos disponibles como campos estáticos de Gdx
6
Gdx.graphics Acceso al contexto gráfico (OpenGL)
Gdx.audio Reproducción de música y efectos de sonido
Gdx.input Acceso a la entrada (pantalla táctil y acelerómetro)
Gdx.files Acceso a los ficheros (assets)
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Gráficos en libgdx
• Tenemos acceso al contexto OpenGL
• Tiempo delta• Indica el tiempo transcurrido desde la anterior iteración
7
int width = Gdx.graphics.getWidth();int height = Gdx.graphics.getHeight(); GL10 gl = Gdx.app.getGraphics().getGL10();gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);gl.glViewport(0, 0, width, height);
Gdx.graphics.getDeltaTime()
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Clases para gráficos
8
Texture Textura OpenGL (potencia de 2)
TextureAtlas Textura con regiones (TexturePacker)
TextureRegion Zona de una textura en memoria
Sprite Región con posición y rotación
BitmapFont Fuente bitmap (formato .fnt)
SpriteBatch Dibujar múltiples sprites 2D
Mesh Malla 3D
ObjLoader Carga una malla 3D de un fichero .obj
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Carga de sprite sheets
• Podemos cargar sprite sheets generados con TexturePacker• Contamos con una herramienta gratuita propia de libgdx• El formato generado es distinto al de Cocos2D
• Las texturas en memoria (atlas) deberemos liberarlas con dispose() cuando no se vayan a utilizar más
9
TextureAtlas atlas = new TextureAtlas(Gdx.files.getFileHandle("sheet", FileType.Internal));TextureRegion regionPersonaje = atlas.findRegion("frame01");TextureRegion regionEnemigo = atlas.findRegion("enemigo"); Sprite spritePersonaje = new Sprite(regionPersonaje);Sprite spriteEnemigo = new Sprite(regionEnemigo);
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Dibujar en un sprite batch
• Dibujar sprites de una misma textura de forma consecutiva
• Al cambiar de textura toda la geometría pendiente se envía a la GPU
• Es importante liberar el batch al finalizar
10
public class MiJuego implements ApplicationListener { SpriteBatch batch; TextureAtlas atlas; Sprite spritePersonaje; Sprite spriteEnemigo; @Override public void create() { // Inicializar atlas y sprites ... batch = new SpriteBatch(); } @Override public void dispose() { batch.dispose(); atlas.dispose(); } @Override public void render() { batch.begin(); spritePersonaje.draw(batch); spriteEnemigo.draw(batch); batch.end(); } }
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Tilemaps• Soporta formato TMX, pero necesitamos generar un fichero
adicional con una herramienta incluida con libgdx• Creamos TiledMap (mosaico) y TileAtlas (textura en memoria)
• Creamos TileMapRenderer para dibujar el mapa en pantalla
• Dibujamos el mapa dentro del ciclo del juego
11
TiledMap fondoMap = TiledLoader.createMap( Gdx.files.getFileHandle("fondo.tmx", FileType.Internal)); TileAtlas fondoAtlas = new TileAtlas(fondoMap, Gdx.files.getFileHandle(".", FileType.Internal));
tileRenderer = new TileMapRenderer(fondoMap, fondoAtlas, 40, 40);
tileRenderer.render();
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Grafo de la escena 2D
• Sólo es útil para la UI en libgdx
12
Button Label
ImageLabel Group Action
Stage
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Acciones en la escena 2D• Creamos la escena
• Añadimos un actor (nodo) a la escena
• Añadimos acciones al actor
• Actializamos y renderizamos la escena en el ciclo del juego
13
stage = new Stage(width, height, false);
Label label = new Label("gameover", fuente, "Game Over");stage.addActor(label);
FadeIn fadeIn = FadeIn.$(1);FadeOut fadeOut = FadeOut.$(1);Delay delay = Delay.$(fadeOut, 1);Sequence seq = Sequence.$(fadeIn, delay);Forever forever = Forever.$(seq);label.action(forever);
@Overridepublic void render() { stage.act(Gdx.graphics.getDeltaTime()); stage.draw();}
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Motor de físicas Box2D• Físicas de cuerpos rígidos• Escrito en C++• Se incluye en casi todos los motores anteriores• AndEngine, Cocos2D, libgdx
14
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Conceptos de Box2D
15
Body Cuerpo rígido. Puede ser estático, cinemático, o dinámico
Fixture Fija las propiedades de un cuerpo, incluyendo su forma
Shape Define la forma de un cuerpo (círculo o polígono)
Constraint Limita los grados de libertad de un objeto
Joint Define una unión de diferentes cuerpos
World Simulación del mundo 2D. Contiene un conjunto de cuerpos
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Mundo de Box2D
• Se encarga de realizar la simulación física
• Podemos añadir al mundo diferentes cuerpos rígidos
• Se crea con el vector de gravedad a aplicar• La gravedad se indica mediante un vector 2D (x, y)• El segundo parámetro nos permite optimizar el rendimiento,
evitando que se simulen los cuerpos inactivos si es true
• Podemos cambiar la gravedad con setGravity
16
World world = new World(new Vector2(0, -‐10), true);
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Tipos de cuerpos en Box2D
17
Estático
CinemáticoDinámico
• Usa el sistema métrico (m, kg)• Debemos fijar ratio de conversión píxeles-metros• Optimizado para manejar objetos de 1 metro
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Unidades de medida en Box2D
18
BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.DynamicBody; bodyDef.position.x = x / PTM_RATIO; bodyDef.position.y = y / PTM_RATIO;
Body body = world.createBody(bodyDef); PolygonShape bodyShape = new PolygonShape(); bodyShape.setAsBox((width/2) / PTM_RATIO, (height/2) / PTM_RATIO); body.createFixture(bodyShape, 1.0f); bodyShape.dispose();
PTM_RATIO = 32width = 32 (1m)height = 64 (2m)
32 px1 m
64 px2 m
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Límites del escenario• Podemos crearlos como objetos estáticos de tipo arista
19
BodyDef limitesBodyDef = new BodyDef();limitesBodyDef.position.x = x;limitesBodyDef.position.y = y; Body limitesBody = world.createBody(limitesBodyDef);EdgeShape limitesShape = new EdgeShape();limitesShape.set(new Vector2(0.0f / PTM_RATIO, 0.0f / PTM_RATIO), new Vector2(width / PTM_RATIO, 0.0f / PTM_RATIO));limitesBody.createFixture(limitesShape,0).setFriction(2.0f); limitesShape.set(new Vector2(width / PTM_RATIO, 0.0f / PTM_RATIO), new Vector2(width / PTM_RATIO, height / PTM_RATIO));limitesBody.createFixture(limitesShape,0); limitesShape.set(new Vector2(width / PTM_RATIO, height / PTM_RATIO), new Vector2(0.0f / PTM_RATIO, height / PTM_RATIO));limitesBody.createFixture(limitesShape,0); limitesShape.set(new Vector2(0.0f / PTM_RATIO, height / PTM_RATIO), new Vector2(0.0f / PTM_RATIO, 0.0f / PTM_RATIO));limitesBody.createFixture(limitesShape,0);
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Simulación física• En cada iteración del ciclo del juego debemos actualizar la
simulación del mundo físico• Debemos proporcionar el delta time en la actualización
20
// Ejecuta la simulaciónworld.step(delta, 6, 2);world.clearForces(); // Lee datos de los cuerpos en la simulación físicaVector2 pos = cuerpo.getPosition();float rot = (float)Math.toDegrees(cuerpo.getAngle());
Conviene acortarlo
Iteraciones posición
Iteraciones velocidad
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Datos de usuario de los cuerpos• Podemos asignar datos de usuarios genéricos a los cuerpos• Útil para adjuntar el sprite asociado al cuerpo
• El cuerpo de Box2D sólo realiza simulación física• Nosotros debemos mostrarlo en pantalla mediante un sprite• Esto lo haremos tras la actualización del mundo
21
body.setUserData(sprite);
Sprite sprite = (Sprite)body.getUserData();Vector2 pos = body.getPosition();float rot = (float)Math.toDegrees(body.getAngle()); sprite.setPosition((int)(pos.x * PTM_RATIO), (int)(pos.y * PTM_RATIO));sprite.setRotation(rot); batch.begin();sprite.draw(batch);batch.end();
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Detección de colisiones• Podemos definir listener de contacto (ContactListener)
22
@Overridepublic void beginContact(Contact c) { // Se produce un contacto entre dos cuerpos} @Overridepublic void endContact(Contact c) { // El contacto entre los cuerpos ha finalizado } @Overridepublic void preSolve(Contact c, Manifold m) { // Se ejecuta antes de resolver el contacto. // Podemos evitar que se procese } @Overridepublic void postSolve(Contact c, ContactImpulse ci) { // Podemos obtener el impulso aplicado sobre los cuerpos en contacto}
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Velocidad de impacto
• WorldManifold da información sobre los puntos de contacto
23
public void beginContact(Contact c) { Body bodyA = c.getFixtureA().getBody(); Body bodyB = c.getFixtureB().getBody(); // Obtiene el punto de contacto Vector2 point = c.getWorldManifold().getPoints()[0]; // Calcula la velocidad a la que se produce el impacto Vector2 velA = bodyA.getLinearVelocityFromWorldPoint(point); Vector2 velB = bodyB.getLinearVelocityFromWorldPoint(point); float vel = c.getWorldManifold().getNormal().dot(velA.sub(velB)); ...}
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
Impulso durante el contacto
• Nos informa de la fuerza ejercida entre los cuerpos mientras dura el contacto
24
public void postSolve(Contact c, ContactImpulse ci) { Body bodyA = c.getFixtureA().getBody(); Body bodyB = c.getFixtureB().getBody(); float impulso = ci.getNormalImpulses()[0];}
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia © 2011-2012 Depto. Ciencia de la Computación e IA Motor de físicas
¿Preguntas...?
25