Create and have the sprite follow a path rather than explicitly

setting the sprite destination.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@152 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Walter Korman
2001-08-02 20:43:03 +00:00
parent efb1881507
commit c41c097cd4
6 changed files with 186 additions and 96 deletions
@@ -1,9 +1,10 @@
//
// $Id: Sprite.java,v 1.5 2001/08/02 18:59:00 shaper Exp $
// $Id: Sprite.java,v 1.6 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.sprite;
import java.awt.*;
import java.util.Enumeration;
import com.threerings.miso.Log;
import com.threerings.miso.tile.Tile;
@@ -62,14 +63,11 @@ public class Sprite
updateDrawPosition();
_curFrame = 0;
_animDelay = -1;
_animDelay = ANIM_NONE;
_numTicks = 0;
setTiles(_tiles);
_dest = new Point();
_state = STATE_NONE;
invalidate();
}
@@ -124,30 +122,53 @@ public class Sprite
}
/**
* Set the destination of the sprite in pixel coordinates.
* Set the sprite's active path and start moving it along its
* merry way. If the sprite is already moving along a previous
* path the old path will be lost and the new path will begin to
* be traversed.
*
* @param x the destination x-position.
* @param y the destination y-position.
* @param path the path to follow.
*/
public void setDestination (int x, int y)
public void move (Path path)
{
// bail if we're already there
if (x == this.x && y == this.y) return;
// make sure following the path is a sensible thing to do
if (path == null || path.size() < 2) return;
// note our destination
_dest.setLocation(x, y);
// save an enumeration of the path nodes
_path = path.elements();
// skip the first node since it's our starting position.
// perhaps someday we'll do something with this.
_path.nextElement();
// start our meandering
moveAlongPath();
}
/**
* Start the sprite moving toward the next node in its path.
*/
protected void moveAlongPath ()
{
// grab the next node in our path
_dest = (PathNode)_path.nextElement();
// if no more nodes remain, clear out our path and bail
if (_dest == null) {
_path = null;
return;
}
Log.info("moveAlongPath [dest=" + _dest + "].");
// determine the horizontal/vertical move increments
float dist = MathUtil.distance(this.x, this.y, x, y);
_incx = (float)(x - this.x) / dist;
_incy = (float)(y - this.y) / dist;
float dist = MathUtil.distance(x, y, _dest.loc.x, _dest.loc.y);
_incx = (float)(_dest.loc.x - x) / dist;
_incy = (float)(_dest.loc.y - y) / dist;
// init position data used to track fractional pixels
_movex = this.x;
_movey = this.y;
// and that we're moving toward it
_state = STATE_MOVING;
_movex = x;
_movey = y;
}
/**
@@ -157,13 +178,10 @@ public class Sprite
{
if (_curTile == null) return;
int xpos = x - (_curTile.width / 2);
int ypos = y - _curTile.height;
Rectangle dirty = new Rectangle(
_drawx, _drawy, _curTile.width, _curTile.height);
Rectangle dirty =
new Rectangle(xpos, ypos, _curTile.width, _curTile.height);
// Log.info("Sprite dirtying rect [x=" + dirty.x + ", y=" + dirty.y +
// Log.info("Sprite invalidate [x=" + dirty.x + ", y=" + dirty.y +
// ", width=" + dirty.width + ", height=" + dirty.height + "].");
_spritemgr.addDirtyRect(dirty);
@@ -176,40 +194,49 @@ public class Sprite
public void tick ()
{
// increment the display tile if performing tile animation
if (_animDelay != -1 && (_numTicks++ == _animDelay)) {
if (_animDelay != ANIM_NONE && (_numTicks++ == _animDelay)) {
_numTicks = 0;
if (++_curFrame > _tiles.length - 1) _curFrame = 0;
_curTile = _tiles[_curFrame];
// dirty our rectangle since we've altered our display tile
invalidate();
}
switch (_state) {
case STATE_MOVING:
// move the sprite incrementally toward its goal
x = (int)(_movex += _incx);
y = (int)(_movey += _incy);
// stop moving once we've reached our destination
if (_incx > 0 && x > _dest.x || _incx < 0 && x < _dest.x ||
_incy > 0 && y > _dest.y || _incy < 0 && y < _dest.y) {
// make sure we stop exactly where desired
x = _dest.x;
y = _dest.y;
// invalidate the sprite in its new location
invalidate();
// note our stoppage
_animDelay = -1;
_state = STATE_NONE;
}
updateDrawPosition();
break;
// move the sprite along toward its destination, if any
if (_dest != null) {
handleMove();
}
}
/**
* Actually move the sprite's position toward its destination one
* display increment.
*/
protected void handleMove ()
{
// move the sprite incrementally toward its goal
x = (int)(_movex += _incx);
y = (int)(_movey += _incy);
// stop moving once we've reached our destination
if (_incx > 0 && x > _dest.loc.x || _incx < 0 && x < _dest.loc.x ||
_incy > 0 && y > _dest.loc.y || _incy < 0 && y < _dest.loc.y) {
// make sure we stop exactly where desired
x = _dest.loc.x;
y = _dest.loc.y;
// dirty our rectangle since we've moved
invalidate();
// move further along the path if necessary
moveAlongPath();
}
updateDrawPosition();
}
/**
* Update the coordinates at which the sprite image is drawn to
* reflect the sprite's current position.
@@ -238,9 +265,8 @@ public class Sprite
return buf.append("]").toString();
}
/** State constants. */
protected static final int STATE_NONE = 0;
protected static final int STATE_MOVING = 1;
/** Value used to denote that no tile animation is desired. */
protected static final int ANIM_NONE = -1;
/** The tiles used to render the sprite. */
protected Tile[] _tiles;
@@ -254,11 +280,11 @@ public class Sprite
/** The coordinates at which the tile image is drawn. */
protected int _drawx, _drawy;
/** The sprite's current state. */
protected int _state;
/** The PathNode objects describing the path the sprite is following. */
protected Enumeration _path;
/** When moving, the sprite's destination coordinates. */
protected Point _dest;
/** When moving, the sprite's destination path node. */
protected PathNode _dest;
/** When moving, the sprite position including fractional pixels. */
protected float _movex, _movey;
@@ -1,5 +1,5 @@
//
// $Id: LineSegmentPath.java,v 1.1 2001/08/02 00:42:02 shaper Exp $
// $Id: LineSegmentPath.java,v 1.2 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.sprite;
@@ -9,7 +9,9 @@ import java.util.Enumeration;
/**
* The Path class represents the path a sprite follows while
* meandering about the screen. There must be at least two nodes in
* any worthwhile path.
* 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.
*/
public class Path
{
@@ -34,6 +36,15 @@ public class Path
_nodes = new ArrayList();
}
public Path (int x, int y)
{
_nodes = new ArrayList();
// add the starting node with an arbitrarily chosen direction
// since direction is meaningless here
addNode(x, y, DIR_NORTH);
}
/**
* Add a node to the path with the specified destination point and
* facing direction.
@@ -47,6 +58,19 @@ public class Path
_nodes.add(new PathNode(x, y, dir));
}
/**
* Return the requested node index in the path, or null if no such
* index exists.
*
* @param idx the node index.
*
* @return the path node.
*/
public PathNode getNode (int idx)
{
return (PathNode)_nodes.get(idx);
}
/**
* Return an enumeration of the PathNode objects in this path.
*/
@@ -81,7 +105,7 @@ public class Path
public Object nextElement ()
{
return _nodes.get(_idx++);
return (_idx >= _nodes.size()) ? null : _nodes.get(_idx++);
}
protected ArrayList _nodes;
@@ -1,5 +1,5 @@
//
// $Id: PathNode.java,v 1.1 2001/08/02 00:42:02 shaper Exp $
// $Id: PathNode.java,v 1.2 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.sprite;
@@ -28,4 +28,16 @@ public class PathNode
loc = new Point(x, y);
this.dir = dir;
}
/**
* Return a string representation of this path node.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer();
buf.append("[x=").append(loc.x);
buf.append(", y=").append(loc.y);
buf.append(", dir=").append(dir);
return buf.append("]").toString();
}
}
@@ -1,10 +1,10 @@
//
// $Id: IsoSceneView.java,v 1.22 2001/08/02 18:58:59 shaper Exp $
// $Id: IsoSceneView.java,v 1.23 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.scene;
import com.threerings.miso.Log;
import com.threerings.miso.sprite.SpriteManager;
import com.threerings.miso.sprite.*;
import com.threerings.miso.tile.Tile;
import com.threerings.miso.tile.TileManager;
import com.threerings.miso.util.MathUtil;
@@ -69,6 +69,9 @@ public class IsoSceneView implements EditableSceneView
// draw lines illustrating tracking of the mouse position
//paintMouseLines(gfx);
gfx.setColor(Color.yellow);
gfx.drawRect(0, 0, _model.bounds.width - 1, _model.bounds.height - 1);
// restore the original clipping region
gfx.setClip(oldclip);
}
@@ -89,12 +92,12 @@ public class IsoSceneView implements EditableSceneView
int[] dinfo = (int[])_dirty.remove(0);
int tx = dinfo[0], ty = dinfo[1];
// get the tile's screen position
Polygon poly = getTilePolygon(tx, ty);
// draw all layers at this tile position
for (int kk = 0; kk < Scene.NUM_LAYERS; kk++) {
// get the tile's screen position
Polygon poly = getTilePolygon(tx, ty);
// get the tile at these coordinates and layer
Tile tile = _scene.tiles[tx][ty][kk];
if (tile == null) continue;
@@ -108,7 +111,7 @@ public class IsoSceneView implements EditableSceneView
}
// draw all sprites residing in the current tile
_spritemgr.renderSprites(gfx, getTilePolygon(tx, ty));
_spritemgr.renderSprites(gfx, poly);
}
}
@@ -386,6 +389,21 @@ public class IsoSceneView implements EditableSceneView
_model.calculateXAxis();
}
public Path getPath (Sprite sprite, int x, int y)
{
// make sure the destination point is within our bounds
if (x < 0 || x >= _model.bounds.width ||
y < 0 || y >= _model.bounds.height) {
return null;
}
// create path from current loc to destination
Path path = new Path(sprite.x, sprite.y);
path.addNode(x, y, Path.DIR_NORTH);
return path;
}
/** The color to draw the highlighted tile. */
protected static final Color HLT_COLOR = Color.green;
@@ -1,14 +1,16 @@
//
// $Id: SceneView.java,v 1.8 2001/08/02 00:42:02 shaper Exp $
// $Id: SceneView.java,v 1.9 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.scene;
import com.threerings.miso.tile.Tile;
import java.awt.Component;
import java.awt.Graphics;
import java.util.ArrayList;
import com.threerings.miso.sprite.Path;
import com.threerings.miso.sprite.Sprite;
import com.threerings.miso.tile.Tile;
/**
* The SceneView interface provides an interface to be implemented by
* classes that provide a view of a given scene by drawing the scene
@@ -37,4 +39,17 @@ public interface SceneView
* @param rects the list of <code>java.awt.Rectangle</code> objects.
*/
public void invalidateRects (ArrayList rects);
/**
* Return a Path object detailing a valid path for the given
* sprite to take in the scene to get from its current position to
* the destination position.
*
* @param sprite the sprite to move.
* @param x the destination x-position in pixel coordinates.
* @param y the destination y-position in pixel coordinates.
*
* @return the sprite's path or null if no valid path exists.
*/
public Path getPath (Sprite sprite, int x, int y);
}
@@ -1,5 +1,5 @@
//
// $Id: SceneViewPanel.java,v 1.6 2001/08/02 18:59:00 shaper Exp $
// $Id: SceneViewPanel.java,v 1.7 2001/08/02 20:43:03 shaper Exp $
package com.threerings.miso.viewer;
@@ -18,8 +18,9 @@ import com.threerings.miso.util.PerformanceMonitor;
import com.threerings.miso.util.PerformanceObserver;
/**
* The SceneViewPanel class is responsible for managing a SceneView,
* rendering it to the screen, and handling view-related UI events.
* The <code>SceneViewPanel</code> class is responsible for managing a
* <code>SceneView</code>, rendering it to the screen, and handling
* view-related UI events.
*/
public class SceneViewPanel extends JPanel
implements MouseListener, MouseMotionListener, PerformanceObserver
@@ -53,7 +54,7 @@ public class SceneViewPanel extends JPanel
// load up the initial scene
prepareStartingScene();
setDoubleBuffered(false);
//setDoubleBuffered(false);
PerformanceMonitor.register(this, "paint", 1000);
}
@@ -100,9 +101,6 @@ public class SceneViewPanel extends JPanel
_view.paint(g);
g.setColor(Color.yellow);
g.drawRect(0, 0, 600, 600);
PerformanceMonitor.tick(this, "paint");
}
@@ -113,34 +111,30 @@ public class SceneViewPanel extends JPanel
/** MouseListener interface methods */
public void mouseClicked (MouseEvent e)
{
Log.info("mouseClicked [x=" + e.getX() + ", y=" + e.getY() + "].");
}
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
public void mousePressed (MouseEvent e)
{
int x = e.getX(), y = e.getY();
Log.info("mousePressed [x=" + x + ", y=" + y + "].");
_sprite.setDestination(x, y);
// get the path from here to there
Path path = _view.getPath(_sprite, x, y);
if (path != null) {
_sprite.move(path);
}
// hackily highlight the tile that was clicked on for happy testing
((EditableSceneView)_view).setHighlightedTile(x, y);
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
public void mouseReleased (MouseEvent e) { }
/** MouseMotionListener interface methods */
public void mouseMoved (MouseEvent e)
{
}
public void mouseDragged (MouseEvent e)
{
}
public void mouseMoved (MouseEvent e) { }
public void mouseDragged (MouseEvent e) { }
/** The config key to obtain the default scene filename. */
protected static final String CFG_SCENE = "miso-viewer.default_scene";
@@ -148,6 +142,7 @@ public class SceneViewPanel extends JPanel
/** The default scene to load and display. */
protected static final String DEF_SCENE = "rsrc/scenes/default.xml";
/** The sprite we're manipulating within the view. */
protected Sprite _sprite;
/** The context object. */