diff --git a/src/java/com/threerings/media/sprite/Sprite.java b/src/java/com/threerings/media/sprite/Sprite.java index 5a0cbf5e4..7140180be 100644 --- a/src/java/com/threerings/media/sprite/Sprite.java +++ b/src/java/com/threerings/media/sprite/Sprite.java @@ -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; diff --git a/src/java/com/threerings/media/util/LineSegmentPath.java b/src/java/com/threerings/media/util/LineSegmentPath.java index 60e07c689..f1c169708 100644 --- a/src/java/com/threerings/media/util/LineSegmentPath.java +++ b/src/java/com/threerings/media/util/LineSegmentPath.java @@ -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; diff --git a/src/java/com/threerings/media/util/PathNode.java b/src/java/com/threerings/media/util/PathNode.java index 65b6cb1f4..a59e2d19a 100644 --- a/src/java/com/threerings/media/util/PathNode.java +++ b/src/java/com/threerings/media/util/PathNode.java @@ -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(); + } } diff --git a/src/java/com/threerings/miso/client/IsoSceneView.java b/src/java/com/threerings/miso/client/IsoSceneView.java index e5c4cc0f4..baf80c6cd 100644 --- a/src/java/com/threerings/miso/client/IsoSceneView.java +++ b/src/java/com/threerings/miso/client/IsoSceneView.java @@ -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; diff --git a/src/java/com/threerings/miso/client/SceneView.java b/src/java/com/threerings/miso/client/SceneView.java index 07d8cda50..23e5a0cd4 100644 --- a/src/java/com/threerings/miso/client/SceneView.java +++ b/src/java/com/threerings/miso/client/SceneView.java @@ -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 java.awt.Rectangle 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); } diff --git a/tests/src/java/com/threerings/miso/viewer/SceneViewPanel.java b/tests/src/java/com/threerings/miso/viewer/SceneViewPanel.java index 4d45af2db..ea26206d8 100644 --- a/tests/src/java/com/threerings/miso/viewer/SceneViewPanel.java +++ b/tests/src/java/com/threerings/miso/viewer/SceneViewPanel.java @@ -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 SceneViewPanel class is responsible for managing a + * SceneView, 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. */