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

📄 pathfollower.java

📁 Vyger offers a D & D and Rogue-like environment in a graphical online roleplay game.
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                yPosition = (float) nextPoint.y;
                orientationAngle = nextAngle;

              // if this is a recreated trajectory do we have to turn to get the right
              // final orientation ?
                if(useEndingOrientationValue && realisticRotations) {
                   nextAngle = (float) endingOrientation;
                   turningAlongPath = true;
                   return;
                }

                useEndingOrientationValue=false;
                stopMovement();
                return;
            }

         // Next Point reached...
            prevPoint = getPosition();
            nextPoint = (Point) path.elementAt( pathIndex );
            updateAngularNode();
        }
    }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  // MOVEMENT CONTROL

    /** To set a player's movement : movement from current position to the given point.
    */
    public void moveTo( Point endPosition, WorldManager wManager ) {
        // Test if xPosition,yPosition is a valid point
        Point startPt = new Point( (int)xPosition, (int)yPosition );
        if ( !AStarDouble.isValidStart(startPt) ) {
            Debug.signal(Debug.WARNING,this,"PathFollower : invalid start point");
            // We reset the position
            WotlasLocation location = player.getLocation();
            // We search for a valid insertion point
            ScreenPoint pReset = null;
            if ( location.isRoom() )
                pReset = player.getMyRoom().getInsertionPoint();
            else {
                if ( location.isTown() ) {
                    TownMap myTown = wManager.getTownMap( location );
                    if (myTown!=null) 
                      pReset = myTown.getInsertionPoint();
                }
                else if ( location.isWorld() ) {
                    WorldMap myWorld = wManager.getWorldMap( location );
                    if (myWorld!=null)  
                        pReset = myWorld.getInsertionPoint();
                }
            }

            if (pReset==null) {
                pReset = new ScreenPoint(0, 0);
                Debug.signal(Debug.CRITICAL,this,"Could not find a valid start point !");
            } else
                Debug.signal(Debug.NOTICE,this,"Found a new valid start point...");
                player.setX(pReset.x);
                player.setY(pReset.y);
                startPt.x = pReset.x;
                startPt.y = pReset.y;              
            }
            path = findPath( startPt, new Point( endPosition.x, endPosition.y ),player.getLocation().isRoom() );
            if( path==null ) {
            	if( walkingAlongPath )
                    stopMovement(); // a message is sent : we were moving...
                else
                    resetMovement(); // no message sent : we were already still...
                return; // no movement
            }
            updateMovementAspect();
            initMovement( path );
            if(player.isMaster())
               player.sendMessage( new PathUpdateMovementMessage( this, player.getPrimaryKey(), player.getSyncID() ) );
     }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** To rotate the player on itself.
   *  @param finalOrientation final orientation to reach
   */
     public void rotateTo( double finalOrientation ) {

         orientationAngle = finalOrientation;

         if( player.isMaster() )
            player.sendMessage( new PathUpdateMovementMessage( this, player.getPrimaryKey(), player.getSyncID() ) );
     }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** To recreate a trajectory from a dest. point & a DeltaTime.
   */
     public void recreateTrajectory( Point pDst, int movementDeltaTime ) {
            path = findPath( new Point( (int)xPosition, (int)yPosition ),
                             new Point( pDst.x, pDst.y ), player.getLocation().isRoom() );

            if( path==null ) {
                Debug.signal( Debug.ERROR, this, "Failed to re-create path !" );
                
                if(player.isMaster())
                   stopMovement();
                else
                   resetMovement();
                return;
            }

            updateMovementAspect();
            
            if(movementDeltaTime>500)
               initMovement( path, movementDeltaTime );
            else
               initMovement( path );
     }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

   /** Initialize a path movement from the start. This is the most method you should
    *  use the most. This method modifies the entire state of the PathFollower.
    *  To test if the movement is finished, call the isMoving method after each tick.
    *
    * @param path a valid path returned by the Astar algorithm.
    */
    synchronized public void initMovement( List path ) {

      // 1 - Control
         if( path==null || path.size()<1 ) {
             Debug.signal(Debug.ERROR, this, "Invalid Path !!!! "+path);
             return;
         }

      // 2 - Path Inits
         this.path = path;
         pathIndex = 1;
         lastUpdateTime = System.currentTimeMillis();
         movementTimeStamp = lastUpdateTime;

         prevPoint =  getPosition();
         nextPoint = (Point) path.elementAt(pathIndex);

         updateAngularNode();

      // 3 - We validate the movement...
         walkingAlongPath = true;
    }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** Given a path followed by a player (1) and an elapsed time since the movement begun (2)
   *  we initialize our path movement at the computed "current" position.
   *
   *  The "current" position is totaly dependent from the speed at which we move. So be
   *  sure to correctly initialize the PathFollower's speed BEFORE calling this method.
   *
   * @param path current path followed by a player.
   * @param deltaTime deltaTime in ms since the player begun to follow the path (starting
   *        at the first point given in the path parameter)
   */
    synchronized public void initMovement( List path, int deltaTime ) {

     // 1 - Control
        if(path==null || path.size()<1 ) {
           resetMovement();
           Debug.signal(Debug.ERROR, this, "Invalid Path !!!! "+path);
           return;
         }

        if(path.size()==1) {
           resetMovement();
           return; // no movement
        }

        this.path = path;

     // 2 - Position evaluation
        float totalDistance = (deltaTime/1000.0f)*speed;
        double d = 0.0f;
        Point a0 = null;
        Point a1 = (Point)path.elementAt(0);
        
        for( int i=0; i<path.size()-1; i++ ) {
            a0 = a1;
            a1 = (Point)path.elementAt(i+1);            
            d += distance( a0, a1 );

         // have we found the last point crossed by our entity ?
            if( d >= totalDistance ) {
              // Path approved !
                 this.path = path;
                 pathIndex = i;

                 orientationAngle = angle( a0, a1 );                
                 xPosition = (float)(a1.x - (d-totalDistance)*Math.cos(orientationAngle) );
                 yPosition = (float)(a1.y - (d-totalDistance)*Math.sin(orientationAngle) );

                 prevPoint =  a0;
                 nextPoint = a1; //(Point) path.elementAt(pathIndex);
                 lastUpdateTime = System.currentTimeMillis();
                 movementTimeStamp = lastUpdateTime;

                 updateAngularNode();

              // We validate the movement
                 walkingAlongPath = true;
                 return;
            }
        }

     // 3 - If we arrive here it means that the movement is over !
     //     We set the PathFollower state to the end of the path
        a0 = (Point)path.elementAt(path.size()-2);
        a1 = (Point)path.elementAt(path.size()-1);

        orientationAngle = angle( a0, a1 );
        xPosition = (float)a1.x;
        yPosition = (float)a1.y;

        if(player.isMaster())
           stopMovement();     
        else
           resetMovement();
   }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** To update the angular movement at a Path node.
   */
    private void updateAngularNode() {
        nextAngle = angle( prevPoint, nextPoint );

        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;

        if (realisticRotations)
          turningAlongPath = true;   // we will turn progressively, using the angularSpeed
        else {
          turningAlongPath = false;
          orientationAngle = nextAngle; // We update the angle right now
        }
    }

 /*------------------------------------------------------------------------------------*/

   /** Helper. Returns the distance between two points
    * @param a first point
    * @param b second point
    * @return distance between the two points.
    */
    public static float distance( Point a, Point b ) {
    	 if(a==null || b==null) return 0f;
    	
         return (float) Math.sqrt( (b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x) );
    }

 /*------------------------------------------------------------------------------------*/

   /** Helper. Returns the angle between the given line and the horizontal.
    * @param first point of the line
    * @param second point of the line
    * @return angle in radian in the [-pi,pi] range.
    */
    public static float angle( Point a, Point b ) {
         if(b.x==a.x) {
            if(b.y>a.y) return (float) Math.PI/2;
            else if (b.y<a.y) return (float) -Math.PI/2;

            return 0.0f;
         }

         float angle = (float) Math.atan( (double)(b.y-a.y)/(b.x-a.x) );

         if(b.x<a.x) {
            if(angle>=0) return (float) ( angle-Math.PI );
            if(angle<0)  return (float) ( angle+Math.PI );
         }

         return angle;
    }

 /*------------------------------------------------------------------------------------*/
  /** write object data with serialize.
   */
    public void writeExternal(java.io.ObjectOutput objectOutput)
    throws java.io.IOException {
        objectOutput.writeInt( ExternalizeGetVersion() );
        objectOutput.writeFloat( xPosition );
        objectOutput.writeFloat( yPosition );
        objectOutput.writeLong( movementTimeStamp );
        objectOutput.writeBoolean( walkingAlongPath );
        objectOutput.writeDouble( orientationAngle );
    }
    
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** read object data with serialize.
   */
    public void readExternal(java.io.ObjectInput objectInput)
    throws java.io.IOException, java.lang.ClassNotFoundException {
        int IdTmp = objectInput.readInt();
        if( IdTmp == ExternalizeGetVersion() ){
            xPosition = objectInput.readFloat();
            yPosition = objectInput.readFloat();
            movementTimeStamp = objectInput.readLong();
            walkingAlongPath = objectInput.readBoolean();
            orientationAngle = objectInput.readDouble();
        } else {
            // to do.... when new version
        }
    }

 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /** id version of data, used in serialized persistance.
   */
    public int ExternalizeGetVersion(){
        return 1;
    }    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -