Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LibGDX: User Input and Frame by Frame Animation

LibGDX: User Input and Frame by Frame Animation

Avatar for Jussi Pohjolainen

Jussi Pohjolainen

January 22, 2016
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. 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 • Notify when mouse was clicked • Mouse / touch / keyboard can be received either in 1) polling or 2) event handling
  2. Polling Touch / Keyboard • For most arcade games, polling

    is good • Multitouch 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);
  3. Event: 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.
  4. Using InputProcessor public class InputDemo extends ApplicationAdapter implements InputProcessor {

    @Override public void create () { Gdx.input.setInputProcessor(this); } @Override public void render () { } @Override public boolean keyDown(int keycode) { return false; } @Override public boolean keyUp(int keycode) { return false; } ...
  5. 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 here return true; } } }
  6. GestureDetector • TouchDown – User touches screen • LongPress –

    User touches screen for some time • Tap – User touches screen and lifts the finger again • Pan – User drags a finger across the screen. Useful for implementing Camera panning in 2D • PanStop – Called when no longer panning • Fling – User dragged a finger across the screen, then lifted up. Useful for swipe gestures • Zoom – User places two fingers on the screen and moves them together/apart. Useful for Camera zooming • Pinch – Zooming + rotation
  7. Starting to Listen to Gestures • Really easy – Gdx.input.setInputProcessor(new

    GestureDetector(GestureListener)); • GestureListener is an interface • GestureAdapter also available
  8. 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){} }
  9. Accelerometer • An accelerometer measures the acceleration of a device

    on three axes • From this acceleration one can derive the tilt or orientation of the device. – Phones: portrait default – Tablet: landscape default • LibGDX shows accelerometer readings always as in the image
  10. 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, notice X vs Y! – speedX += Gdx.input.getAccelerometerY();
  11. User input • Desktop – Swing dialog • Android –

    Android dialog • Use TextInputListener
  12. public class InputDemo extends ApplicationAdapter { @Override public 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 { @Override public void input (String text) { Gdx.app.log("InputDemo", text); } @Override public void canceled () { Gdx.app.log("InputDemo", "canceled"); } } }
  13. Game Object • Game object may hold information about –

    Texture – Geometry • width • height • x, y – Color • You could create a class for your game object that capsulates all of these • But even better, libGDX has already this class, it's called Sprite
  14. Sprite - class • Holds geometry, color and texture information

    • Has a position and a size given as width and height • Sprite is always rectangular • Sprite has also origin for rotation and scaling – origin is in bottom left
  15. 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; @Override public void create () { player = new Sprite( alienTexture = new Texture("alien-displeased-icon.png") ); camera = new OrthographicCamera(); camera.setToOrtho(false, WIDTH, HEIGHT); batch = new SpriteBatch(); } @Override public 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(); } @Override public void dispose() { alienTexture.dispose(); } }
  16. Animation • Use Animation class – Animation walkAnimation = new

    Animation(frameDuration, frames); • Frame duration? Time between frames in seconds: 1 / 60 fps • Frames? – TextureRegionarray • TextureRegion? – Part of texture
  17. Split .png into TextureRegions walkSheet = new Texture(Gdx.files.internal(”image.png")); // Method

    for splitting one texture to TextureRegions TextureRegion[][] tmp = TextureRegion.split( walkSheet, walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight() / FRAME_ROWS );
  18. 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; }
  19. Split .png into TextureRegions walkSheet = new Texture(Gdx.files.internal(”image.png")); // Method

    for splitting one texture to TextureRegions TextureRegion[][] tmp = TextureRegion.split( walkSheet, walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight() / FRAME_ROWS ); TextureRegion [] frames = transformTo1D(tmp); Animation walkAnimation = new Animation(1 / 60f, frames);
  20. 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(); }
  21. Creating Game Objects • For each Game Object, create own

    class • The class may have – Inheritance relationship with Sprite / Texture(is – a) or – Composition relationship with Sprite / Texture (has – a) • Add attributes like – speedX, speedY, sounds, animations • See example from course homepage!