package net.alcuria.umbracraft.engine.components;
import net.alcuria.umbracraft.Game;
import net.alcuria.umbracraft.engine.components.AnimationGroupComponent.Direction;
import net.alcuria.umbracraft.engine.entities.Entity;
import net.alcuria.umbracraft.engine.events.Event;
import net.alcuria.umbracraft.engine.events.EventListener;
import net.alcuria.umbracraft.engine.events.KeyDownEvent;
import net.alcuria.umbracraft.engine.events.TouchpadCreatedEvent;
import net.alcuria.umbracraft.engine.manager.input.InputHalter;
import net.alcuria.umbracraft.save.model.SaveProfile;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
/** A component specifically for handling object input from the player.
* @author Andrew Keturi */
public class ControlledInputComponent implements Component, EventListener {
private static final float KNOB_TOLERANCE = 0.45f;
private static final int MARGIN = 6;
private static final float MAX_SPEED = 2; // max speed of the entity
private static final float MAX_SPEED_TIME = 0.12f; // time entity takes to reach max speed
private static Touchpad touchpad; // this fixes issues with changing maps/recreating entities and it's a bit ugly but...?
private Entity entity;
private AnimationCollectionComponent group;
private InputHalter halter;
private float holdTimeX, holdTimeY;
private final Vector3 inspectPos = new Vector3();
private MapCollisionComponent physics;
private boolean subscribed;
@Override
public void create(Entity entity) {
if (subscribed) {
return;
}
this.entity = entity;
halter = new InputHalter();
Game.log("ControlledInput: SUBSCRIBING");
Game.publisher().subscribe(this);
subscribed = true;
}
@Override
public void dispose(Entity entity) {
Game.log("ControlledInput: UNSUBSCRIBING");
Game.publisher().unsubscribe(this);
subscribed = false;
}
public void inspect() {
if (halter.isHalted()) {
return;
}
physics = entity.getComponent(MapCollisionComponent.class);
group = entity.getComponent(AnimationCollectionComponent.class);
if (physics != null && group != null) {
inspectPos.x = entity.position.x;// + physics.getWidth() / 2;
inspectPos.y = entity.position.y;// + physics.getHeight() / 2;
inspectPos.z = entity.position.z;
final Direction d = group.getGroup().getDirection();
if (d == Direction.UPRIGHT || d == Direction.RIGHT || d == Direction.DOWNRIGHT) {
inspectPos.x += physics.getWidth() / 2 + MARGIN;
}
if (d == Direction.UPLEFT || d == Direction.LEFT || d == Direction.DOWNLEFT) {
inspectPos.x -= physics.getWidth() / 2 + MARGIN;
}
if (d == Direction.UPLEFT || d == Direction.UP || d == Direction.UPRIGHT) {
inspectPos.y += physics.getHeight() / 2 + MARGIN;
}
if (d == Direction.DOWNLEFT || d == Direction.DOWN || d == Direction.DOWNRIGHT) {
inspectPos.y -= physics.getHeight() / 2 + MARGIN;
}
Game.log("Pressed Enter, publishing KeyDownEvent");
Game.publisher().publish(new KeyDownEvent(Keys.ENTER, inspectPos));
}
}
@Override
public void onEvent(Event event) {
if (event instanceof TouchpadCreatedEvent) {
touchpad = ((TouchpadCreatedEvent) event).touchpad;
Game.log("Set touchpad");
} else {
halter.check(event);
}
}
@Override
public void render(Entity entity) {
if (Game.isDebug()) {
Game.batch().draw(Game.assets().get("debug.png", Texture.class), inspectPos.x, inspectPos.y, 1, 1);
}
}
@Override
public void update(Entity entity) {
if (halter.isHalted()) {
return;
}
// check which keys are pressed and update velocity accordingly
boolean pressingXKey = false;
boolean pressingYKey = false;
// check for touchpad input or keyboard input
if (touchpad != null && touchpad.isTouched()) {
//Game.log(touchpad.getKnobPercentX() + " " + touchpad.getKnobPercentY());
entity.velocity.x = touchpad.getKnobPercentX() > KNOB_TOLERANCE ? MAX_SPEED : (touchpad.getKnobPercentX() < -KNOB_TOLERANCE ? -MAX_SPEED : 0);
entity.velocity.y = touchpad.getKnobPercentY() > KNOB_TOLERANCE ? MAX_SPEED : (touchpad.getKnobPercentY() < -KNOB_TOLERANCE ? -MAX_SPEED : 0);
pressingXKey = Math.abs(entity.velocity.x) > MAX_SPEED / 4;
pressingYKey = Math.abs(entity.velocity.y) > MAX_SPEED / 4;
//Game.log(Math.abs(entity.velocity.x) + " " + pressingXKey + " " + pressingYKey);
if (pressingXKey && pressingYKey) {
entity.velocity.x *= 0.707f;
entity.velocity.y *= 0.707f;
}
} else {
if (Gdx.input.isKeyPressed(Keys.W)) {
entity.velocity.y = MAX_SPEED;
if (Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.D)) {
entity.velocity.y *= 0.707f;
}
pressingYKey = true;
}
if (Gdx.input.isKeyPressed(Keys.A)) {
entity.velocity.x = -MAX_SPEED;
if (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.S)) {
entity.velocity.x *= 0.707f;
}
pressingXKey = true;
}
if (Gdx.input.isKeyPressed(Keys.S)) {
entity.velocity.y = -MAX_SPEED;
if (Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.D)) {
entity.velocity.y *= 0.707f;
}
pressingYKey = true;
}
if (Gdx.input.isKeyPressed(Keys.D)) {
entity.velocity.x = MAX_SPEED;
if (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.S)) {
entity.velocity.x *= 0.707f;
}
pressingXKey = true;
}
// apply any interpolation to the velocity
holdTimeX += pressingXKey ? Gdx.graphics.getDeltaTime() : -Gdx.graphics.getDeltaTime();
holdTimeX = MathUtils.clamp(holdTimeX, 0, MAX_SPEED_TIME);
holdTimeY += pressingYKey ? Gdx.graphics.getDeltaTime() : -Gdx.graphics.getDeltaTime();
holdTimeY = MathUtils.clamp(holdTimeY, 0, MAX_SPEED_TIME);
entity.velocity.x *= holdTimeX / MAX_SPEED_TIME;
entity.velocity.y *= holdTimeY / MAX_SPEED_TIME;
entity.velocity.x *= (entity.speedModifier);
entity.velocity.y *= (entity.speedModifier);
}
if (Gdx.input.isKeyJustPressed(Keys.F1)) {
Game.setDebug(!Game.isDebug());
}
if (Gdx.input.isKeyJustPressed(Keys.F2)) {
SaveProfile.toGame(Game.save().getProfiles().get(0));
}
if (Gdx.input.isKeyJustPressed(Keys.ENTER)) {
inspect();
}
}
}