Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

TOUCH + KEYBOARD

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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.

Slide 6

Slide 6 text

InputProcessor - methods

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

GESTURES

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

Starting to Listen to Gestures • Really easy – Gdx.input.setInputProcessor(new GestureDetector(GestureListener)); • GestureListener is an interface • GestureAdapter also available

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

ACCELEROMETER

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

(0,0) Accelerometer x Accelerometer y y increments x increments

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

SIMPLE TEXT INPUT

Slide 18

Slide 18 text

User input • Desktop – Swing dialog • Android – Android dialog • Use TextInputListener

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

SPRITE

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

Creating a Sprite

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

FRAME ANIMATION

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

TextureRegion

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

TIPS

Slide 33

Slide 33 text

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!