📄 pathfollower.java
字号:
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To set the position from a Point.
* @param p Point
*/
public void setPosition( Point p ) {
xPosition = (float) p.x;
yPosition = (float) p.y;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To get the current position as a Point.
* @return current position
*/
public Point getPosition() {
return new Point( (int)xPosition, (int)yPosition );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To get the target position of the current movement ( last point in the path ).
* @return returns the target position, can be the current position if we are not moving...
*/
public Point getTargetPosition() {
if(path!=null && path.size()>0)
return (Point)path.elementAt( path.size()-1 );
if(endPoint!=null)
return endPoint.toPoint();
return new Point( -100, -100 ); // out of screen point
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Returns true if we are moving
*/
public boolean isMoving() {
return walkingAlongPath;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To reset our movement along the path.
*/
public void resetMovement() {
walkingAlongPath = false;
turningAlongPath = false;
path = null;
nextPoint = null;
prevPoint = null;
endPoint = null;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To stop our movement along the path.
*/
public void stopMovement() {
resetMovement();
if(player.isMaster())
player.sendMessage( new PathUpdateMovementMessage( this, player.getPrimaryKey(), player.getSyncID() ) );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To set if we want realistic rotations or not.
* @param realisticRotations true if you want realistic rotations.
*/
public void setRealisticRotations( boolean realisticRotations ) {
this.realisticRotations = realisticRotations;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To get the movement's timeStamp.
*/
public long getMovementTimeStamp() {
return movementTimeStamp;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To set the movement's timeStamp.
*/
public void setMovementTimeStamp( long movementTimeStamp ) {
this.movementTimeStamp = movementTimeStamp;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To get an update message representing the current movement state.
* IMPORTANT : We don't set any primaryKey.
*
* @return a MovementUpdateMessage
*/
public MovementUpdateMessage getUpdate() {
if(AStarDouble.isInitialized())
return (MovementUpdateMessage) new PathUpdateMovementMessage( this, null, player.getSyncID() );
else
return (MovementUpdateMessage) new PathUpdateMovementMessage( this, player.getPrimaryKey(), player.getSyncID() );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To update the current movement.
* @param updateMessage MovementUpdateMessage
*/
public synchronized void setUpdate( MovementUpdateMessage updateMessage ) {
if( !(updateMessage instanceof PathUpdateMovementMessage) ) {
Debug.signal( Debug.ERROR, this, "Received bad update message :"+updateMessage.getClass());
return;
}
PathUpdateMovementMessage msg = (PathUpdateMovementMessage) updateMessage;
useEndingOrientationValue=false;
/* METHOD 1 : SIMPLE UPDATE : WE FORCE THE NEW POSITION
xPosition = (float)msg.srcPoint.x;
yPosition = (float)msg.srcPoint.y;
orientationAngle = msg.orientationAngle;
walkingAlongPath = msg.isMoving;
if( walkingAlongPath ) {
Point pDst = new Point( msg.dstPoint.x, msg.dstPoint.y );
if (AStarDouble.isInitialized()) {
// Astar initialized, re-creating path
recreateTrajectory( pDst, msg.movementDeltaTime );
}
else {
// Astar not initialized, just saving data
endPoint = new ScreenPoint( pDst );
movementTimeStamp = System.currentTimeMillis();
reconstructTrajectory = true;
movementDeltaTime = msg.movementDeltaTime;
}
}
else {
// No movement
resetMovement();
}
*/
/* METHOD 2 : ADVANCED UPDATE : WE TEST THE NEW POSITION */
if (!AStarDouble.isInitialized()) {
// We just save the data
xPosition = (float)msg.srcPoint.x;
yPosition = (float)msg.srcPoint.y;
orientationAngle = msg.orientationAngle;
walkingAlongPath = msg.isMoving;
if( walkingAlongPath ) {
endPoint = new ScreenPoint( msg.dstPoint.x, msg.dstPoint.y );
movementTimeStamp = System.currentTimeMillis();
reconstructTrajectory = true;
movementDeltaTime = msg.movementDeltaTime;
}
else
resetMovement(); // No movement
}
else
{
// AStar initialized
// Do we have to consider this update ?
boolean takeUpdate = false;
if( walkingAlongPath ) {
Point target = getTargetPosition();
if( msg.isMoving ) {
if( distance( msg.srcPoint, getPosition() )>MAX_DISTANCE_DELAY ||
findPath( getPosition(), msg.dstPoint, player.getLocation().isRoom() )==null )
takeUpdate = true;
else
recreateTrajectory( msg.dstPoint, 0 );
}
else {
// no movement, we received the master replica's ending trajectory position
if( target.x!=msg.srcPoint.x || target.y!=msg.srcPoint.y
|| distance( target, getPosition() )>MAX_DISTANCE_DELAY ) {
takeUpdate = true;
}
else {
// save the final orientation for later
useEndingOrientationValue=true;
endingOrientation = msg.orientationAngle;
}
}
}
else if( !msg.isMoving && Math.abs(xPosition-msg.srcPoint.x)<=1
&& Math.abs(yPosition-msg.srcPoint.y)<=1 ) {
// we turn on ourself
turningAlongPath = true;
useEndingOrientationValue = true;
nextAngle = msg.orientationAngle;
angularDirection = 1;
while( nextAngle-orientationAngle > Math.PI )
nextAngle = (float)(nextAngle-2*Math.PI);
while( nextAngle-orientationAngle < -Math.PI )
nextAngle = (float)(nextAngle+2*Math.PI);
if( orientationAngle > nextAngle )
angularDirection = -1;
path=null;
}
else
takeUpdate = true;
if(!takeUpdate)
return;
// Our update...
xPosition = (float)msg.srcPoint.x;
yPosition = (float)msg.srcPoint.y;
orientationAngle = msg.orientationAngle;
walkingAlongPath = msg.isMoving;
if( walkingAlongPath )
recreateTrajectory( msg.dstPoint, msg.movementDeltaTime );
else
resetMovement(); // No movement
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** To update speed & rotations
*/
private void updateMovementAspect() {
realisticRotations = false; // default
speed = 1.0f; // default : very slow speed
if( player==null || player.getLocation()==null )
return;
if ( player.getLocation().isRoom() )
realisticRotations = true;
speed = player.getBasicChar().getSpeed( player.getLocation() );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Our Tick method. Call this method regularly to update the position along the path.
*/
public void tick() {
if (AStarDouble.isInitialized()) {
if(reconstructTrajectory) {
if(endPoint!=null)
recreateTrajectory( endPoint.toPoint(), movementDeltaTime );
reconstructTrajectory = false;
}
else
updatePathMovement();
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/** Updates our movement along path.
* Method to call each tick to update the entity's position.
* This method does nothing if there is no current move.
*/
private synchronized void updatePathMovement() {
if(!turningAlongPath && !walkingAlongPath)
return;
// 1 - Time Update - Delta T
long now = System.currentTimeMillis();
double deltaT = ( now-lastUpdateTime )/1000.0f;
lastUpdateTime = now;
if(deltaT>=0.8f) return; // SECURITY if a slow is encountered
if(deltaT<0) return; // Date has been advanced
// 2 - Orientation update
if (turningAlongPath) {
// Orientation update
orientationAngle += angularDirection*deltaT*angularSpeed;
// End of turn ?
double deltaA = (nextAngle-orientationAngle)*angularDirection;
if( deltaA<=0 ) {
if(useEndingOrientationValue &&
( path==null || pathIndex >= path.size() ) ) {
resetMovement(); // recreated trajectory ending by a rotation...
return;
}
turningAlongPath = false;
orientationAngle = angle( getPosition(), nextPoint );
}
else if(deltaA>Math.PI/8)
return; // no footsteps, the angle is to great, we just turn...
}
// 3 - Position Update
if( path==null )
return; // no path to follow we just have to turn on ourself
xPosition = (float)(xPosition + speed*deltaT*Math.cos( orientationAngle ) );
yPosition = (float)(yPosition + speed*deltaT*Math.sin( orientationAngle ) );
// 4 - Have we reached the next point in the path ?
float deltaD = distance( getPosition(), prevPoint ) - distance( nextPoint, prevPoint );
if( deltaD >= 0 ) {
pathIndex++;
// Path end point reached ?
if( pathIndex >= path.size() ) {
xPosition = (float) nextPoint.x;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -