Rogue: Savage Rats, a retro-themed dungeon crawler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
rogue-savage-rats/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java

297 lines
4.9 KiB

package mightypork.rogue.world.entity.modules;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityModule;
import mightypork.utils.ion.IonDataBundle;
import mightypork.utils.math.algo.Coord;
import mightypork.utils.math.algo.Move;
import mightypork.utils.math.constraints.vect.VectConst;
public class EntityModulePosition extends EntityModule {
/** Last pos, will be freed upon finishing move */
private Coord lastPos = new Coord(0, 0);
private boolean walking = false;
private final Queue<Move> path = new LinkedList<>();
private final EntityPos entityPos = new EntityPos();
private double stepTime = 0.5;
// marks for simple renderers
public int lastXDir = 1;
public int lastYDir = 1;
private final Set<EntityMoveListener> moveListeners = new LinkedHashSet<>();
public EntityModulePosition(Entity entity)
{
super(entity);
}
@Override
public void save(IonDataBundle bundle)
{
bundle.putSequence("path", path);
bundle.put("lpos", lastPos);
bundle.putBundled("pos", entityPos);
bundle.put("step_time", stepTime);
}
@Override
public void load(IonDataBundle bundle)
{
bundle.loadSequence("path", path);
lastPos = bundle.get("lpos", lastPos);
bundle.loadBundled("pos", entityPos);
stepTime = bundle.get("step_time", stepTime);
}
@Override
public boolean isModuleSaved()
{
return true;
}
/**
* Set coord without animation
*
* @param coord coord
*/
public void setCoord(Coord coord)
{
freeTile(); // release old tile
entityPos.setTo(coord);
lastPos.setTo(coord);
cancelPath(); // discard remaining steps
occupyTile();
}
/**
* Occupy current tile in level
*/
public void occupyTile()
{
if (entity.getLevel() != null) {
entity.getLevel().occupyTile(getCoord());
}
}
/**
* free current tile in level
*/
public void freeTile()
{
if (entity.getLevel() != null) {
entity.getLevel().freeTile(getCoord());
}
}
/**
* @param delta delta time
*/
@Override
public void update(double delta)
{
if (entity.isDead()) return; // corpses dont walk
if (!entityPos.isFinished()) {
entityPos.update(delta);
}
if (walking && entityPos.isFinished()) {
walking = false;
for (final EntityMoveListener l : moveListeners) {
l.onStepFinished();
}
if (path.isEmpty()) {
for (final EntityMoveListener l : moveListeners) {
l.onPathFinished();
}
}
}
if (!walking && !path.isEmpty()) {
walking = true;
final Move step = path.poll();
final Coord planned = entityPos.getCoord().add(step.toCoord());
if (!entity.getLevel().isWalkable(planned)) {
cancelPath();
for (final EntityMoveListener l : moveListeners) {
l.onPathInterrupted();
}
walking = false;
} else {
// tmp for renderer
if (step.x() != 0) this.lastXDir = step.x();
if (step.y() != 0) this.lastYDir = step.y();
freeTile();
lastPos.setTo(entityPos.getCoord());
entityPos.walk(step, stepTime);
occupyTile();
}
}
}
/**
* @return true if path buffer is empty
*/
public boolean isPathFinished()
{
return entityPos.isFinished() && path.isEmpty();
}
/**
* Add a step to path buffer
*
* @param step
*/
public void addStep(Move step)
{
if (path.isEmpty() && !canGoTo(step)) return;
path.add(step);
}
/**
* Discard steps in buffer
*/
public void cancelPath()
{
path.clear();
}
/**
* Find path to
*
* @param target
* @return path found
*/
public boolean navigateTo(Coord target)
{
if (target.equals(getCoord())) return true;
final List<Move> newPath = entity.getPathFinder().findPathRelative(entityPos.getCoord(), target);
if (newPath == null) return false;
cancelPath();
addSteps(newPath);
return true;
}
/**
* Add a move listener. If already present, do nothing.
*
* @param listener the listener
*/
public void addMoveListener(EntityMoveListener listener)
{
moveListeners.add(listener);
}
/**
* Add steps to path buffer
*
* @param path steps
*/
public void addSteps(List<Move> path)
{
this.path.addAll(path);
}
/**
* @return coord in level
*/
public Coord getCoord()
{
return entityPos.getCoord();
}
/**
* Set step time (seconds)
*
* @param stepTime step time
*/
public void setStepTime(double stepTime)
{
this.stepTime = stepTime;
}
/**
* @return step progress 0..1
*/
public double getProgress()
{
return entityPos.getProgress();
}
/**
* @return visual pos in level; interpolated from last to new coord
*/
public VectConst getVisualPos()
{
return entityPos.getVisualPos();
}
public boolean isMoving()
{
return walking;
}
public boolean hasPath()
{
return isMoving() || !path.isEmpty();
}
public boolean canGoTo(Move side)
{
return entity.getPathFinder().isAccessible(getCoord().add(side));
}
public Coord getLastPos()
{
return lastPos;
}
}