Post on 15-Jul-2015
libGDX: User Input and Frame by Frame Anima8on
Jussi Pohjolainen Tampere University of Applied Sciences
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.
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;
}}
}
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 • 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
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();
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");
}
}}
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
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();}
}
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
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(); }