libgdx: user input and frame by frame animation

33
libGDX: User Input and Frame by Frame Anima8on Jussi Pohjolainen Tampere University of Applied Sciences

Upload: jussi-pohjolainen

Post on 15-Jul-2015

526 views

Category:

Technology


2 download

TRANSCRIPT

libGDX:  User  Input  and  Frame  by  Frame  Anima8on  

Jussi  Pohjolainen  Tampere  University  of  Applied  Sciences  

TOUCH  +  KEYBOARD  

Event  vs  Polling  

•  Polling  – Do  something  on  each  frame,  really  fast  

•  Was  mouse  clicked?  Was  mouse  clicked?  Was  mouse  clicked?  

– Good  for  arcade  games  •  Event  – Do  something  when  event  handles  

•  No8fy  when  mouse  was  clicked  

•  Mouse  /  touch  /  keyboard  can  be  received  either  in  1)  polling  or  2)  event  handling  

Polling  Touch  /  Keyboard  

•  For  most  arcade  games,  polling  is  good  •  Mul8touch  is  supported!  

–  boolean first = Gdx.input.isTouched(0); –  boolean second = Gdx.input.isTouched(1); –  int firstX = Gdx.input.getX(); –  int firstY = Gdx.input.getY(); –  int secondX = Gdx.input.getX(1); –  int secondY = Gdx.input.getY(1);

•  Keyboard  –  boolean isAPressed = Gdx.input.isKeyPressed(Keys.A);

Polling:  InputProcessor

•  An  InputProcessor  (Interface)  is  used  to  receive  input  events  from  the  keyboard  and  the  touch  screen  

•  It  has  to  be  registered  – Input.setInputProcessor(InputProcessor);

•  When  registered  the  methods  from  InputProcessor  interface  are  called.

InputProcessor  -­‐  methods  

