More polishing work on scene rendering.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@543 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: CharacterManager.java,v 1.2 2001/10/22 18:21:41 shaper Exp $
|
// $Id: CharacterManager.java,v 1.3 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -26,9 +26,11 @@ public class CharacterManager
|
|||||||
/**
|
/**
|
||||||
* Construct the character manager.
|
* Construct the character manager.
|
||||||
*/
|
*/
|
||||||
public CharacterManager (Config config, TileManager tilemgr)
|
public CharacterManager (
|
||||||
|
Config config, TileManager tilemgr, IsoSceneViewModel model)
|
||||||
{
|
{
|
||||||
_tilemgr = tilemgr;
|
_tilemgr = tilemgr;
|
||||||
|
_model = model;
|
||||||
|
|
||||||
// load character data descriptions
|
// load character data descriptions
|
||||||
String file = config.getValue(CHARFILE_KEY, DEFAULT_CHARFILE);
|
String file = config.getValue(CHARFILE_KEY, DEFAULT_CHARFILE);
|
||||||
@@ -58,8 +60,8 @@ public class CharacterManager
|
|||||||
MultiFrameImage[] anims = TileUtil.getAmbulatorySpriteFrames(
|
MultiFrameImage[] anims = TileUtil.getAmbulatorySpriteFrames(
|
||||||
_tilemgr, tsid, info.frameCount);
|
_tilemgr, tsid, info.frameCount);
|
||||||
|
|
||||||
AmbulatorySprite sprite = new AmbulatorySprite(0, 0, anims);
|
AmbulatorySprite sprite = new AmbulatorySprite(_model, 0, 0, anims);
|
||||||
sprite.setFrameRate(info.frameRate);
|
sprite.setFrameRate(info.fps);
|
||||||
sprite.setOrigin(info.origin.x, info.origin.y);
|
sprite.setOrigin(info.origin.x, info.origin.y);
|
||||||
|
|
||||||
return sprite;
|
return sprite;
|
||||||
@@ -79,6 +81,9 @@ public class CharacterManager
|
|||||||
/** The tile manager. */
|
/** The tile manager. */
|
||||||
protected TileManager _tilemgr;
|
protected TileManager _tilemgr;
|
||||||
|
|
||||||
|
/** The iso scene view model. */
|
||||||
|
protected IsoSceneViewModel _model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that contains character description information for a
|
* A class that contains character description information for a
|
||||||
* single character for use when constructing the character's
|
* single character for use when constructing the character's
|
||||||
@@ -88,13 +93,13 @@ public class CharacterManager
|
|||||||
{
|
{
|
||||||
public int tsid;
|
public int tsid;
|
||||||
public int frameCount;
|
public int frameCount;
|
||||||
public int frameRate;
|
public int fps;
|
||||||
public Point origin = new Point();
|
public Point origin = new Point();
|
||||||
|
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[tsid=" + tsid + ", frameCount=" + frameCount +
|
return "[tsid=" + tsid + ", frameCount=" + frameCount +
|
||||||
", frameRate=" + frameRate + ", origin=" + origin + "]";
|
", fps=" + fps + ", origin=" + origin + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
//
|
//
|
||||||
// $Id: CharacterSprite.java,v 1.13 2001/10/22 18:21:41 shaper Exp $
|
// $Id: CharacterSprite.java,v 1.14 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
|
||||||
import com.threerings.media.sprite.*;
|
import com.threerings.media.sprite.*;
|
||||||
|
|
||||||
import com.threerings.miso.Log;
|
import com.threerings.miso.Log;
|
||||||
import com.threerings.miso.tile.MisoTile;
|
import com.threerings.miso.tile.MisoTile;
|
||||||
|
import com.threerings.miso.scene.util.IsoUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ambulatory sprite is a sprite that animates itself while walking
|
* An ambulatory sprite is a sprite that animates itself while walking
|
||||||
@@ -25,11 +28,13 @@ public class AmbulatorySprite extends Sprite implements Traverser
|
|||||||
* @param anims the set of multi-frame images to use when animating
|
* @param anims the set of multi-frame images to use when animating
|
||||||
* the sprite in each of the compass directions.
|
* the sprite in each of the compass directions.
|
||||||
*/
|
*/
|
||||||
public AmbulatorySprite (int x, int y, MultiFrameImage[] anims)
|
public AmbulatorySprite (
|
||||||
|
IsoSceneViewModel model, int x, int y, MultiFrameImage[] anims)
|
||||||
{
|
{
|
||||||
super(x, y);
|
super(x, y);
|
||||||
|
|
||||||
// keep track of these
|
// keep track of these
|
||||||
|
_model = model;
|
||||||
_anims = anims;
|
_anims = anims;
|
||||||
|
|
||||||
// give ourselves an initial orientation
|
// give ourselves an initial orientation
|
||||||
@@ -115,9 +120,111 @@ public class AmbulatorySprite extends Sprite implements Traverser
|
|||||||
return tile.passable;
|
return tile.passable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sprite's location on the x-axis in tile coordinates.
|
||||||
|
*/
|
||||||
|
public int getTileX ()
|
||||||
|
{
|
||||||
|
return _tilex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sprite's location on the y-axis in tile coordinates.
|
||||||
|
*/
|
||||||
|
public int getTileY ()
|
||||||
|
{
|
||||||
|
return _tiley;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sprite's location on the x-axis within its current
|
||||||
|
* tile in fine coordinates.
|
||||||
|
*/
|
||||||
|
public int getFineX ()
|
||||||
|
{
|
||||||
|
return _finex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sprite's location on the y-axis within its current
|
||||||
|
* tile in fine coordinates.
|
||||||
|
*/
|
||||||
|
public int getFineY ()
|
||||||
|
{
|
||||||
|
return _finey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void setLocation (int x, int y)
|
||||||
|
{
|
||||||
|
super.setLocation(x, y);
|
||||||
|
|
||||||
|
if (_path == null) {
|
||||||
|
// we only calculate the sprite's tile and fine
|
||||||
|
// coordinates if we have no path, since paths that move
|
||||||
|
// us about are responsible for keeping our scene
|
||||||
|
// coordinates up to date since only they can know where
|
||||||
|
// we really are while in transition from one place to
|
||||||
|
// another.
|
||||||
|
|
||||||
|
// get the sprite's position in full coordinates
|
||||||
|
Point fpos = new Point();
|
||||||
|
IsoUtil.screenToFull(_model, _x, _y, fpos);
|
||||||
|
|
||||||
|
// save off the sprite's tile and fine coordinates
|
||||||
|
_tilex = IsoUtil.fullToTile(fpos.x);
|
||||||
|
_tiley = IsoUtil.fullToTile(fpos.y);
|
||||||
|
_finex = IsoUtil.fullToFine(fpos.x);
|
||||||
|
_finey = IsoUtil.fullToFine(fpos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the sprite's location in tile coordinates; the sprite is
|
||||||
|
* not actually moved in any way. This method is only intended
|
||||||
|
* for use in updating the sprite's stored position which is made
|
||||||
|
* accessible to others that may care to review it.
|
||||||
|
*/
|
||||||
|
public void setTileLocation (int x, int y)
|
||||||
|
{
|
||||||
|
_tilex = x;
|
||||||
|
_tiley = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the sprite's location in fine coordinates; the sprite is
|
||||||
|
* not actually moved in any way. This method is only intended
|
||||||
|
* for use in updating the sprite's stored position which is made
|
||||||
|
* accessible to others that may care to review it.
|
||||||
|
*/
|
||||||
|
public void setFineLocation (int x, int y)
|
||||||
|
{
|
||||||
|
_finex = x;
|
||||||
|
_finey = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void toString (StringBuffer buf)
|
||||||
|
{
|
||||||
|
super.toString(buf);
|
||||||
|
buf.append(", tilex=").append(_tilex);
|
||||||
|
buf.append(", tiley=").append(_tiley);
|
||||||
|
buf.append(", finex=").append(_finex);
|
||||||
|
buf.append(", finey=").append(_finey);
|
||||||
|
}
|
||||||
|
|
||||||
/** The animation frames for the sprite facing each direction. */
|
/** The animation frames for the sprite facing each direction. */
|
||||||
protected MultiFrameImage[] _anims;
|
protected MultiFrameImage[] _anims;
|
||||||
|
|
||||||
|
/** The iso scene view model. */
|
||||||
|
protected IsoSceneViewModel _model;
|
||||||
|
|
||||||
/** The origin of the sprite. */
|
/** The origin of the sprite. */
|
||||||
protected int _xorigin, _yorigin;
|
protected int _xorigin, _yorigin;
|
||||||
|
|
||||||
|
/** The sprite location in tile coordinates. */
|
||||||
|
protected int _tilex, _tiley;
|
||||||
|
|
||||||
|
/** The sprite location in fine coordinates. */
|
||||||
|
protected int _finex, _finey;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: DirtyItemList.java,v 1.4 2001/10/22 18:14:57 shaper Exp $
|
|
||||||
|
|
||||||
package com.threerings.media.sprite;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.threerings.media.sprite.Sprite;
|
|
||||||
import com.threerings.media.tile.ObjectTile;
|
|
||||||
|
|
||||||
import com.threerings.media.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The dirty item list keeps track of dirty sprites and object tiles
|
|
||||||
* in a scene.
|
|
||||||
*/
|
|
||||||
public class DirtyItemList extends ArrayList
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Appends the dirty sprite at the given coordinates to the dirty
|
|
||||||
* item list.
|
|
||||||
*/
|
|
||||||
public void appendDirtySprite (
|
|
||||||
Sprite sprite, int x, int y, Rectangle dirtyRect)
|
|
||||||
{
|
|
||||||
add(new DirtyItem(sprite, null, x, y, dirtyRect));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appends the dirty object tile at the given coordinates to the
|
|
||||||
* dirty item list.
|
|
||||||
*/
|
|
||||||
public void appendDirtyObject (
|
|
||||||
ObjectTile tile, Shape bounds, int x, int y, Rectangle dirtyRect)
|
|
||||||
{
|
|
||||||
add(new DirtyItem(tile, bounds, x, y, dirtyRect));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class to hold the items inserted in the dirty list along with
|
|
||||||
* all of the information necessary to render their dirty regions
|
|
||||||
* to the target graphics context when the time comes to do so.
|
|
||||||
*/
|
|
||||||
public class DirtyItem
|
|
||||||
{
|
|
||||||
public Object obj;
|
|
||||||
public Shape bounds;
|
|
||||||
public int x, y;
|
|
||||||
public Rectangle dirtyRect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a dirty item.
|
|
||||||
*/
|
|
||||||
public DirtyItem (
|
|
||||||
Object obj, Shape bounds, int x, int y, Rectangle dirtyRect)
|
|
||||||
{
|
|
||||||
this.obj = obj;
|
|
||||||
this.bounds = bounds;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.dirtyRect = dirtyRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Paints the dirty item to the given graphics context. Only
|
|
||||||
* the portion of the item that falls within the given dirty
|
|
||||||
* rectangle is actually drawn.
|
|
||||||
*/
|
|
||||||
public void paint (Graphics2D gfx, Rectangle clip)
|
|
||||||
{
|
|
||||||
Shape oclip = gfx.getClip();
|
|
||||||
|
|
||||||
// clip the draw region to the dirty portion of the item
|
|
||||||
gfx.clip(clip);
|
|
||||||
|
|
||||||
// paint the item
|
|
||||||
if (obj instanceof Sprite) {
|
|
||||||
((Sprite)obj).paint(gfx);
|
|
||||||
} else {
|
|
||||||
((ObjectTile)obj).paint(gfx, bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore original clipping region
|
|
||||||
gfx.setClip(oclip);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString ()
|
|
||||||
{
|
|
||||||
return "[obj=" + obj + ", x=" + x + ", y=" + y + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: LineSegmentPath.java,v 1.11 2001/10/12 00:36:03 shaper Exp $
|
// $Id: LineSegmentPath.java,v 1.12 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.media.sprite;
|
package com.threerings.media.sprite;
|
||||||
|
|
||||||
@@ -9,21 +9,22 @@ import java.awt.Graphics2D;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
import com.threerings.media.util.MathUtil;
|
import com.threerings.media.util.MathUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>LineSegmentPath</code> class is used to cause a sprite to
|
* The line segment path is used to cause a sprite to follow a path
|
||||||
* follow a path that is made up of a sequence of line segments. There
|
* that is made up of a sequence of line segments. There must be at
|
||||||
* must be at least two nodes in any worthwhile path. The direction of the
|
* least two nodes in any worthwhile path. The direction of the first
|
||||||
* first node in the path is meaningless since the sprite begins at that
|
* node in the path is meaningless since the sprite begins at that
|
||||||
* node and will therefore never be heading towards it.
|
* node and will therefore never be heading towards it.
|
||||||
*/
|
*/
|
||||||
public class LineSegmentPath implements Path
|
public class LineSegmentPath implements Path
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Construct a <code>LineSegmentPath</code> object.
|
* Constructs a line segment path.
|
||||||
*/
|
*/
|
||||||
public LineSegmentPath ()
|
public LineSegmentPath ()
|
||||||
{
|
{
|
||||||
@@ -31,45 +32,17 @@ public class LineSegmentPath implements Path
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a <code>LineSegmentPath</code> object with the specified
|
* Constructs a line segment path with the specified list of
|
||||||
* starting node coordinates. An arbitrary direction will be assigned
|
* points. An arbitrary direction will be assigned to the
|
||||||
* to the starting node.
|
* starting node.
|
||||||
*
|
*
|
||||||
* @param x the starting node x-position.
|
* @param x the starting node x-position.
|
||||||
* @param y the starting node y-position.
|
* @param y the starting node y-position.
|
||||||
*/
|
*/
|
||||||
public LineSegmentPath (int x, int y)
|
public LineSegmentPath (List points)
|
||||||
{
|
{
|
||||||
_nodes = new ArrayList();
|
_nodes = new ArrayList();
|
||||||
|
createPath(points);
|
||||||
// add the starting node with an arbitrarily chosen direction
|
|
||||||
// since direction is meaningless here
|
|
||||||
addNode(x, y, Sprite.DIR_NORTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a node to the path with the specified destination point and
|
|
||||||
* facing direction.
|
|
||||||
*
|
|
||||||
* @param x the x-position.
|
|
||||||
* @param y the y-position.
|
|
||||||
* @param dir the facing direction.
|
|
||||||
*/
|
|
||||||
public void addNode (int x, int y, int dir)
|
|
||||||
{
|
|
||||||
_nodes.add(new PathNode(x, y, dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a node to the path with the specified destination point. An
|
|
||||||
* arbitrary direction will be assigned to the node.
|
|
||||||
*
|
|
||||||
* @param x the x-position.
|
|
||||||
* @param y the y-position.
|
|
||||||
*/
|
|
||||||
public void addNode (int x, int y)
|
|
||||||
{
|
|
||||||
_nodes.add(new PathNode(x, y, Sprite.DIR_NORTH));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +105,7 @@ public class LineSegmentPath implements Path
|
|||||||
_niter = _nodes.iterator();
|
_niter = _nodes.iterator();
|
||||||
|
|
||||||
// pretend like we were previously heading to our starting position
|
// pretend like we were previously heading to our starting position
|
||||||
_dest = (PathNode)_niter.next();
|
_dest = getNextNode();
|
||||||
|
|
||||||
// begin traversing the path
|
// begin traversing the path
|
||||||
headToNextNode(sprite, timestamp, timestamp);
|
headToNextNode(sprite, timestamp, timestamp);
|
||||||
@@ -169,6 +142,12 @@ public class LineSegmentPath implements Path
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
protected boolean headToNextNode (Sprite sprite, long startstamp, long now)
|
protected boolean headToNextNode (Sprite sprite, long startstamp, long now)
|
||||||
{
|
{
|
||||||
// check to see if we've completed our path
|
// check to see if we've completed our path
|
||||||
@@ -183,7 +162,7 @@ public class LineSegmentPath implements Path
|
|||||||
_src = _dest;
|
_src = _dest;
|
||||||
|
|
||||||
// pop the next node off the path
|
// pop the next node off the path
|
||||||
_dest = (PathNode)_niter.next();
|
_dest = getNextNode();
|
||||||
|
|
||||||
// adjust the sprite's orientation
|
// adjust the sprite's orientation
|
||||||
sprite.setOrientation(_dest.dir);
|
sprite.setOrientation(_dest.dir);
|
||||||
@@ -205,6 +184,7 @@ public class LineSegmentPath implements Path
|
|||||||
return updatePosition(sprite, now);
|
return updatePosition(sprite, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
public void paint (Graphics2D gfx)
|
public void paint (Graphics2D gfx)
|
||||||
{
|
{
|
||||||
gfx.setColor(Color.red);
|
gfx.setColor(Color.red);
|
||||||
@@ -219,11 +199,79 @@ public class LineSegmentPath implements Path
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return StringUtil.toString(_nodes.iterator());
|
return StringUtil.toString(_nodes.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the path with the path nodes that lead the sprite from
|
||||||
|
* its starting position to the given destination coordinates
|
||||||
|
* following the given list of screen coordinates.
|
||||||
|
*/
|
||||||
|
protected void createPath (List points)
|
||||||
|
{
|
||||||
|
Point last = null;
|
||||||
|
int size = points.size();
|
||||||
|
for (int ii = 0; ii < size; ii++) {
|
||||||
|
Point p = (Point)points.get(ii);
|
||||||
|
|
||||||
|
int dir = (ii == 0) ? Sprite.DIR_NORTH : getDirection(last, p);
|
||||||
|
addNode(p.x, p.y, dir);
|
||||||
|
last = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a node to the path with the specified destination point and
|
||||||
|
* facing direction.
|
||||||
|
*
|
||||||
|
* @param x the x-position.
|
||||||
|
* @param y the y-position.
|
||||||
|
* @param dir the facing direction.
|
||||||
|
*/
|
||||||
|
protected void addNode (int x, int y, int dir)
|
||||||
|
{
|
||||||
|
_nodes.add(new PathNode(x, y, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next node in the path.
|
||||||
|
*/
|
||||||
|
protected PathNode getNextNode ()
|
||||||
|
{
|
||||||
|
return (PathNode)_niter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the direction that point <code>b</code> lies in from
|
||||||
|
* point <code>a</code> as one of the <code>Sprite</code>
|
||||||
|
* direction constants.
|
||||||
|
*/
|
||||||
|
protected int getDirection (Point a, Point b)
|
||||||
|
{
|
||||||
|
if (a.x == b.x && a.y > b.y) {
|
||||||
|
return Sprite.DIR_NORTH;
|
||||||
|
} else if (a.x < b.x && a.y > b.y) {
|
||||||
|
return Sprite.DIR_NORTHEAST;
|
||||||
|
} else if (a.x > b.x && a.y == b.y) {
|
||||||
|
return Sprite.DIR_EAST;
|
||||||
|
} else if (a.x > b.x && a.y < b.y) {
|
||||||
|
return Sprite.DIR_SOUTHEAST;
|
||||||
|
} else if (a.x == b.x && a.y < b.y) {
|
||||||
|
return Sprite.DIR_SOUTH;
|
||||||
|
} else if (a.x > b.x && a.y < b.y) {
|
||||||
|
return Sprite.DIR_SOUTHWEST;
|
||||||
|
} else if (a.x > b.x && a.y == b.y) {
|
||||||
|
return Sprite.DIR_WEST;
|
||||||
|
} else if (a.x > b.x && a.y > b.y) {
|
||||||
|
return Sprite.DIR_NORTHWEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sprite.DIR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/** The nodes that make up the path. */
|
/** The nodes that make up the path. */
|
||||||
protected ArrayList _nodes;
|
protected ArrayList _nodes;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: PathNode.java,v 1.5 2001/09/05 00:40:33 shaper Exp $
|
// $Id: PathNode.java,v 1.6 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.media.sprite;
|
package com.threerings.media.sprite;
|
||||||
|
|
||||||
@@ -35,9 +35,20 @@ public class PathNode
|
|||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
buf.append("[x=").append(loc.x);
|
buf.append("[");
|
||||||
buf.append(", y=").append(loc.y);
|
toString(buf);
|
||||||
buf.append(", dir=").append(dir);
|
|
||||||
return buf.append("]").toString();
|
return buf.append("]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be overridden by derived classes (which should be sure
|
||||||
|
* to call <code>super.toString()</code>) to append the derived class
|
||||||
|
* specific path node information to the string buffer.
|
||||||
|
*/
|
||||||
|
public void toString (StringBuffer buf)
|
||||||
|
{
|
||||||
|
buf.append("x=").append(loc.x);
|
||||||
|
buf.append(", y=").append(loc.y);
|
||||||
|
buf.append(", dir=").append(dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
//
|
||||||
|
// $Id: DirtyItemList.java,v 1.1 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.threerings.media.sprite.Sprite;
|
||||||
|
import com.threerings.media.tile.ObjectTile;
|
||||||
|
|
||||||
|
import com.threerings.media.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dirty item list keeps track of dirty sprites and object tiles
|
||||||
|
* in a scene.
|
||||||
|
*/
|
||||||
|
public class DirtyItemList extends ArrayList
|
||||||
|
{
|
||||||
|
/** The dirty item comparator used to sort dirty items back to front. */
|
||||||
|
public static final Comparator DIRTY_COMP = new DirtyItemComparator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the dirty sprite at the given coordinates to the dirty
|
||||||
|
* item list.
|
||||||
|
*/
|
||||||
|
public void appendDirtySprite (
|
||||||
|
Sprite sprite, int x, int y, Rectangle dirtyRect)
|
||||||
|
{
|
||||||
|
add(new DirtyItem(sprite, null, x, y, dirtyRect));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the dirty object tile at the given coordinates to the
|
||||||
|
* dirty item list.
|
||||||
|
*/
|
||||||
|
public void appendDirtyObject (
|
||||||
|
ObjectTile tile, Shape bounds, int x, int y, Rectangle dirtyRect)
|
||||||
|
{
|
||||||
|
add(new DirtyItem(tile, bounds, x, y, dirtyRect));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of the {@link DirtyItem} objects in the list
|
||||||
|
* sorted with the {@link DirtyItemComparator}.
|
||||||
|
*/
|
||||||
|
public DirtyItem[] sort ()
|
||||||
|
{
|
||||||
|
DirtyItem items[] = new DirtyItem[size()];
|
||||||
|
toArray(items);
|
||||||
|
Arrays.sort(items, DirtyItemList.DIRTY_COMP);
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to hold the items inserted in the dirty list along with
|
||||||
|
* all of the information necessary to render their dirty regions
|
||||||
|
* to the target graphics context when the time comes to do so.
|
||||||
|
*/
|
||||||
|
public class DirtyItem
|
||||||
|
{
|
||||||
|
public Object obj;
|
||||||
|
public Shape bounds;
|
||||||
|
public int x, y;
|
||||||
|
public Rectangle dirtyRect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a dirty item.
|
||||||
|
*/
|
||||||
|
public DirtyItem (
|
||||||
|
Object obj, Shape bounds, int x, int y, Rectangle dirtyRect)
|
||||||
|
{
|
||||||
|
this.obj = obj;
|
||||||
|
this.bounds = bounds;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.dirtyRect = dirtyRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paints the dirty item to the given graphics context. Only
|
||||||
|
* the portion of the item that falls within the given dirty
|
||||||
|
* rectangle is actually drawn.
|
||||||
|
*/
|
||||||
|
public void paint (Graphics2D gfx, Rectangle clip)
|
||||||
|
{
|
||||||
|
Shape oclip = gfx.getClip();
|
||||||
|
|
||||||
|
// clip the draw region to the dirty portion of the item
|
||||||
|
gfx.clip(clip);
|
||||||
|
|
||||||
|
// paint the item
|
||||||
|
if (obj instanceof Sprite) {
|
||||||
|
((Sprite)obj).paint(gfx);
|
||||||
|
} else {
|
||||||
|
((ObjectTile)obj).paint(gfx, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore original clipping region
|
||||||
|
gfx.setClip(oclip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
// we're never equal to something that's not our kind
|
||||||
|
if (!(other instanceof DirtyItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sprites are equivalent if they're the same sprite
|
||||||
|
DirtyItem b = (DirtyItem)other;
|
||||||
|
if ((obj instanceof Sprite) && (b.obj instanceof Sprite)) {
|
||||||
|
return (obj == b.obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// object-to-object or object-to-sprite are distinguished
|
||||||
|
// simply by tile coordinate since they can never occupy
|
||||||
|
// the same tile
|
||||||
|
return (x == b.x && y == b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[obj=" + obj + ", x=" + x + ", y=" + y +
|
||||||
|
", drect=" + dirtyRect + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A comparator class for use in sorting the dirty sprites and
|
||||||
|
* objects in a scene in ascending x- and y-coordinate order
|
||||||
|
* suitable for rendering in the isometric view with proper visual
|
||||||
|
* results.
|
||||||
|
*/
|
||||||
|
public static class DirtyItemComparator implements Comparator
|
||||||
|
{
|
||||||
|
public int compare (Object a, Object b)
|
||||||
|
{
|
||||||
|
DirtyItem da = (DirtyItem)a;
|
||||||
|
DirtyItem db = (DirtyItem)b;
|
||||||
|
|
||||||
|
if (da.x == db.x &&
|
||||||
|
da.y == db.y &&
|
||||||
|
da.obj != db.obj) {
|
||||||
|
// we're comparing two sprites co-existing on the same
|
||||||
|
// tile, so study their fine coordinates to determine
|
||||||
|
// rendering order
|
||||||
|
AmbulatorySprite as = (AmbulatorySprite)da.obj;
|
||||||
|
AmbulatorySprite bs = (AmbulatorySprite)db.obj;
|
||||||
|
|
||||||
|
int aloc = as.getFineX() + as.getFineY();
|
||||||
|
int bloc = bs.getFineX() + bs.getFineY();
|
||||||
|
|
||||||
|
if (aloc < bloc) {
|
||||||
|
return -1;
|
||||||
|
} else if (aloc > bloc) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// if they're at the same vertical row of
|
||||||
|
// intra-tile tiles, just use something consistent
|
||||||
|
return as.hashCode() - bs.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether right edge of a overlaps with left edge of b
|
||||||
|
int comp = getRightOverlap(da, db);
|
||||||
|
if (comp != 0) {
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether right edge of b overlaps with left edge of a
|
||||||
|
comp = getRightOverlap(db, da);
|
||||||
|
if (comp != 0) {
|
||||||
|
// reverse ordering per reversed overlap check
|
||||||
|
return (comp == -1) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine ordering based purely on coordinates
|
||||||
|
if (da.x <= db.x && da.y <= db.y) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Object obj)
|
||||||
|
{
|
||||||
|
return (obj == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the right edge of <code>da</code> to see whether it
|
||||||
|
* overlaps with the left edge of <code>db</code>.
|
||||||
|
*
|
||||||
|
* @return -1 if <code>da</code> should be rendered behind
|
||||||
|
* <code>db</code>, 0 if the right edge of <code>da</code>
|
||||||
|
* does not overlap with <code>db</code>, and 1 if
|
||||||
|
* <code>da</code> should be rendered in front of
|
||||||
|
* <code>db</code>.
|
||||||
|
*/
|
||||||
|
protected int getRightOverlap (DirtyItem da, DirtyItem db)
|
||||||
|
{
|
||||||
|
int ax = da.x, bx = db.x;
|
||||||
|
int ay = da.y, by = db.y;
|
||||||
|
|
||||||
|
// get da's rightmost corner coordinate
|
||||||
|
if (da.obj instanceof ObjectTile) {
|
||||||
|
ay -= (((ObjectTile)da.obj).baseHeight - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get db's leftmost corner coordinate
|
||||||
|
if (db.obj instanceof ObjectTile) {
|
||||||
|
bx -= (((ObjectTile)db.obj).baseWidth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ax < bx && ay > by) {
|
||||||
|
// we most certainly don't overlap
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate inequality constant for db's leftmost corner
|
||||||
|
int k = (bx + by);
|
||||||
|
|
||||||
|
// we need to determine whether to render da in front of
|
||||||
|
// db, so we check whether da's rightmost corner is above
|
||||||
|
// or below db's leftmost corner.
|
||||||
|
if (ay <= k - ax) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: IsoSceneView.java,v 1.66 2001/10/23 02:04:07 shaper Exp $
|
// $Id: IsoSceneView.java,v 1.67 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -13,21 +13,21 @@ import java.util.*;
|
|||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
|
|
||||||
import com.threerings.media.sprite.*;
|
import com.threerings.media.sprite.*;
|
||||||
import com.threerings.media.sprite.DirtyItemList.DirtyItem;
|
|
||||||
import com.threerings.media.tile.Tile;
|
import com.threerings.media.tile.Tile;
|
||||||
import com.threerings.media.tile.ObjectTile;
|
import com.threerings.media.tile.ObjectTile;
|
||||||
|
|
||||||
import com.threerings.miso.Log;
|
import com.threerings.miso.Log;
|
||||||
|
import com.threerings.miso.scene.DirtyItemList.DirtyItem;
|
||||||
import com.threerings.miso.scene.util.*;
|
import com.threerings.miso.scene.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>IsoSceneView</code> provides an isometric view of a
|
* The iso scene view provides an isometric view of a particular
|
||||||
* particular scene.
|
* scene.
|
||||||
*/
|
*/
|
||||||
public class IsoSceneView implements SceneView
|
public class IsoSceneView implements SceneView
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Construct an <code>IsoSceneView</code> object.
|
* Constructs an iso scene view.
|
||||||
*
|
*
|
||||||
* @param spritemgr the sprite manager.
|
* @param spritemgr the sprite manager.
|
||||||
* @param model the data model.
|
* @param model the data model.
|
||||||
@@ -190,7 +190,7 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the scene to the given graphics context.
|
* Renders the scene to the given graphics context.
|
||||||
*
|
*
|
||||||
* @param gfx the graphics context.
|
* @param gfx the graphics context.
|
||||||
*/
|
*/
|
||||||
@@ -236,21 +236,19 @@ public class IsoSceneView implements SceneView
|
|||||||
*/
|
*/
|
||||||
protected void renderDirtyItems (Graphics2D gfx)
|
protected void renderDirtyItems (Graphics2D gfx)
|
||||||
{
|
{
|
||||||
|
// Log.info("renderDirtyItems");
|
||||||
|
|
||||||
// sort the dirty sprites and objects visually back-to-front
|
// sort the dirty sprites and objects visually back-to-front
|
||||||
int size = _dirtyItems.size();
|
DirtyItem items[] = _dirtyItems.sort();
|
||||||
DirtyItem items[] = new DirtyItem[size];
|
|
||||||
_dirtyItems.toArray(items);
|
|
||||||
Arrays.sort(items, IsoUtil.DIRTY_COMP);
|
|
||||||
|
|
||||||
// merge all dirty rectangles for each item into a single
|
// merge all dirty rectangles for each item into a single
|
||||||
// rectangle before painting
|
// rectangle before painting
|
||||||
Rectangle dirtyRect = new Rectangle();
|
Rectangle dirtyRect = new Rectangle();
|
||||||
DirtyItem cur = null, last = null;
|
DirtyItem cur = null, last = null;
|
||||||
for (int ii = 0; ii < size; ii++) {
|
for (int ii = 0; ii < items.length; ii++) {
|
||||||
cur = items[ii];
|
cur = items[ii];
|
||||||
|
|
||||||
if (last == null ||
|
if (last == null || !cur.equals(last)) {
|
||||||
(cur.x != last.x || cur.y != last.y)) {
|
|
||||||
|
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
// paint the item with its full dirty rectangle
|
// paint the item with its full dirty rectangle
|
||||||
@@ -590,16 +588,13 @@ public class IsoSceneView implements SceneView
|
|||||||
|
|
||||||
int size = _dirtySprites.size();
|
int size = _dirtySprites.size();
|
||||||
for (int ii = 0; ii < size; ii++) {
|
for (int ii = 0; ii < size; ii++) {
|
||||||
Sprite sprite = (Sprite)_dirtySprites.get(ii);
|
AmbulatorySprite sprite = (AmbulatorySprite)_dirtySprites.get(ii);
|
||||||
|
|
||||||
// get the sprite's position in tile coordinates
|
|
||||||
Point tpos = new Point();
|
|
||||||
IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), tpos);
|
|
||||||
|
|
||||||
// get the dirty portion of the sprite
|
// get the dirty portion of the sprite
|
||||||
Rectangle drect = sprite.getBounds().intersection(r);
|
Rectangle drect = sprite.getBounds().intersection(r);
|
||||||
|
|
||||||
_dirtyItems.appendDirtySprite(sprite, tpos.x, tpos.y, drect);
|
_dirtyItems.appendDirtySprite(
|
||||||
|
sprite, sprite.getTileX(), sprite.getTileY(), drect);
|
||||||
// Log.info("Dirtied item: " + sprite);
|
// Log.info("Dirtied item: " + sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,78 +628,18 @@ public class IsoSceneView implements SceneView
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// constrain destination pixels to fine coordinates
|
// get the destination tile coordinates
|
||||||
Point fpos = new Point();
|
Point dest = new Point();
|
||||||
IsoUtil.screenToFull(_model, x, y, fpos);
|
IsoUtil.screenToTile(_model, x, y, dest);
|
||||||
|
|
||||||
// calculate tile coordinates for start and end position
|
// get a reasonable tile path through the scene
|
||||||
Point stpos = new Point();
|
List points = AStarPathUtil.getPath(
|
||||||
IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), stpos);
|
|
||||||
int tbx = IsoUtil.fullToTile(fpos.x);
|
|
||||||
int tby = IsoUtil.fullToTile(fpos.y);
|
|
||||||
|
|
||||||
// Log.info("Seeking path [sx=" + stpos.x + ", sy=" + stpos.y +
|
|
||||||
// ", dx=" + tbx + ", dy=" + tby + " ,fdx=" + fpos.x +
|
|
||||||
// ", fdy=" + fpos.y + "].");
|
|
||||||
|
|
||||||
// get a reasonable path from start to end
|
|
||||||
List tilepath = AStarPathUtil.getPath(
|
|
||||||
_scene.getBaseLayer(), _model.scenewid, _model.scenehei,
|
_scene.getBaseLayer(), _model.scenewid, _model.scenehei,
|
||||||
sprite, stpos.x, stpos.y, tbx, tby);
|
sprite, sprite.getTileX(), sprite.getTileY(), dest.x, dest.y);
|
||||||
if (tilepath == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make more visually appealing path segments from start
|
// construct a path object to guide the sprite on its merry way
|
||||||
// to second tile, and penultimate to ultimate tile.
|
return (points == null) ? null :
|
||||||
|
new TilePath(_model, sprite, points, x, y);
|
||||||
// construct path with starting screen position
|
|
||||||
LineSegmentPath path =
|
|
||||||
new LineSegmentPath(sprite.getX(), sprite.getY());
|
|
||||||
|
|
||||||
// add all nodes on the calculated path
|
|
||||||
Point nspos = new Point();
|
|
||||||
Point prev = stpos;
|
|
||||||
int size = tilepath.size();
|
|
||||||
for (int ii = 1; ii < size - 1; ii++) {
|
|
||||||
Point n = (Point)tilepath.get(ii);
|
|
||||||
|
|
||||||
// determine the direction this node lies in from the
|
|
||||||
// previous node
|
|
||||||
int dir = IsoUtil.getIsoDirection(prev.x, prev.y, n.x, n.y);
|
|
||||||
|
|
||||||
// determine the node's position in screen pixel coordinates
|
|
||||||
IsoUtil.tileToScreen(_model, n.x, n.y, nspos);
|
|
||||||
|
|
||||||
// add the node to the path, wandering through the middle
|
|
||||||
// of each tile in the path for now
|
|
||||||
path.addNode(nspos.x + _model.tilehwid,
|
|
||||||
nspos.y + _model.tilehhei, dir);
|
|
||||||
|
|
||||||
prev = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the final destination point's screen coordinates
|
|
||||||
// constrained to the closest full coordinate
|
|
||||||
Point spos = new Point();
|
|
||||||
IsoUtil.fullToScreen(_model, fpos.x, fpos.y, spos);
|
|
||||||
|
|
||||||
// get the direction we're to face while heading toward the end
|
|
||||||
int dir;
|
|
||||||
if (prev == stpos) {
|
|
||||||
// if our destination is within our origination tile,
|
|
||||||
// direction is based on fine coordinates
|
|
||||||
dir = IsoUtil.getDirection(
|
|
||||||
_model, sprite.getX(), sprite.getY(), spos.x, spos.y);
|
|
||||||
} else {
|
|
||||||
// else it's based on the last tile we traversed
|
|
||||||
dir = IsoUtil.getIsoDirection(prev.x, prev.y, tbx, tby);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the final destination path node
|
|
||||||
path.addNode(spos.x, spos.y, dir);
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The stroke used to draw dirty rectangles. */
|
/** The stroke used to draw dirty rectangles. */
|
||||||
|
|||||||
@@ -0,0 +1,185 @@
|
|||||||
|
//
|
||||||
|
// $Id: TilePath.java,v 1.1 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.threerings.media.sprite.*;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public class TilePath extends LineSegmentPath
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a tile path.
|
||||||
|
*
|
||||||
|
* @param model the iso scene view model the path is associated with.
|
||||||
|
* @param sprite the sprite to follow the path.
|
||||||
|
* @param tiles the tiles to be traversed during the path.
|
||||||
|
* @param destx the destination x-position in screen pixel
|
||||||
|
* coordinates.
|
||||||
|
* @param desty the destination y-position in screen pixel
|
||||||
|
* coordinates.
|
||||||
|
*/
|
||||||
|
public TilePath (
|
||||||
|
IsoSceneViewModel model, AmbulatorySprite sprite, List tiles,
|
||||||
|
int destx, int desty)
|
||||||
|
{
|
||||||
|
_model = model;
|
||||||
|
|
||||||
|
// set up the path nodes
|
||||||
|
createPath(sprite, tiles, destx, desty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public boolean updatePosition (Sprite sprite, long timestamp)
|
||||||
|
{
|
||||||
|
boolean moved = super.updatePosition(sprite, timestamp);
|
||||||
|
|
||||||
|
if (moved) {
|
||||||
|
AmbulatorySprite as = (AmbulatorySprite)sprite;
|
||||||
|
int sx = sprite.getX(), sy = sprite.getY();
|
||||||
|
Point pos = new Point();
|
||||||
|
|
||||||
|
// check whether we've arrived at the destination tile
|
||||||
|
if (!_arrived) {
|
||||||
|
// get the sprite's latest tile coordinates
|
||||||
|
IsoUtil.screenToTile(_model, sx, sy, pos);
|
||||||
|
|
||||||
|
// if the sprite has reached the destination tile,
|
||||||
|
// update the sprite's tile location and remember
|
||||||
|
// we've arrived
|
||||||
|
int dtx = _dest.getTileX(), dty = _dest.getTileY();
|
||||||
|
if (pos.x == dtx && pos.y == dty) {
|
||||||
|
as.setTileLocation(dtx, dty);
|
||||||
|
// Log.info("Sprite arrived [dtx=" + dtx +
|
||||||
|
// ", dty=" + dty + "].");
|
||||||
|
_arrived = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the sprite's latest fine coordinates
|
||||||
|
IsoUtil.tileToScreen(_model, as.getTileX(), as.getTileY(), pos);
|
||||||
|
Point fpos = new Point();
|
||||||
|
IsoUtil.pixelToFine(_model, sx - pos.x, sy - pos.y, fpos);
|
||||||
|
|
||||||
|
// inform the sprite
|
||||||
|
as.setFineLocation(fpos.x, fpos.y);
|
||||||
|
|
||||||
|
// Log.info("Sprite moved [s=" + as + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected PathNode getNextNode ()
|
||||||
|
{
|
||||||
|
// upgrade the path node to a tile path node
|
||||||
|
_dest = (TilePathNode)super.getNextNode();
|
||||||
|
|
||||||
|
// note that we've not yet arrived at the destination tile
|
||||||
|
_arrived = false;
|
||||||
|
|
||||||
|
return _dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the path with the tile path nodes that lead the sprite
|
||||||
|
* from its starting position to the given destination coordinates
|
||||||
|
* following the given list of tile coordinates.
|
||||||
|
*/
|
||||||
|
protected void createPath (
|
||||||
|
AmbulatorySprite sprite, List tiles, int destx, int desty)
|
||||||
|
{
|
||||||
|
// constrain destination pixels to fine coordinates
|
||||||
|
Point fpos = new Point();
|
||||||
|
IsoUtil.screenToFull(_model, destx, desty, fpos);
|
||||||
|
|
||||||
|
// add the starting path node
|
||||||
|
int stx = sprite.getTileX(), sty = sprite.getTileY();
|
||||||
|
int sx = sprite.getX(), sy = sprite.getY();
|
||||||
|
addNode(stx, sty, sx, sy, Sprite.DIR_NORTH);
|
||||||
|
|
||||||
|
// TODO: make more visually appealing path segments from start
|
||||||
|
// to second tile, and penultimate to ultimate tile.
|
||||||
|
|
||||||
|
// add all remaining path nodes excepting the last one
|
||||||
|
Point prev = new Point(stx, sty);
|
||||||
|
Point spos = new Point();
|
||||||
|
int size = tiles.size();
|
||||||
|
for (int ii = 1; ii < size - 1; ii++) {
|
||||||
|
Point next = (Point)tiles.get(ii);
|
||||||
|
|
||||||
|
// determine the direction from previous to next node
|
||||||
|
int dir = IsoUtil.getIsoDirection(prev.x, prev.y, next.x, next.y);
|
||||||
|
|
||||||
|
// determine the node's position in screen pixel coordinates
|
||||||
|
IsoUtil.tileToScreen(_model, next.x, next.y, spos);
|
||||||
|
|
||||||
|
// add the node to the path, wandering through the middle
|
||||||
|
// of each tile in the path for now
|
||||||
|
int dsx = spos.x + _model.tilehwid;
|
||||||
|
int dsy = spos.y + _model.tilehhei;
|
||||||
|
addNode(next.x, next.y, dsx, dsy, dir);
|
||||||
|
|
||||||
|
prev = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the final destination point's screen coordinates
|
||||||
|
// constrained to the closest full coordinate
|
||||||
|
IsoUtil.fullToScreen(_model, fpos.x, fpos.y, spos);
|
||||||
|
|
||||||
|
// get the tile coordinates for the final destination tile
|
||||||
|
int tdestx = IsoUtil.fullToTile(fpos.x);
|
||||||
|
int tdesty = IsoUtil.fullToTile(fpos.y);
|
||||||
|
|
||||||
|
// get the facing direction for the final node
|
||||||
|
int dir;
|
||||||
|
if (prev.x == stx && prev.y == sty) {
|
||||||
|
// if destination is within starting tile, direction is
|
||||||
|
// determined by studying the fine coordinates
|
||||||
|
dir = IsoUtil.getDirection(_model, sx, sy, spos.x, spos.y);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// else it's based on the last tile we traversed
|
||||||
|
dir = IsoUtil.getIsoDirection(prev.x, prev.y, tdestx, tdesty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the final destination path node
|
||||||
|
addNode(tdestx, tdesty, spos.x, spos.y, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a node to the path with the specified destination
|
||||||
|
* coordinates and facing direction.
|
||||||
|
*
|
||||||
|
* @param tx the tile x-position.
|
||||||
|
* @param ty the tile y-position.
|
||||||
|
* @param x the x-position.
|
||||||
|
* @param y the y-position.
|
||||||
|
* @param dir the facing direction.
|
||||||
|
*/
|
||||||
|
protected void addNode (int tx, int ty, int x, int y, int dir)
|
||||||
|
{
|
||||||
|
_nodes.add(new TilePathNode(tx, ty, x, y, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the sprite has arrived at the current destination tile. */
|
||||||
|
protected boolean _arrived;
|
||||||
|
|
||||||
|
/** The destination tile path node. */
|
||||||
|
protected TilePathNode _dest;
|
||||||
|
|
||||||
|
/** The iso scene view model. */
|
||||||
|
protected IsoSceneViewModel _model;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// $Id: TilePathNode.java,v 1.1 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
|
import com.threerings.media.sprite.PathNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tile path nodes extends the path node class to allow
|
||||||
|
* associating tile coordinates with a node in a path.
|
||||||
|
*/
|
||||||
|
public class TilePathNode extends PathNode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a tile path node.
|
||||||
|
*/
|
||||||
|
public TilePathNode (int tilex, int tiley, int x, int y, int dir)
|
||||||
|
{
|
||||||
|
super(x, y, dir);
|
||||||
|
|
||||||
|
_tilex = tilex;
|
||||||
|
_tiley = tiley;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node's x-axis tile coordinates.
|
||||||
|
*/
|
||||||
|
public int getTileX ()
|
||||||
|
{
|
||||||
|
return _tilex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node's y-axis tile coordinates.
|
||||||
|
*/
|
||||||
|
public int getTileY ()
|
||||||
|
{
|
||||||
|
return _tiley;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void toString (StringBuffer buf)
|
||||||
|
{
|
||||||
|
super.toString(buf);
|
||||||
|
buf.append(", tilex=").append(_tilex);
|
||||||
|
buf.append(", tiley=").append(_tiley);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The path node tile coordinates. */
|
||||||
|
protected int _tilex, _tiley;
|
||||||
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
//
|
//
|
||||||
// $Id: IsoUtil.java,v 1.12 2001/10/22 18:21:41 shaper Exp $
|
// $Id: IsoUtil.java,v 1.13 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene.util;
|
package com.threerings.miso.scene.util;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
import com.threerings.media.sprite.Sprite;
|
import com.threerings.media.sprite.Sprite;
|
||||||
import com.threerings.media.sprite.DirtyItemList.DirtyItem;
|
|
||||||
import com.threerings.media.tile.ObjectTile;
|
import com.threerings.media.tile.ObjectTile;
|
||||||
import com.threerings.media.util.MathUtil;
|
import com.threerings.media.util.MathUtil;
|
||||||
|
|
||||||
@@ -20,9 +18,6 @@ import com.threerings.miso.scene.*;
|
|||||||
*/
|
*/
|
||||||
public class IsoUtil
|
public class IsoUtil
|
||||||
{
|
{
|
||||||
/** The dirty item comparator used to sort dirty items back to front. */
|
|
||||||
public static final Comparator DIRTY_COMP = new DirtyItemComparator();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a polygon bounding all footprint tiles of the given
|
* Returns a polygon bounding all footprint tiles of the given
|
||||||
* object tile.
|
* object tile.
|
||||||
@@ -399,87 +394,4 @@ public class IsoUtil
|
|||||||
|
|
||||||
/** Multiplication factor to embed tile coords in full coords. */
|
/** Multiplication factor to embed tile coords in full coords. */
|
||||||
protected static final int FULL_TILE_FACTOR = 100;
|
protected static final int FULL_TILE_FACTOR = 100;
|
||||||
|
|
||||||
/**
|
|
||||||
* A comparator class for use in sorting the dirty sprites and
|
|
||||||
* objects in a scene in ascending x- and y-coordinate order
|
|
||||||
* suitable for rendering in the isometric view with proper visual
|
|
||||||
* results.
|
|
||||||
*/
|
|
||||||
public static class DirtyItemComparator implements Comparator
|
|
||||||
{
|
|
||||||
public int compare (Object a, Object b)
|
|
||||||
{
|
|
||||||
DirtyItem da = (DirtyItem)a;
|
|
||||||
DirtyItem db = (DirtyItem)b;
|
|
||||||
|
|
||||||
// check whether right edge of a overlaps with left edge of b
|
|
||||||
int comp = getRightOverlap(da, db);
|
|
||||||
if (comp != 0) {
|
|
||||||
return comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether right edge of b overlaps with left edge of a
|
|
||||||
comp = getRightOverlap(db, da);
|
|
||||||
if (comp != 0) {
|
|
||||||
// reverse ordering per reversed overlap check
|
|
||||||
return (comp == -1) ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine ordering based purely on coordinates
|
|
||||||
if (da.x <= db.x && da.y <= db.y) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals (Object obj)
|
|
||||||
{
|
|
||||||
return (obj == this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks the right edge of <code>da</code> to see whether it
|
|
||||||
* overlaps with the left edge of <code>db</code>.
|
|
||||||
*
|
|
||||||
* @return -1 if <code>da</code> should be rendered behind
|
|
||||||
* <code>db</code>, 0 if the right edge of <code>da</code>
|
|
||||||
* does not overlap with <code>db</code>, and 1 if
|
|
||||||
* <code>da</code> should be rendered in front of
|
|
||||||
* <code>db</code>.
|
|
||||||
*/
|
|
||||||
protected int getRightOverlap (DirtyItem da, DirtyItem db)
|
|
||||||
{
|
|
||||||
int ax = da.x, bx = db.x;
|
|
||||||
int ay = da.y, by = db.y;
|
|
||||||
|
|
||||||
// get da's rightmost corner coordinate
|
|
||||||
if (da.obj instanceof ObjectTile) {
|
|
||||||
ay -= (((ObjectTile)da.obj).baseHeight - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get db's leftmost corner coordinate
|
|
||||||
if (db.obj instanceof ObjectTile) {
|
|
||||||
bx -= (((ObjectTile)db.obj).baseWidth - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ax < bx && ay > by) {
|
|
||||||
// we most certainly don't overlap
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate inequality constant for db's leftmost corner
|
|
||||||
int k = (bx + by);
|
|
||||||
|
|
||||||
// we need to determine whether to render da in front of
|
|
||||||
// db, so we check whether da's rightmost corner is above
|
|
||||||
// or below db's leftmost corner.
|
|
||||||
if (ay <= k - ax) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ViewerFrame.java,v 1.23 2001/10/23 02:03:49 shaper Exp $
|
// $Id: ViewerFrame.java,v 1.24 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.viewer;
|
package com.threerings.miso.viewer;
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@ import com.threerings.media.sprite.SpriteManager;
|
|||||||
import com.threerings.media.tile.TileManager;
|
import com.threerings.media.tile.TileManager;
|
||||||
|
|
||||||
import com.threerings.miso.Log;
|
import com.threerings.miso.Log;
|
||||||
import com.threerings.miso.scene.CharacterManager;
|
|
||||||
import com.threerings.miso.viewer.util.ViewerContext;
|
import com.threerings.miso.viewer.util.ViewerContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,13 +34,9 @@ public class ViewerFrame extends JFrame
|
|||||||
SpriteManager spritemgr = new SpriteManager();
|
SpriteManager spritemgr = new SpriteManager();
|
||||||
TileManager tilemgr = ctx.getTileManager();
|
TileManager tilemgr = ctx.getTileManager();
|
||||||
|
|
||||||
// construct the character manager from which we obtain our sprite
|
|
||||||
CharacterManager charmgr = new CharacterManager(
|
|
||||||
ctx.getConfig(), tilemgr);
|
|
||||||
|
|
||||||
// set up the scene view panel with a default scene
|
// set up the scene view panel with a default scene
|
||||||
ViewerSceneViewPanel svpanel =
|
ViewerSceneViewPanel svpanel =
|
||||||
new ViewerSceneViewPanel(ctx, spritemgr, charmgr);
|
new ViewerSceneViewPanel(ctx, spritemgr);
|
||||||
|
|
||||||
// add the main panel to the frame
|
// add the main panel to the frame
|
||||||
getContentPane().add(svpanel);
|
getContentPane().add(svpanel);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ViewerSceneViewPanel.java,v 1.20 2001/10/23 02:03:49 shaper Exp $
|
// $Id: ViewerSceneViewPanel.java,v 1.21 2001/10/24 00:55:08 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.miso.viewer;
|
package com.threerings.miso.viewer;
|
||||||
|
|
||||||
@@ -25,8 +25,7 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
/**
|
/**
|
||||||
* Construct the panel and initialize it with a context.
|
* Construct the panel and initialize it with a context.
|
||||||
*/
|
*/
|
||||||
public ViewerSceneViewPanel (
|
public ViewerSceneViewPanel (ViewerContext ctx, SpriteManager spritemgr)
|
||||||
ViewerContext ctx, SpriteManager spritemgr, CharacterManager charmgr)
|
|
||||||
{
|
{
|
||||||
super(ctx.getConfig(), spritemgr);
|
super(ctx.getConfig(), spritemgr);
|
||||||
|
|
||||||
@@ -35,6 +34,19 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
// create an animation manager for this panel
|
// create an animation manager for this panel
|
||||||
_animmgr = new AnimationManager(spritemgr, this);
|
_animmgr = new AnimationManager(spritemgr, this);
|
||||||
|
|
||||||
|
// load up the initial scene
|
||||||
|
prepareStartingScene();
|
||||||
|
|
||||||
|
// construct the character manager from which we obtain sprites
|
||||||
|
CharacterManager charmgr = new CharacterManager(
|
||||||
|
ctx.getConfig(), ctx.getTileManager(), _scenemodel);
|
||||||
|
|
||||||
|
// create the manipulable sprite
|
||||||
|
_sprite = createSprite(spritemgr, charmgr, TSID_CHAR_USER);
|
||||||
|
|
||||||
|
// create the decoy sprites
|
||||||
|
createDecoys(spritemgr, charmgr);
|
||||||
|
|
||||||
// listen to the desired events
|
// listen to the desired events
|
||||||
addMouseListener(new MouseAdapter() {
|
addMouseListener(new MouseAdapter() {
|
||||||
public void mousePressed (MouseEvent e) {
|
public void mousePressed (MouseEvent e) {
|
||||||
@@ -42,15 +54,6 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// load up the initial scene
|
|
||||||
prepareStartingScene();
|
|
||||||
|
|
||||||
// create the manipulable sprite
|
|
||||||
_sprite = createSprite(spritemgr, charmgr);
|
|
||||||
|
|
||||||
// create the decoy sprites
|
|
||||||
createDecoys(spritemgr, charmgr);
|
|
||||||
|
|
||||||
PerformanceMonitor.register(this, "paint", 1000);
|
PerformanceMonitor.register(this, "paint", 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +61,9 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
* Creates a new sprite.
|
* Creates a new sprite.
|
||||||
*/
|
*/
|
||||||
protected AmbulatorySprite createSprite (
|
protected AmbulatorySprite createSprite (
|
||||||
SpriteManager spritemgr, CharacterManager charmgr)
|
SpriteManager spritemgr, CharacterManager charmgr, int tsid)
|
||||||
{
|
{
|
||||||
AmbulatorySprite s = charmgr.getCharacter(TSID_CHAR);
|
AmbulatorySprite s = charmgr.getCharacter(tsid);
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
s.setLocation(300, 300);
|
s.setLocation(300, 300);
|
||||||
s.addSpriteObserver(this);
|
s.addSpriteObserver(this);
|
||||||
@@ -78,7 +81,8 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
{
|
{
|
||||||
_decoys = new AmbulatorySprite[NUM_DECOYS];
|
_decoys = new AmbulatorySprite[NUM_DECOYS];
|
||||||
for (int ii = 0; ii < NUM_DECOYS; ii++) {
|
for (int ii = 0; ii < NUM_DECOYS; ii++) {
|
||||||
if ((_decoys[ii] = createSprite(spritemgr, charmgr)) != null) {
|
_decoys[ii] = createSprite(spritemgr, charmgr, TSID_CHAR);
|
||||||
|
if (_decoys[ii] != null) {
|
||||||
createRandomPath(_decoys[ii]);
|
createRandomPath(_decoys[ii]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,8 +157,6 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
do {
|
do {
|
||||||
x = RandomUtil.getInt(d.width);
|
x = RandomUtil.getInt(d.width);
|
||||||
y = RandomUtil.getInt(d.height);
|
y = RandomUtil.getInt(d.height);
|
||||||
// Log.info("Moving sprite [s=" + s + ", x=" + x +
|
|
||||||
// ", y=" + y + "].");
|
|
||||||
} while (!createPath(s, x, y));
|
} while (!createPath(s, x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +165,6 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
{
|
{
|
||||||
if (event instanceof PathCompletedEvent) {
|
if (event instanceof PathCompletedEvent) {
|
||||||
AmbulatorySprite s = (AmbulatorySprite)event.getSprite();
|
AmbulatorySprite s = (AmbulatorySprite)event.getSprite();
|
||||||
// Log.info("Path completed [sprite=" + s + "].");
|
|
||||||
|
|
||||||
if (s != _sprite) {
|
if (s != _sprite) {
|
||||||
// move the sprite to a new random location
|
// move the sprite to a new random location
|
||||||
@@ -173,13 +174,16 @@ public class ViewerSceneViewPanel extends SceneViewPanel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The number of decoy characters milling about. */
|
/** The number of decoy characters milling about. */
|
||||||
protected static final int NUM_DECOYS = 10;
|
protected static final int NUM_DECOYS = 2;
|
||||||
|
|
||||||
/** The tileset id for the character tiles. */
|
/** The tileset id for the decoy character tiles. */
|
||||||
protected static final int TSID_CHAR = 1011;
|
protected static final int TSID_CHAR = 1011;
|
||||||
|
|
||||||
|
/** The tileset id for the user character tiles. */
|
||||||
|
protected static final int TSID_CHAR_USER = 1012;
|
||||||
|
|
||||||
/** The animation manager. */
|
/** The animation manager. */
|
||||||
AnimationManager _animmgr;
|
protected AnimationManager _animmgr;
|
||||||
|
|
||||||
/** The sprite we're manipulating within the view. */
|
/** The sprite we're manipulating within the view. */
|
||||||
protected AmbulatorySprite _sprite;
|
protected AmbulatorySprite _sprite;
|
||||||
|
|||||||
Reference in New Issue
Block a user