Separated path code from sprite code so that we can have other things

follow a path (specifically, I want to allow the media panel to be
"scrolled" along a path).


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1409 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2002-05-31 03:38:03 +00:00
parent f448ebe4f1
commit ccbc47a7de
12 changed files with 133 additions and 122 deletions
@@ -1,10 +1,10 @@
//
// $Id: CharacterSprite.java,v 1.31 2002/05/29 23:27:14 mdb Exp $
// $Id: CharacterSprite.java,v 1.32 2002/05/31 03:38:02 mdb Exp $
package com.threerings.cast;
import com.threerings.media.sprite.Path;
import com.threerings.media.sprite.ImageSprite;
import com.threerings.media.util.Path;
/**
* A character sprite is a sprite that animates itself while walking
@@ -1,5 +1,5 @@
//
// $Id: ImageSprite.java,v 1.5 2002/05/04 19:35:31 mdb Exp $
// $Id: ImageSprite.java,v 1.6 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
@@ -145,6 +145,12 @@ public class ImageSprite extends Sprite
return;
}
// if these are the same frames we already had, no need to do a
// bunch of pointless business
if (frames == _frames) {
return;
}
// start with our old bounds
Rectangle dirty = new Rectangle(_bounds);
@@ -203,7 +209,7 @@ public class ImageSprite extends Sprite
// move the sprite along toward its destination, if any
if (_path != null) {
moved = _path.updatePosition(this, timestamp);
moved = _path.tick(this, timestamp);
}
// increment the display image if performing image animation
@@ -1,8 +1,10 @@
//
// $Id: PathCompletedEvent.java,v 1.1 2001/09/13 19:36:20 mdb Exp $
// $Id: PathCompletedEvent.java,v 1.2 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
import com.threerings.media.util.Path;
/**
* A path completed event is dispatched when a sprite completes a path
* along which it has been requested to move.
@@ -1,5 +1,5 @@
//
// $Id: Sprite.java,v 1.44 2002/05/29 23:27:14 mdb Exp $
// $Id: Sprite.java,v 1.45 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
@@ -12,6 +12,8 @@ import java.util.ArrayList;
import com.threerings.util.DirectionCodes;
import com.threerings.media.Log;
import com.threerings.media.util.Path;
import com.threerings.media.util.Pathable;
/**
* The sprite class represents a single moveable object in an animated
@@ -19,7 +21,7 @@ import com.threerings.media.Log;
* be moved along a path.
*/
public abstract class Sprite
implements DirectionCodes
implements DirectionCodes, Pathable
{
/**
* Constructs a sprite with a default initial location of <code>(0,
@@ -332,7 +334,7 @@ public abstract class Sprite
{
// if we've a path, move the sprite along toward its destination
if (_path != null) {
_path.updatePosition(this, tickStamp);
_path.tick(this, tickStamp);
}
}
@@ -1,7 +1,7 @@
//
// $Id: LinePath.java,v 1.1 2002/05/17 21:14:06 mdb Exp $
// $Id: LinePath.java,v 1.2 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
package com.threerings.media.util;
import java.awt.Color;
import java.awt.Graphics2D;
@@ -14,7 +14,7 @@ import com.threerings.media.Log;
import com.threerings.media.util.MathUtil;
/**
* The line path is used to cause a sprite to go from point A to point B
* The line path is used to cause a pathable to go from point A to point B
* in a certain number of milliseconds.
*/
public class LinePath implements Path
@@ -56,29 +56,29 @@ public class LinePath implements Path
}
// documentation inherited
public void init (Sprite sprite, long timestamp)
public void init (Pathable pable, long timestamp)
{
// give the sprite a chance to perform any starting antics
sprite.pathBeginning();
// give the pable a chance to perform any starting antics
pable.pathBeginning();
// make a note of the time at which we expect to arrive
_arrivalTime = timestamp + _duration;
// pretend like we just moved the sprite
// pretend like we just moved the pathable
_lastMove = timestamp;
// update our position to the start of the path
updatePosition(sprite, timestamp);
tick(pable, timestamp);
}
// documentation inherited
public boolean updatePosition (Sprite sprite, long timestamp)
public boolean tick (Pathable pable, long timestamp)
{
// if we've blown past our arrival time, we need to get our bootay
// to the prearranged spot and get the hell out
if (timestamp >= _arrivalTime) {
sprite.setLocation(_dest.x, _dest.y);
sprite.pathCompleted();
pable.setLocation(_dest.x, _dest.y);
pable.pathCompleted();
return true;
}
@@ -87,22 +87,22 @@ public class LinePath implements Path
// the number of milliseconds until we're expected to finish
float rt = (float)(_arrivalTime - _lastMove);
// how many pixels we have left to go
int leftx = _dest.x - sprite.getX(), lefty = _dest.y - sprite.getY();
int leftx = _dest.x - pable.getX(), lefty = _dest.y - pable.getY();
// we want to move the sprite by the remaining distance multiplied
// by the move delta divided by the remaining time
// we want to move the pathable by the remaining distance
// multiplied by the move delta divided by the remaining time
int dx = Math.round((float)(leftx * dt) / rt);
int dy = Math.round((float)(lefty * dt) / rt);
// Log.info("Updated sprite [duration=" + _duration +
// Log.info("Updated pathable [duration=" + _duration +
// ", dist=" + _distance + ", dt=" + dt + ", rt=" + rt +
// ", leftx=" + leftx + ", lefty=" + lefty +
// ", dx=" + dx + ", dy=" + dy + "].");
// only update the sprite's location if it actually moved
// only update the pathable's location if it actually moved
if (dx != 0 || dy != 0) {
_lastMove = timestamp;
sprite.setLocation(sprite.getX() + dx, sprite.getY() + dy);
pable.setLocation(pable.getX() + dx, pable.getY() + dy);
return true;
}
@@ -143,6 +143,6 @@ public class LinePath implements Path
/** The time at which we expect to complete our path. */
protected long _arrivalTime;
/** The time at which we last actually moved the sprite. */
/** The time at which we last actually moved the pathable. */
protected long _lastMove;
}
@@ -1,7 +1,7 @@
//
// $Id: LineSegmentPath.java,v 1.22 2002/05/17 21:13:26 mdb Exp $
// $Id: LineSegmentPath.java,v 1.23 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
package com.threerings.media.util;
import java.awt.Color;
import java.awt.Point;
@@ -20,11 +20,11 @@ import com.threerings.media.Log;
import com.threerings.media.util.MathUtil;
/**
* The line segment path is used to cause a sprite to follow a path
* that is made up of a sequence of line segments. There must be at
* least two nodes in any worthwhile path. The direction of the first
* node in the path is meaningless since the sprite begins at that
* node and will therefore never be heading towards it.
* The line segment path is used to cause a pathable to follow a path that
* is made up of a sequence of line segments. There must be at least two
* nodes in any worthwhile path. The direction of the first node in the
* path is meaningless since the pathable begins at that node and will
* therefore never be heading towards it.
*/
public class LineSegmentPath
implements DirectionCodes, Path
@@ -102,14 +102,14 @@ public class LineSegmentPath
}
/**
* Sets the velocity of this sprite in pixels per millisecond. The
* Sets the velocity of this pathable in pixels per millisecond. The
* velocity is measured as pixels traversed along the path that the
* sprite is traveling rather than in the x or y directions
* individually. Note that the sprite velocity should not be changed
* while a path is being traversed; doing so may result in the sprite
* position changing unexpectedly.
* pathable is traveling rather than in the x or y directions
* individually. Note that the pathable velocity should not be
* changed while a path is being traversed; doing so may result in the
* pathable position changing unexpectedly.
*
* @param velocity the sprite velocity in pixels per millisecond.
* @param velocity the pathable velocity in pixels per millisecond.
*/
public void setVelocity (float velocity)
{
@@ -117,10 +117,10 @@ public class LineSegmentPath
}
/**
* Computes the velocity at which the sprite will need to travel along
* this path such that it will arrive at the destination in
* Computes the velocity at which the pathable will need to travel
* along this path such that it will arrive at the destination in
* approximately the specified number of milliseconds. Efforts are
* taken to get the sprite there as close to the desired time as
* taken to get the pathable there as close to the desired time as
* possible, but framerate variation may prevent it from arriving
* exactly on time.
*/
@@ -162,22 +162,22 @@ public class LineSegmentPath
}
// documentation inherited
public void init (Sprite sprite, long timestamp)
public void init (Pathable pable, long timestamp)
{
// give the sprite a chance to perform any starting antics
sprite.pathBeginning();
// give the pathable a chance to perform any starting antics
pable.pathBeginning();
// if we have only one node then let the sprite know that we're
// if we have only one node then let the pathable know that we're
// done straight away
if (size() < 2) {
// move the sprite to the location specified by the first node
// (assuming we have a first node)
// move the pathable to the location specified by the first
// node (assuming we have a first node)
if (size() == 1) {
PathNode node = (PathNode)_nodes.get(0);
sprite.setLocation(node.loc.x, node.loc.y);
pable.setLocation(node.loc.x, node.loc.y);
}
// and let the sprite know that we're done
sprite.pathCompleted();
// and let the pathable know that we're done
pable.pathCompleted();
return;
}
@@ -188,11 +188,11 @@ public class LineSegmentPath
_dest = getNextNode();
// begin traversing the path
headToNextNode(sprite, timestamp, timestamp);
headToNextNode(pable, timestamp, timestamp);
}
// documentation inherited
public boolean updatePosition (Sprite sprite, long timestamp)
public boolean tick (Pathable pable, long timestamp)
{
// figure out how far along this segment we should be
long msecs = timestamp - _nodestamp;
@@ -204,22 +204,22 @@ public class LineSegmentPath
// end of this node, then move to the next one
if (pctdone >= 1.0) {
long used = (long)(_seglength / _vel);
return headToNextNode(sprite, _nodestamp + used, timestamp);
return headToNextNode(pable, _nodestamp + used, timestamp);
}
// otherwise we position the sprite along the path
int ox = sprite.getX();
int oy = sprite.getY();
// otherwise we position the pathable along the path
int ox = pable.getX();
int oy = pable.getY();
int nx = _src.loc.x + (int)((_dest.loc.x - _src.loc.x) * pctdone);
int ny = _src.loc.y + (int)((_dest.loc.y - _src.loc.y) * pctdone);
// Log.info("Moving sprite [msecs=" + msecs + ", pctdone=" + pctdone +
// Log.info("Moving pathable [msecs=" + msecs + ", pctdone=" + pctdone +
// ", travpix=" + travpix + ", seglength=" + _seglength +
// ", dx=" + (nx-ox) + ", dy=" + (ny-oy) + "].");
// only update the sprite's location if it actually moved
// only update the pathable's location if it actually moved
if (ox != nx || oy != ny) {
sprite.setLocation(nx, ny);
pable.setLocation(nx, ny);
return true;
}
@@ -233,18 +233,18 @@ public class LineSegmentPath
}
/**
* Place the sprite moving along the path at the end of the
* previous path node, face it appropriately for the next node,
* and start it on its way. Returns whether the sprite position
* moved.
* Place the pathable moving along the path at the end of the previous
* path node, face it appropriately for the next node, and start it on
* its way. Returns whether the pathable position moved.
*/
protected boolean headToNextNode (Sprite sprite, long startstamp, long now)
protected boolean headToNextNode (
Pathable pable, long startstamp, long now)
{
// check to see if we've completed our path
if (!_niter.hasNext()) {
// move the sprite to the location of our last destination
sprite.setLocation(_dest.loc.x, _dest.loc.y);
sprite.pathCompleted();
// move the pathable to the location of our last destination
pable.setLocation(_dest.loc.x, _dest.loc.y);
pable.pathCompleted();
return true;
}
@@ -254,9 +254,9 @@ public class LineSegmentPath
// pop the next node off the path
_dest = getNextNode();
// adjust the sprite's orientation
// adjust the pathable's orientation
if (_dest.dir != NONE) {
sprite.setOrientation(_dest.dir);
pable.setOrientation(_dest.dir);
}
// make a note of when we started traversing this node
@@ -269,11 +269,11 @@ public class LineSegmentPath
// if we're already there (the segment length is zero), we skip to
// the next segment
if (_seglength == 0) {
return headToNextNode(sprite, startstamp, now);
return headToNextNode(pable, startstamp, now);
}
// now update the sprite's position based on our progress thus far
return updatePosition(sprite, now);
// now update the pathable's position based on our progress thus far
return tick(pable, now);
}
// documentation inherited
@@ -298,7 +298,7 @@ public class LineSegmentPath
}
/**
* Populate the path with the path nodes that lead the sprite from
* Populate the path with the path nodes that lead the pathable from
* its starting position to the given destination coordinates
* following the given list of screen coordinates.
*/
@@ -329,10 +329,10 @@ public class LineSegmentPath
/** We use this when moving along this path. */
protected Iterator _niter;
/** When moving, the sprite's source path node. */
/** When moving, the pathable's source path node. */
protected PathNode _src;
/** When moving, the sprite's destination path node. */
/** When moving, the pathable's destination path node. */
protected PathNode _dest;
/** The time at which we started traversing the current node. */
@@ -344,7 +344,7 @@ public class LineSegmentPath
/** The path velocity in pixels per millisecond. */
protected float _vel = DEFAULT_VELOCITY;
/** When moving, the sprite position including fractional pixels. */
/** When moving, the pathable position including fractional pixels. */
protected float _movex, _movey;
/** When moving, the distance to move on each axis per tick. */
@@ -353,6 +353,6 @@ public class LineSegmentPath
/** The distance to move on the straight path line per tick. */
protected float _fracx, _fracy;
/** Default sprite velocity. */
/** Default pathable velocity. */
protected static final float DEFAULT_VELOCITY = 200f/1000f;
}
+24 -25
View File
@@ -1,56 +1,55 @@
//
// $Id: Path.java,v 1.6 2002/05/17 21:12:48 mdb Exp $
// $Id: Path.java,v 1.7 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
package com.threerings.media.util;
import java.awt.Graphics2D;
/**
* A path is used to cause a sprite to follow a particular path along the
* screen. The sprite will call into the path every time it is ticked by
* the animation manager and the path is responsible for updating the
* position of the sprite based on the time that has elapsed since the
* sprite started down the path. The animation manager attempts to tick
* once per frame at the desired frame rate, but may tick less often if
* CPU resources are limited, thus paths should not rely on tick counts
* but instead use elapsed time to determine progress.
* A path is used to cause a {@link Pathable} to follow a particular path
* along the screen. The {@link Pathable} is responsible for calling
* {@link #tick} on the path with reasonable frequency (generally as a
* part of the frame tick. The path is responsible for updating the
* position of the {@link Pathable} based on the time that has elapsed
* since the {@link Pathable} started down the path.
*
* <p> The path should call back to the sprite (via {@link
* Sprite#pathCompleted}) to let it know when the path has been completed.
* <p> The path should call the appropriate callbacks on the {@link
* Pathable} when appropriate (e.g. {@link Pathable#pathBeginning}, {@link
* Pathable#pathCompleted}).
*/
public interface Path
{
/**
* Called once to let the path prepare itself for the process of
* animating the supplied sprite.
* animating the supplied pathable.
*/
public void init (Sprite sprite, long tickStamp);
public void init (Pathable pable, long tickStamp);
/**
* Called to request that this path update the position of the
* specified sprite based on the supplied timestamp information. A
* specified pathable based on the supplied timestamp information. A
* path should record its initial timestamp and determine the progress
* of the sprite along the path based on the time elapsed since the
* sprite began down the path.
* of the pathable along the path based on the time elapsed since the
* pathable began down the path.
*
* @param sprite the sprite whose position should be updated.
* @param pable the pathable whose position should be updated.
* @param tickStamp the timestamp associated with this frame.
*
* @return true if the sprite's position was updated, false if the
* path determined that the sprite should not move at this time.
* @return true if the pathable's position was updated, false if the
* path determined that the pathable should not move at this time.
*/
public boolean updatePosition (Sprite sprite, long tickStamp);
public boolean tick (Pathable pable, long tickStamp);
/**
* This is called if the sprite manager is paused for some length of
* time and then unpaused. Paths should adjust any time stamps they
* are maintaining internally by the delta so that time maintains the
* This is called if the pathable is paused for some length of time
* and then unpaused. Paths should adjust any time stamps they are
* maintaining internally by the delta so that time maintains the
* illusion of flowing smoothly forward.
*/
public void fastForward (long timeDelta);
/**
* Called when the view that contains the sprite following this path
* Called when the view that contains the pathable following this path
* is scrolling by the specified amount. Gives the path an opportunity
* to adjust its internal coordinates by the scrolled amount.
*/
@@ -1,7 +1,7 @@
//
// $Id: PathNode.java,v 1.6 2001/10/24 00:55:08 shaper Exp $
// $Id: PathNode.java,v 1.7 2002/05/31 03:38:03 mdb Exp $
package com.threerings.media.sprite;
package com.threerings.media.util;
import java.awt.Point;
@@ -1,5 +1,5 @@
//
// $Id: IsoSceneView.java,v 1.109 2002/05/30 22:21:51 ray Exp $
// $Id: IsoSceneView.java,v 1.110 2002/05/31 03:38:03 mdb Exp $
package com.threerings.miso.scene;
@@ -26,8 +26,8 @@ import com.samskivert.util.HashIntMap;
import com.threerings.media.RegionManager;
import com.threerings.media.sprite.Path;
import com.threerings.media.sprite.SpriteManager;
import com.threerings.media.util.Path;
import com.threerings.media.tile.ObjectTile;
import com.threerings.media.tile.Tile;
@@ -1,5 +1,5 @@
//
// $Id: SceneView.java,v 1.27 2002/04/23 01:18:17 mdb Exp $
// $Id: SceneView.java,v 1.28 2002/05/31 03:38:03 mdb Exp $
package com.threerings.miso.scene;
@@ -8,7 +8,7 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import com.threerings.media.sprite.Path;
import com.threerings.media.util.Path;
/**
* The scene view interface provides an interface to be implemented by
@@ -1,23 +1,25 @@
//
// $Id: TilePath.java,v 1.4 2002/03/16 03:15:05 shaper Exp $
// $Id: TilePath.java,v 1.5 2002/05/31 03:38:03 mdb Exp $
package com.threerings.miso.scene;
import java.awt.*;
import java.util.List;
import com.threerings.media.sprite.*;
import com.threerings.util.DirectionCodes;
import com.threerings.media.util.LineSegmentPath;
import com.threerings.media.util.PathNode;
import com.threerings.media.util.Pathable;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil;
/**
* The tile path represents a path of tiles through a scene. The path
* is traversed by treating each pair of connected tiles as a line
* segment. Only ambulatory sprites can follow a tile path, and their
* tile coordinates are updated as the path is traversed.
* The tile path represents a path of tiles through a scene. The path is
* traversed by treating each pair of connected tiles as a line segment.
* Only ambulatory sprites can follow a tile path, and their tile
* coordinates are updated as the path is traversed.
*/
public class TilePath extends LineSegmentPath
implements DirectionCodes
@@ -44,13 +46,13 @@ public class TilePath extends LineSegmentPath
}
// documentation inherited
public boolean updatePosition (Sprite sprite, long timestamp)
public boolean tick (Pathable pable, long timestamp)
{
boolean moved = super.updatePosition(sprite, timestamp);
boolean moved = super.tick(pable, timestamp);
if (moved) {
MisoCharacterSprite mcs = (MisoCharacterSprite)sprite;
int sx = sprite.getX(), sy = sprite.getY();
MisoCharacterSprite mcs = (MisoCharacterSprite)pable;
int sx = mcs.getX(), sy = mcs.getY();
Point pos = new Point();
// check whether we've arrived at the destination tile
@@ -1,9 +1,9 @@
//
// $Id: TilePathNode.java,v 1.1 2001/10/24 00:55:08 shaper Exp $
// $Id: TilePathNode.java,v 1.2 2002/05/31 03:38:03 mdb Exp $
package com.threerings.miso.scene;
import com.threerings.media.sprite.PathNode;
import com.threerings.media.util.PathNode;
/**
* The tile path nodes extends the path node class to allow