📄 screenobjectpathfollower.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( screenObject.isTheServerSide() ) if( screenObject instanceof NpcOnTheScreen )// player.sendMessage( new PathUpdateMovementMessage( this, player.getPrimaryKey(), player.getSyncID() ) ); ((NpcOnTheScreen)screenObject).getRouter().sendMessage( new ScreenObjectPathUpdateMovementMessage( this, screenObject.getPrimaryKey() , screenObject.getSyncID()),null, MessageRouter.EXTENDED_GROUP ); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /** 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 ScreenObjectPathUpdateMovementMessage( this, null, screenObject.getSyncID() ); else return (MovementUpdateMessage) new ScreenObjectPathUpdateMovementMessage( this, screenObject.getPrimaryKey(), screenObject.getSyncID() ); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /** To update the current movement. * @param updateMessage MovementUpdateMessage */ public synchronized void setUpdate( MovementUpdateMessage updateMessage ) { if( !(updateMessage instanceof ScreenObjectPathUpdateMovementMessage) ) { Debug.signal( Debug.ERROR, this, "Received bad update message :"+updateMessage.getClass()); return; } ScreenObjectPathUpdateMovementMessage msg = (ScreenObjectPathUpdateMovementMessage) 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, screenObject.getLocation().isTileMap() )==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( screenObject==null || screenObject.getLocation()==null ) return; if ( screenObject.getLocation().isRoom() ) realisticRotations = true; speed = screenObject.getSpeed( screenObject.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; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -