package net.alcuria.umbracraft.engine.components;
import net.alcuria.gen.R;
import net.alcuria.umbracraft.Config;
import net.alcuria.umbracraft.Game;
import net.alcuria.umbracraft.engine.Pathfinder;
import net.alcuria.umbracraft.engine.Pathfinder.PathNode;
import net.alcuria.umbracraft.engine.components.AnimationGroupComponent.Direction;
import net.alcuria.umbracraft.engine.entities.Entity;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
/** A component for handling input directed by some other component (for
* instance, a {@link ScriptComponent}.
* @author Andrew Keturi */
public class DirectedInputComponent implements Component {
private static final float TOLERANCE = 0.4f;
private boolean choseNextNode;
private final Texture debug;
private Direction direction;
private Entity entity;
private final Vector3 lastPosition = new Vector3();
private final Pathfinder pathfinder;
private float targetX, targetY, currentX, currentY;
public DirectedInputComponent() {
pathfinder = new Pathfinder(this);
debug = Game.assets().get(R.debug, Texture.class);
}
@Override
public void create(Entity entity) {
this.entity = entity;
}
@Override
public void dispose(Entity entity) {
}
public boolean hasNoMoves() {
return pathfinder.getSolution().size == 0;
}
@Override
public void render(Entity entity) {
if (Game.isDebug()) {
Color oldColor = Game.batch().getColor();
Game.batch().setColor(Color.RED);
Game.batch().draw(debug, targetX * 16 - 1, targetY * 16 - 1, 3, 3);
Game.batch().setColor(Color.BLUE);
Game.batch().draw(debug, currentX * 16 - 1, currentY * 16 - 1, 3, 3);
Game.batch().setColor(oldColor);
}
}
public void renderPaths() {
pathfinder.renderPaths();
}
public void resetTarget(int i, int j) {
pathfinder.stop();
targetX = i + 0.5f;
targetY = j + 0.5f;
}
/** Sets the target to walk to
* @param x
* @param y */
public void setTarget(int x, int y) {
pathfinder.setTarget(new PathNode((int) (entity.position.x / Config.tileWidth), (int) (entity.position.y / Config.tileWidth)), new PathNode(x, y));
}
@Override
public void update(Entity entity) {
currentX = (entity.position.x / Config.tileWidth);
currentY = (entity.position.y / Config.tileWidth);
// see if we're stuck, if so try rejiggering the pathfinder
if (((entity.position.epsilonEquals(lastPosition, 0.01f) && (targetX != currentX || targetY != currentY)))) {
// setTarget(targetX, targetY); //FIXME: too many crazy npe's
// Game.log("STUCK " + targetX + " " + targetY);
// lastPosition.set(entity.position);
}
pathfinder.update(entity);
// see if we really need to move
if (pathfinder.getSolution().size <= 0) {
entity.velocity.x *= 0.7;
entity.velocity.y *= 0.7;
if (entity.velocity.epsilonEquals(Vector3.Zero, 0.1f)) {
entity.velocity.x = 0;
entity.velocity.y = 0;
}
return;
}
if (!choseNextNode) {
final PathNode lastNode = pathfinder.getSolution().get(pathfinder.getSolution().size - 1);
targetX = lastNode.x + 0.5f;
targetY = lastNode.y + 0.5f;
choseNextNode = true;
}
if (MathUtils.isEqual(targetX, currentX, 0.5f) && MathUtils.isEqual(targetY, currentY, 0.5f) && pathfinder.getSolution().size > 0) {
choseNextNode = false;
pathfinder.getSolution().removeIndex(pathfinder.getSolution().size - 1);
return;
}
// pick a new direction
float dX = Math.abs(targetX - currentX);
float dY = Math.abs(targetY - currentY);
direction = null;
boolean horizontal = dX > TOLERANCE;
boolean vertical = dY > TOLERANCE;
if (horizontal && !vertical) {
// left / right
if (targetX > currentX) {
direction = Direction.RIGHT;
} else {
direction = Direction.LEFT;
}
} else if (!horizontal && vertical) {
if (targetY > currentY) {
direction = Direction.UP;
} else {
direction = Direction.DOWN;
}
} else if (horizontal && vertical) {
if (targetY > currentY) {
if (targetX > currentX) {
direction = Direction.UPRIGHT;
} else {
direction = Direction.UPLEFT;
}
} else {
if (targetX > currentX) {
direction = Direction.DOWNRIGHT;
} else {
direction = Direction.DOWNLEFT;
}
}
}
if (direction == null) {
return;
}
lastPosition.set(entity.position);
// update velocity
switch (direction) {
case DOWN:
entity.velocity.y = -2;
entity.velocity.x = 0;
break;
case DOWNLEFT:
entity.velocity.x = -2 * 0.707f;
entity.velocity.y = -2 * 0.707f;
break;
case DOWNRIGHT:
entity.velocity.x = 2 * 0.707f;
entity.velocity.y = -2 * 0.707f;
break;
case LEFT:
entity.velocity.x = -2;
entity.velocity.y = 0;
break;
case RIGHT:
entity.velocity.x = 2;
entity.velocity.y = 0;
break;
case UP:
entity.velocity.y = 2;
entity.velocity.x = 0;
break;
case UPLEFT:
entity.velocity.x = -2 * 0.707f;
entity.velocity.y = 2 * 0.707f;
break;
case UPRIGHT:
entity.velocity.x = 2 * 0.707f;
entity.velocity.y = 2 * 0.707f;
break;
default:
break;
}
entity.velocity.x *= (entity.speedModifier);
entity.velocity.y *= (entity.speedModifier);
}
}