Using  InputProcessor public class InputDemo extends ApplicationAdapter implements InputProcessor {

@Overridepublic void create () {

Gdx.input.setInputProcessor(this);}

@Overridepublic void render () {}

@Overridepublic boolean keyDown(int keycode) {

return false;}

@Overridepublic boolean keyUp(int keycode) {

return false;}

...  

Using  InputAdapter  and  Inner  Class  public class InputDemo extends ApplicationAdapter {

@Override

public void create () {Gdx.input.setInputProcessor(new Listener());

}

private class Listener extends InputAdapter {@Override

public boolean touchDragged(int screenX, int screenY, int pointer) {// implementation herereturn true;

}}

}

GESTURES  

GestureDetector  •  TouchDown  

–  User  touches  screen  •  LongPress  

–  User  touches  screen  for  some  8me  •  Tap  

–  User  touches  screen  and  liVs  the  finger  again  •  Pan  

–  User  drags  a  finger  across  the  screen.  Useful  for  implemenIng  Camera  panning  in  2D  •  PanStop  

–  Called  when  no  longer  panning  •  Fling  

–  User  dragged  a  finger  across  the  screen,  then  liVed  up.  Useful  for  swipe  gestures  •  Zoom  

–  User  places  two  fingers  on  the  screen  and  moves  them  together/apart.  Useful  for  Camera  zooming  

•  Pinch  –  Zooming  +  rota8on  

Star8ng  to  Listen  to  Gestures  

•  Really  easy  –  Gdx.input.setInputProcessor(new GestureDetector(GestureListener));

•  GestureListener  is  an  interface  •  GestureAdapter  also  available    

GestureListener  public class MyGestureListener implements GestureListener {

@Override public boolean touchDown(float x, float y, int pointer, int button) {}

@Override public boolean tap(float x, float y, int count, int button) {}

@Override public boolean longPress(float x, float y) {}

@Override public boolean fling(float velocityX, float velocityY, int button) {}

@Override public boolean pan(float x, float y, float deltaX, float deltaY) {}

@Override public boolean panStop(float x, float y, int pointer, int button) {}

@Override public boolean zoom (float originalDistance, float currentDistance){}

@Override public boolean pinch (Vector2 initialFirstPointer, Vector2 initialSecondPointer, Vector2 firstPointer, Vector2 secondPointer){}}

ACCELEROMETER  

Accelerometer  •  An  accelerometer  

measures  the  accelera8on  of  a  device  on  three  axes  

•  From  this  accelera8on  one  can  derive  the  8lt  or  orienta8on  of  the  device.  –  Phones:  portrait  default  –  Tablet:  landscape  default  

•  LibGDX  shows  accelerometer  readings  always  as  in  the  image  

(0,0)  

Accelerometer  x  

Accelerometer  y  

y  increments  

x  increments  

Accelerometer  Readings  

•  Accelerometer  readings  can  be  accessed    –  float accelX = Gdx.input.getAccelerometerX(); –  float accelY = Gdx.input.getAccelerometerY(); –  float accelZ = Gdx.input.getAccelerometerZ();

•  When  moving  and  if  in  landscape  mode  in  android,  no8ce  X  vs  Y!  –  speedX += Gdx.input.getAccelerometerY();

SIMPLE  TEXT  INPUT  

User  input  

•  Desktop  – Swing  dialog  

•  Android  – Android  dialog  

•  Use  TextInputListener

public class InputDemo extends ApplicationAdapter {

@Overridepublic void create () {

MyTextInputListener listener = new MyTextInputListener();Gdx.input.setInputProcessor(new GestureDetector(new GestureDetector.GestureAdapter() {

@Override

public boolean tap(float x, float y, int count, int button) {Gdx.input.getTextInput(new MyTextInputListener(), "title", "test", "hint");return true;

}

}));}

private class MyTextInputListener implements Input.TextInputListener {@Overridepublic void input (String text) {

Gdx.app.log("InputDemo", text);

}

@Overridepublic void canceled () {

Gdx.app.log("InputDemo", "canceled");

}

}}

SPRITE  

Game  Object  •  Game  object  may  hold  informa8on  about  –  Texture  – Geometry  

•  width  •  height  •  x,  y  

–  Color  •  You  could  create  a  class  for  your  game  object  that  capsulates  all  of  these  

•  But  even  beaer,  libGDX  has  already  this  class,  it's  called  Sprite

Sprite  -­‐  class  

•  Holds  geometry,  color  and  texture  informa8on  

•  Has  a  posi8on  and  a  size  given  as  width  and  height  

•  Sprite  is  always  rectangular  •  Sprite  has  also  origin  for  rota8on  and  scaling  – origin  is  in  boaom  leV  

Crea8ng  a  Sprite

public class SpriteDemo extends ApplicationAdapter {

private Sprite player;private Texture alienTexture;

private OrthographicCamera camera;

private SpriteBatch batch;

public final static float WIDTH = 1280;public final static float HEIGHT = 720;

@Overridepublic void create () {

player = new Sprite( alienTexture = new Texture("alien-displeased-icon.png") );camera = new OrthographicCamera();camera.setToOrtho(false, WIDTH, HEIGHT);

batch = new SpriteBatch();}

@Overridepublic void render() {

batch.setProjectionMatrix(camera.combined);

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();

player.draw(batch);

batch.end();}

@Overridepublic void dispose() {

alienTexture.dispose();}

}  

FRAME  ANIMATION  

Anima8on  

•  Use  Anima8on  class  – Animation walkAnimation = new Animation(frameDuration, frames);

•  Frame  dura8on?  Time  between  frames  in  seconds:  1  /  60  fps  

•  Frames?  – TextureRegion  array  

•  TextureRegion?  – Part  of  texture

TextureRegion  

Split  .png  into  TextureRegions  walkSheet = new Texture(Gdx.files.internal(”image.png"));// Method for splitting one texture to TextureRegionsTextureRegion[][] tmp = TextureRegion.split( walkSheet, walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight() / FRAME_ROWS );

2D  array  -­‐>  1D  private TextureRegion[] transformTo1D(TextureRegion[][] tmp) {

TextureRegion [] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];

int index = 0;for (int i = 0; i < FRAME_ROWS; i++) {

for (int j = 0; j < FRAME_COLS; j++) { walkFrames[index++] = tmp[i][j]; } }

return walkFrames;}

Split  .png  into  TextureRegions  walkSheet = new Texture(Gdx.files.internal(”image.png"));// Method for splitting one texture to TextureRegionsTextureRegion[][] tmp = TextureRegion.split( walkSheet, walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight() / FRAME_ROWS );

TextureRegion [] frames = transformTo1D(tmp);

Animation walkAnimation = new Animation(1 / 60f, frames);

Rendering  float stateTime = 1.0f; TextureRegion currentFrame; public void render() { // stateTime was initialized to 0.0f stateTime += Gdx.graphics.getDeltaTime(); // stateTime is used to calculate the next frame // frameDuration! // true = it's a looping anim // false = it's not a looping anim currentFrame = walkAnimation.getKeyFrame(stateTime, true); spriteBatch.begin(); spriteBatch.draw(currentFrame, 150, 150); spriteBatch.end(); }

TIPS  

Crea8ng  Game  Objects  

•  For  each  Game  Object,  create  own  class  •  The  class  may  have  –  Inheritance  relaIonship  with  Sprite  /  Texture  (is  –  a)  or  

– ComposiIon  relaIonship  with  Sprite  /  Texture  (has  –  a)  

•  Add  aaributes  like  – speedX,  speedY,  sounds,  anima8ons  

•  See  example  from  course  homepage!