sesión 6: motor de físicas y libgdx · sonido gdx.input acceso a ... • podemos cargar sprite...

25
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

Upload: phamdien

Post on 30-Sep-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 2: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 3: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 4: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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);      }}

Page 5: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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)

Page 6: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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)

Page 7: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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()

Page 8: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 9: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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);

Page 10: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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();                }                    }

Page 11: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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();

Page 12: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 13: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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();}

Page 14: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 15: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 16: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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);

Page 17: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 18: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

• 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

Page 19: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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);

Page 20: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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

Page 21: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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();

Page 22: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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}

Page 23: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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));            ...}

Page 24: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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];}

Page 25: Sesión 6: Motor de físicas y libgdx · sonido Gdx.input Acceso a ... • Podemos cargar sprite sheets generados con TexturePacker • Contamos con una herramienta gratuita propia

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