I've looked into numerous different ways to process input for android but I really can't get my head around it. I'm wondering with the code I provide you, could someone explain to me how I can integrate either approach into my code? and why it is appropriate to do so?
Firstly, I'll explain what my intentions are and show you a quick overview of the relevant code. I'm wanting to move my character, left, right and jump (for the time being). This is my first game, it's a portrait (somewhat similar context as Doodle Jump in regards to rendering) game without the automatic jumping. I'm got my level generated randomly, it renders all objects. Now I want to add input, but the main confusion is for me where do I put the code in my code?
Firstly, I have a GameObject
class and a sub class DynamicGameObject
, this is the super
class for all objects inside the world (platforms, powerups, coins, player, enemies etc)
GameObject.java
public class GameObject {
public final Vector2 position;
public final Rectangle bounds;
public GameObject (float x, float y, float width, float height) {
this.position = new Vector2(x, y);
this.bounds = new Rectangle(x - width / 2, y - height / 2, width, height);
}
DynamicGameObject.java
public class DynamicGameObject extends GameObject {
protected static Vector2 velocity;
public final Vector2 accel;
public DynamicGameObject (float x, float y, float width, float height) {
super(x, y, width, height);
setVelocity(new Vector2());
accel = new Vector2();
}
public Vector2 getVelocity() {
return velocity;
}
public void setVelocity(Vector2 velocity) {
DynamicGameObject.velocity = velocity;
}
}
And then I have the main game object in which will be moving upon the actions I'll implement. In this class would I be putting any input processing?
Ruben. java [relevant code]
public Ruben (float x, float y) {
super(x, y, RUBEN_WIDTH, RUBEN_HEIGHT);
state = RUBEN_STATE_IDLE;
stateTime = 0;
grounded = true;
facingRight = true;
}
public void update (float deltaTime) {
//getVelocity().add(World.gravity.x * deltaTime, World.gravity.y * deltaTime);
position.add(velocity.x * deltaTime, velocity.y * deltaTime);
bounds.x = position.x - bounds.width / 2;
bounds.y = position.y - bounds.height / 2;
if (position.x < 0) position.x = World.WORLD_WIDTH;
if (position.x > World.WORLD_WIDTH) position.x = 0;
stateTime += deltaTime;
}
Then I have the world class that will update everything inside the game, The relevant update method will be where ruben gets updated, shown here:
private void updateRuben (float deltaTime, float accelX) {
if (ruben.getState() != Ruben.RUBEN_STATE_IDLE && ruben.position.y <= 0.5f) ruben.hitPlatform();
if (ruben.getState() != Ruben.RUBEN_STATE_IDLE) ruben.getVelocity().x = -accelX / 10 * Ruben.RUBEN_MOVE_VELOCITY;
// clamp the velocity to the maximum, x-axis only
if (Math.abs(ruben.getVelocity().x) > Ruben.RUBEN_MAX_VELOCITY) {
ruben.getVelocity().x = Math.signum(ruben.getVelocity().x) * Ruben.RUBEN_MAX_VELOCITY;
}
// clamp the velocity to 0 if it's < 1, and set the state to standing
if (Math.abs(ruben.getVelocity().x) < 1) {
ruben.getVelocity().x = 0;
if (Ruben.isGrounded()) {
Ruben.setState(Ruben.RUBEN_STATE_IDLE);
}
}
ruben.getVelocity().scl(deltaTime);
ruben.update(deltaTime);
heightSoFar = Math.max(ruben.position.y, heightSoFar);
}
So Now i'm hoping you get the general context of the actor i'm dealing with, where would I go about putting a gesture listener callback? Do I put it into ruben? or do I create a seperate class altogether? I've tried out so many different ways and I'm not really getting anywhere it's abit frustrating. Where does the input handler go for the gestures? I tried putting the callback for a gesture detector with a new gesture listener inside the constructor of Ruben
(GestureDetector gd = new GestureDetector(new GestureHandler(this));
and then using a variable to indicate a fling has been directed upwards on the screen, when the boolean trigger is true, set the state of ruben to jump and change the velocity on y axis. It still didn't work. Can someone help?
if you need anything else, let me know.
Main game class
public class GameView extends Game {
// used by all screens
public SpriteBatch batcher;
@Override
public void create () {
batcher = new SpriteBatch();
Settings.load();
Assets.loadBackgrounds();
Assets.loadItems();
Assets.loadRuben();
setScreen(new MainMenuScreen(this));
}
@Override
public void render() {
super.render();
}
}
If you want to use an InputAdapter
like the GestureDetector
in libGdx you must set it, don't know if you do so, else there won't be any method called from the GestureDetector
. Hope that's the main problem. GestureDetector LibGdx Wiki
Gdx.input.setInputProcessor(new GestureDetector(new GestureHandler(this)));
Also if you want to use multiple InputAdapter you have to use an InputMultiplexer
especially if you also want to use a Stage for GUI things. Event Handling LibGdx Wiki
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(stage);
inputMultiplexer.addProcessor(new GestureDetector(new GestureHandler(this)));
Gdx.input.setInputProcessor(inputMultiplexer);
EDIT:
My preferred way to implement it with a Screen is MainMenuScreen extends Screen implements GestureDetector.GestureListener
and in the show()
method Gdx.input.setInputProcessor(new GestureDetector(this));
then you have also easy access to the objects you want to control from the methods.