📄 pathfollower.java
字号:
/*
* Light And Shadow. A Persistent Universe based on Robert Jordan's Wheel of Time Books.
* Copyright (C) 2001-2003 WOTLAS Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package wotlas.common.movement;
import wotlas.libs.pathfinding.*;
import wotlas.common.*;
import wotlas.common.message.movement.*;
import wotlas.common.universe.*;
import wotlas.utils.*;
import wotlas.libs.persistence.*;
import wotlas.common.screenobject.*;
import java.awt.Point;
/**
* A path follower... well yes, this class is a path adept :) It follows a given path
* at a certain speed taking into account angle variations...
*
* IMPORTANT : this implementation is NOT synchronized... please avoid the situation
* when one thread is invoking the tick() method and the other a setXXX()...
*
* @author Petrus, Aldiss, Diego
*/
public class PathFollower implements MovementComposer,BackupReady {
/** id used in Serialized interface.
*/
private static final long serialVersionUID = 556565L;
/*------------------------------------------------------------------------------------*/
/** Distance in pixels before we consider the slave replica too far from its
* master replica : we then make slave replica jump to its final position.
*/
public final static int MAX_DISTANCE_DELAY = 200;
/*------------------------------------------------------------------------------------*/
/** To tell that we must reconstruct a trajectory that was not possible
* to construct before, due to a AStar not initialized...
*/
transient private boolean reconstructTrajectory = false;
/** Saved DeltaTime for trajectory reconstruction.
*/
transient private int movementDeltaTime;
/*------------------------------------------------------------------------------------*/
// PATH FIELDS
/** Player's trajectory
*/
transient private List path;
/** Our current index in the Path ( next point we target )
*/
transient private int pathIndex;
/** Previous point in path.
*/
transient private Point prevPoint;
/** Next point in path.
*/
transient private Point nextPoint;
/** End point of the path (for persistence only).
*/
private ScreenPoint endPoint;
/** Next Angle in the path.
*/
transient private float nextAngle;
/** what's our current movement ? walking ? turning ? do we have to provide
* realistic rotations ?
*/
private boolean walkingAlongPath;
transient private boolean turningAlongPath;
transient private boolean realisticRotations;
/** Last update time.
*/
transient private long lastUpdateTime;
/*------------------------------------------------------------------------------------*/
// KINEMATIC FIELDS
/** Current position
*/
private float xPosition;
private float yPosition;
/** Current Orientation (our angle in rads)
*/
private double orientationAngle;
/** PathFollower speed in pixel/s ( default 60 pixel/s )
*/
transient private float speed = 60;
/** PathFollower angular speed in radian/s ( default 3 rad/s )
*/
transient private float angularSpeed = 3;
/** in which angular direction are we turning ? +1 for positive direction, -1 otherwise.
*/
transient private byte angularDirection;
/** Time when we initialized the last movement.
*/
private long movementTimeStamp;
/*------------------------------------------------------------------------------------*/
/** Do we have to set a special orientation of the player at the end of his movement.
* This field is useful when recreating a trajectory : we don't want the final
* orientation of the player to differ from the original replica.
*/
transient private boolean useEndingOrientationValue;
/** The ending orientation for the slave replica of the player.
*/
transient private double endingOrientation;
/** Asociated Player.
*/
transient private Player player;
/*------------------------------------------------------------------------------------*/
/** To init the MovementComposer classes with the ground's mask.
* @param mask two dimension mask representing the zones where the players can go.
* @param maskTileSize mask tile size (in pixels).
* @param playerSize represents the average player size ( in maskTileSize unit )
*/
public void setMovementMask( boolean mask[][], int maskTileSize, int playerSize ) {
AStarDouble.setMask( mask );
AStarDouble.setTileSize( maskTileSize );
AStarDouble.setSpriteSize( playerSize );
}
/*------------------------------------------------------------------------------------*/
/** To get a path between two points via Astar.
* @param a first point
* @param b second point
* @return path
*/
public static List findPath( Point a, Point b, boolean pathInRoom ) {
int tileSize = AStarDouble.getTileSize();
List path = AStarDouble.findPath( new Point( a.x/tileSize, a.y/tileSize ),
new Point( b.x/tileSize, b.y/tileSize ) );
path = AStarDouble.smoothPath(path);
if( path==null || path.size()<2 )
return null; // no movement
if(path!=null)
for (int i=0; i<path.size(); i++) {
Point p = (Point) path.elementAt(i);
if(pathInRoom && i!=path.size()-1) {
p.x = p.x*tileSize-5;
p.y = p.y*tileSize-5;
}
else {
p.x *= tileSize;
p.y *= tileSize;
}
}
return path;
}
/*------------------------------------------------------------------------------------*/
/** Empty Constructor.
*/
public PathFollower() {
walkingAlongPath = false;
turningAlongPath = false;
realisticRotations = false;
useEndingOrientationValue = false;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Constructor with initial position & orientation
*
* @param xPosition x position in pixels.
* @param yPosition y position in pixels.
* @param orientationAngle orientation angle in radians.
*/
public PathFollower( float xPosition, float yPosition, double orientationAngle ) {
this();
this.xPosition = xPosition;
this.yPosition = yPosition;
this.orientationAngle = orientationAngle;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To init this MovementComposer.
* @param player associated player.
*/
public void init(Player player) {
this.player = player;
}
public void init(ScreenObject screenObject) {
Debug.signal( Debug.ERROR, null, "This should never be called : init with ScreenObject on PathFollower!" );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
// KINEMATIC GETTERS & SETTERS
/** To get the X position.
* @return x position
*/
public float getXPosition() {
return xPosition;
}
/** To set the X Position.
* @param x x cordinate
*/
public void setXPosition( float xPosition ){
this.xPosition = xPosition;
}
/** To get the Y position.
* @return y position
*/
public float getYPosition() {
return yPosition;
}
/** To set the Y Position.
* @param y y cordinate
*/
public void setYPosition( float yPosition ){
this.yPosition = yPosition;
}
/** To get the orientation angle.
* @return angle in radians.
*/
public double getOrientationAngle() {
return orientationAngle;
}
/** To set the orientation angle.
* @param orientationAngle angle in radians.
*/
public void setOrientationAngle(double orientationAngle) {
this.orientationAngle = orientationAngle;
}
/** To set player's speed
*/
public void setSpeed(float speed) {
this.speed = speed;
}
/** To get player's speed
*/
public float getSpeed() {
return speed;
}
/** To set player's angular speed
*/
public void setAngularSpeed(float angularSpeed) {
this.angularSpeed = angularSpeed;
}
/** To get player's angular speed
*/
public float getAngularSpeed() {
return angularSpeed;
}
/** To set if the player is walking along the path
*/
public void setWalkingAlongPath(boolean walkingAlongPath) {
this.walkingAlongPath = walkingAlongPath;
}
/** is the player moving ( same as isMoving(), this method is for persistence only )
*/
public boolean getWalkingAlongPath() {
return walkingAlongPath;
}
/** To set the player end position ( for persistence only )
*/
public void setEndPoint(ScreenPoint endPoint) {
this.endPoint= endPoint;
}
/** To get the end position of the current movement ( for persistence only, prefer
* getTargetPosition() )
*/
public ScreenPoint getEndPoint() {
return endPoint;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -