⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pathfollower.java

📁 Vyger offers a D & D and Rogue-like environment in a graphical online roleplay game.
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -