diff --git a/src/java/com/threerings/cast/CharacterManager.java b/src/java/com/threerings/cast/CharacterManager.java
index 649946b3a..f0f68c65c 100644
--- a/src/java/com/threerings/cast/CharacterManager.java
+++ b/src/java/com/threerings/cast/CharacterManager.java
@@ -1,5 +1,5 @@
//
-// $Id: CharacterManager.java,v 1.15 2002/03/08 07:50:32 mdb Exp $
+// $Id: CharacterManager.java,v 1.16 2002/03/16 03:15:04 shaper Exp $
package com.threerings.cast;
@@ -10,7 +10,8 @@ import java.util.HashMap;
import com.samskivert.util.Tuple;
import com.threerings.media.sprite.MultiFrameImage;
-import com.threerings.media.sprite.Sprite;
+
+import com.threerings.util.DirectionCodes;
import com.threerings.cast.Log;
import com.threerings.cast.util.TileUtil;
@@ -21,6 +22,7 @@ import com.threerings.cast.util.TileUtil;
* compositing and caching of composited character animations.
*/
public class CharacterManager
+ implements DirectionCodes
{
/**
* Constructs the character manager.
@@ -176,7 +178,7 @@ public class CharacterManager
CharacterDescriptor descrip, String action)
throws NoSuchComponentException
{
- MultiFrameImage[] frames = new MultiFrameImage[Sprite.DIRECTION_COUNT];
+ MultiFrameImage[] frames = new MultiFrameImage[DIRECTION_COUNT];
int[] cids = descrip.getComponentIds();
int ccount = cids.length;
diff --git a/src/java/com/threerings/cast/CharacterSprite.java b/src/java/com/threerings/cast/CharacterSprite.java
index 8a6b4dda0..1336cd9e7 100644
--- a/src/java/com/threerings/cast/CharacterSprite.java
+++ b/src/java/com/threerings/cast/CharacterSprite.java
@@ -1,18 +1,18 @@
//
-// $Id: CharacterSprite.java,v 1.24 2002/03/15 01:10:25 mdb Exp $
+// $Id: CharacterSprite.java,v 1.25 2002/03/16 03:15:04 shaper Exp $
package com.threerings.cast;
import com.threerings.media.sprite.MultiFrameImage;
import com.threerings.media.sprite.Path;
-import com.threerings.media.sprite.Sprite;
+import com.threerings.media.sprite.ImageSprite;
/**
* A character sprite is a sprite that animates itself while walking
* about in a scene.
*/
-public class CharacterSprite
- extends Sprite implements StandardActions
+public class CharacterSprite extends ImageSprite
+ implements StandardActions
{
/**
* Initializes this character sprite with the specified character
diff --git a/src/java/com/threerings/cast/builder/SpritePanel.java b/src/java/com/threerings/cast/builder/SpritePanel.java
index d04f12c5f..e7e24edb6 100644
--- a/src/java/com/threerings/cast/builder/SpritePanel.java
+++ b/src/java/com/threerings/cast/builder/SpritePanel.java
@@ -1,5 +1,5 @@
//
-// $Id: SpritePanel.java,v 1.11 2002/03/08 07:50:32 mdb Exp $
+// $Id: SpritePanel.java,v 1.12 2002/03/16 03:15:04 shaper Exp $
package com.threerings.cast.builder;
@@ -9,11 +9,14 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
+import java.util.List;
+
import com.threerings.media.animation.AnimatedPanel;
import com.threerings.media.animation.AnimationManager;
-import com.threerings.media.sprite.Sprite;
import com.threerings.media.sprite.SpriteManager;
+import com.threerings.util.DirectionCodes;
+
import com.threerings.cast.Log;
import com.threerings.cast.CharacterDescriptor;
import com.threerings.cast.CharacterManager;
@@ -24,9 +27,8 @@ import com.threerings.cast.StandardActions;
* The sprite panel displays a character sprite centered in the panel
* suitable for user perusal.
*/
-public class SpritePanel
- extends AnimatedPanel
- implements BuilderModelListener
+public class SpritePanel extends AnimatedPanel
+ implements DirectionCodes, BuilderModelListener
{
/**
* Constructs the sprite panel.
@@ -47,10 +49,8 @@ public class SpritePanel
}
// documentation inherited
- protected void render (Graphics g)
+ protected void render (Graphics2D gfx, List invalidRects)
{
- Graphics2D gfx = (Graphics2D)g;
-
// clear the background
gfx.setColor(Color.lightGray);
Dimension d = getSize();
@@ -63,7 +63,7 @@ public class SpritePanel
if (_sprite != null) {
// render the sprite
- _sprite.paint((Graphics2D)g);
+ _sprite.paint(gfx);
}
}
@@ -100,7 +100,7 @@ public class SpritePanel
protected void setSprite (CharacterSprite sprite)
{
sprite.setActionSequence(StandardActions.STANDING);
- sprite.setOrientation(Sprite.WEST);
+ sprite.setOrientation(WEST);
_sprite = sprite;
centerSprite();
repaint();
diff --git a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java
index f07d2cc77..ba959134b 100644
--- a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java
+++ b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java
@@ -1,5 +1,5 @@
//
-// $Id: BundledComponentRepository.java,v 1.8 2002/03/08 09:35:14 mdb Exp $
+// $Id: BundledComponentRepository.java,v 1.9 2002/03/16 03:15:04 shaper Exp $
package com.threerings.cast.bundle;
@@ -27,12 +27,13 @@ import com.threerings.resource.ResourceManager;
import com.threerings.media.ImageManager;
import com.threerings.media.sprite.MultiFrameImage;
-import com.threerings.media.sprite.Sprite;
import com.threerings.media.tile.ImageProvider;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.NoSuchTileException;
+import com.threerings.util.DirectionCodes;
+
import com.threerings.cast.CharacterComponent;
import com.threerings.cast.ComponentClass;
import com.threerings.cast.ComponentRepository;
@@ -47,7 +48,7 @@ import com.threerings.cast.NoSuchComponentException;
* @see ResourceManager
*/
public class BundledComponentRepository
- implements ComponentRepository
+ implements DirectionCodes, ComponentRepository
{
/**
* Constructs a repository which will obtain its resource set from the
@@ -271,8 +272,7 @@ public class BundledComponentRepository
fset.setImageProvider(this);
// and create the necessary multiframe image instances
- MultiFrameImage[] frames =
- new MultiFrameImage[Sprite.DIRECTION_COUNT];
+ MultiFrameImage[] frames = new MultiFrameImage[DIRECTION_COUNT];
for (int i = 0; i < frames.length; i++) {
frames[i] = new TileSetFrameImage(fset, i);
}
@@ -310,7 +310,7 @@ public class BundledComponentRepository
// documentation inherited
public int getFrameCount ()
{
- return _set.getTileCount() / Sprite.DIRECTION_COUNT;
+ return _set.getTileCount() / DIRECTION_COUNT;
}
// documentation inherited
diff --git a/src/java/com/threerings/cast/util/TileUtil.java b/src/java/com/threerings/cast/util/TileUtil.java
index 87e06d05d..6fe5d6eab 100644
--- a/src/java/com/threerings/cast/util/TileUtil.java
+++ b/src/java/com/threerings/cast/util/TileUtil.java
@@ -1,5 +1,5 @@
//
-// $Id: TileUtil.java,v 1.11 2002/03/10 22:31:21 mdb Exp $
+// $Id: TileUtil.java,v 1.12 2002/03/16 03:15:05 shaper Exp $
package com.threerings.cast.util;
@@ -8,9 +8,10 @@ import java.awt.Image;
import java.awt.image.BufferedImage;
import com.threerings.media.sprite.MultiFrameImage;
-import com.threerings.media.sprite.Sprite;
import com.threerings.media.util.ImageUtil;
+import com.threerings.util.DirectionCodes;
+
import com.threerings.cast.Log;
import com.threerings.cast.Colorization;
@@ -18,6 +19,7 @@ import com.threerings.cast.Colorization;
* Miscellaneous tile-related utility functions.
*/
public class TileUtil
+ implements DirectionCodes
{
/**
* Renders each of the given src component frames into
@@ -33,7 +35,7 @@ public class TileUtil
MultiFrameImage[] dest, MultiFrameImage[] src,
Colorization[] zations)
{
- for (int orient = 0; orient < Sprite.DIRECTION_COUNT; orient++) {
+ for (int orient = 0; orient < DIRECTION_COUNT; orient++) {
MultiFrameImage sframes = src[orient];
MultiFrameImage dframes = dest[orient];
diff --git a/src/java/com/threerings/media/sprite/ImageSprite.java b/src/java/com/threerings/media/sprite/ImageSprite.java
new file mode 100644
index 000000000..b89eda789
--- /dev/null
+++ b/src/java/com/threerings/media/sprite/ImageSprite.java
@@ -0,0 +1,270 @@
+//
+// $Id: ImageSprite.java,v 1.1 2002/03/16 03:15:05 shaper Exp $
+
+package com.threerings.media.sprite;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.threerings.media.Log;
+
+/**
+ * Extends the sprite class to support rendering the sprite with one or
+ * more frames of image animation. Overrides various methods to provide
+ * correspondingly desirable functionality, e.g., {@link #hitTest} only
+ * reports a hit if the specified point is within a non-transparent pixel
+ * for the sprite's current image frame.
+ */
+public class ImageSprite extends Sprite
+{
+ /** Default frame rate. */
+ public static final int DEFAULT_FRAME_RATE = 15;
+
+ /** Animation mode indicating no animation. */
+ public static final int NO_ANIMATION = 0;
+
+ /** Animation mode indicating movement cued animation. */
+ public static final int MOVEMENT_CUED = 1;
+
+ /** Animation mode indicating time based animation. */
+ public static final int TIME_BASED = 2;
+
+ /**
+ * Constructs an image sprite without any associated frames and with a
+ * default initial location of (0, 0). The sprite should
+ * be populated with a set of frames used to display it via a
+ * subsequent call to {@link #setFrames}, and its location updated
+ * with {@link #setLocation}.
+ */
+ public ImageSprite ()
+ {
+ this(0, 0, null);
+ }
+
+ /**
+ * Constructs an image sprite without any associated frames. The
+ * sprite should be populated with a set of frames used to display it
+ * via a subsequent call to {@link #setFrames}.
+ *
+ * @param x the sprite x-position in pixels.
+ * @param y the sprite y-position in pixels.
+ */
+ public ImageSprite (int x, int y)
+ {
+ this(x, y, null);
+ }
+
+ /**
+ * Constructs an image sprite.
+ *
+ * @param x the sprite x-position in pixels.
+ * @param y the sprite y-position in pixels.
+ * @param frames the multi-frame image used to display the sprite.
+ */
+ public ImageSprite (int x, int y, MultiFrameImage frames)
+ {
+ super(x, y);
+
+ // initialize frame animation member data
+ _frames = frames;
+ _frameIdx = 0;
+ _animMode = NO_ANIMATION;
+ _frameDelay = 1000L/DEFAULT_FRAME_RATE;
+ }
+
+ // documentation inherited
+ protected void init (SpriteManager spritemgr)
+ {
+ super.init(spritemgr);
+
+ setFrames(_frames);
+ }
+
+ /**
+ * Returns true if the sprite's bounds contain the specified point,
+ * and if there is a non-transparent pixel in the sprite's image at
+ * the specified point, false if not.
+ */
+ public boolean hitTest (int x, int y)
+ {
+ // first check to see that we're in the sprite's bounds and that
+ // we've got a frame image (if we've got no image, there's nothing
+ // to be hit)
+ if (!super.hitTest(x, y) || _frame == null) {
+ return false;
+ }
+
+ if (_frame instanceof BufferedImage) {
+ BufferedImage bimage = (BufferedImage)_frame;
+ int argb = bimage.getRGB(x - _bounds.x, y - _bounds.y);
+ int alpha = argb >> 24;
+ // Log.info("Checking [x=" + x + ", y=" + y +
+ // ", bounds=" + _bounds + ", " + alpha);
+
+ // it's only a hit if the pixel is non-transparent
+ return (argb >> 24) != 0;
+
+ } else {
+ Log.warning("Can't check for transparent pixel " +
+ "[image=" + _frame + "].");
+ return true;
+ }
+ }
+
+ /**
+ * Sets the animation mode for this sprite. The available modes are:
+ *
+ *
TIME_BASED: cues the animation based on a target
+ * frame rate (specified via {@link #setFrameRate}).
+ * MOVEMENT_CUED: ticks the animation to the next
+ * frame every time the sprite is moved along its path.
+ * NO_ANIMATION: disables animation.
+ * TIME_BASED.
+ *
+ * @param fps the desired frames per second.
+ */
+ public void setFrameRate (int fps)
+ {
+ _frameDelay = 1000L/fps;
+ }
+
+ /**
+ * Set the image array used to render the sprite.
+ *
+ * @param frames the sprite images.
+ */
+ public void setFrames (MultiFrameImage frames)
+ {
+ if (frames == null) {
+ // Log.warning("Someone set up us the null frames! " +
+ // "[sprite=" + this + "].");
+ return;
+ }
+
+ // start with our old bounds
+ Rectangle dirty = new Rectangle(_bounds);
+
+ _frames = frames;
+ _frameIdx %= _frames.getFrameCount();
+ _frame = _frames.getFrame(_frameIdx);
+
+ // determine our drawing offsets and rendered rectangle size
+ if (_frame == null) {
+ _bounds.width = 0;
+ _bounds.height = 0;
+
+ } else {
+ _bounds.width = _frame.getWidth(null);
+ _bounds.height = _frame.getHeight(null);
+ }
+
+ // add our new bounds
+ dirty.add(_bounds);
+
+ updateRenderOffset();
+ updateRenderOrigin();
+ invalidate(dirty);
+ }
+
+ // documentation inherited
+ public void paint (Graphics2D gfx)
+ {
+ if (_frame != null) {
+ gfx.drawImage(_frame, _bounds.x, _bounds.y, null);
+ } else {
+ super.paint(gfx);
+ }
+ }
+
+ // documentation inherited
+ public void tick (long timestamp)
+ {
+ // if we have no frames, we're hosulated (to use a Greenwell term)
+ if (_frames == null) {
+ return;
+ }
+
+ int fcount = _frames.getFrameCount();
+ boolean moved = false;
+
+ // move the sprite along toward its destination, if any
+ if (_path != null) {
+ moved = _path.updatePosition(this, timestamp);
+ }
+
+ // increment the display image if performing image animation
+ int nfidx = _frameIdx;
+ switch (_animMode) {
+ case NO_ANIMATION:
+ // nothing doing
+ break;
+
+ case TIME_BASED:
+ nfidx = (int)((timestamp/_frameDelay) % fcount);
+ break;
+
+ case MOVEMENT_CUED:
+ // update the frame if the sprite moved
+ if (moved) {
+ nfidx = (_frameIdx + 1) % fcount;
+ }
+ break;
+ }
+
+ // only update the sprite if our frame index changed
+ if (nfidx != _frameIdx) {
+ _frameIdx = nfidx;
+ _frame = _frames.getFrame(_frameIdx);
+ // dirty our rectangle since we've altered our display image
+ invalidate();
+ }
+ }
+
+ // documentation inherited
+ protected void invalidate (Rectangle r)
+ {
+ if (_frame != null) {
+ super.invalidate(r);
+ }
+ }
+
+ // documentation inherited
+ protected void toString (StringBuffer buf)
+ {
+ super.toString(buf);
+ buf.append(", fidx=").append(_frameIdx);
+ }
+
+ /** The images used to render the sprite. */
+ protected MultiFrameImage _frames;
+
+ /** The current frame being rendered. */
+ protected Image _frame;
+
+ /** The current frame index to render. */
+ protected int _frameIdx;
+
+ /** What type of animation is desired for this sprite. */
+ protected int _animMode;
+
+ /** For how many milliseconds to display an animation frame. */
+ protected long _frameDelay;
+}
diff --git a/src/java/com/threerings/media/sprite/LabelSprite.java b/src/java/com/threerings/media/sprite/LabelSprite.java
new file mode 100644
index 000000000..f61e80156
--- /dev/null
+++ b/src/java/com/threerings/media/sprite/LabelSprite.java
@@ -0,0 +1,59 @@
+//
+// $Id: LabelSprite.java,v 1.1 2002/03/16 03:15:05 shaper Exp $
+
+package com.threerings.media.sprite;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+
+import com.samskivert.swing.Label;
+
+import com.threerings.media.Log;
+
+/**
+ * A sprite that uses a label to render itself. Assumes that the label
+ * has been previously laid out (see {@link Label#layout}). The label
+ * should not be altered after the sprite is created.
+ */
+public class LabelSprite extends Sprite
+{
+ /**
+ * Constructs a label sprite that renders itself with the specified
+ * label.
+ */
+ public LabelSprite (Label label)
+ {
+ this(0, 0, label);
+ }
+
+ /**
+ * Constructs a label sprite with the given initial position that
+ * renders itself with the specified label.
+ */
+ public LabelSprite (int x, int y, Label label)
+ {
+ super(x, y);
+
+ _label = label;
+ }
+
+ // documentation inherited
+ protected void init (SpriteManager spritemgr)
+ {
+ super.init(spritemgr);
+
+ // size the bounds to fit our label
+ Dimension size = _label.getSize();
+ _bounds.width = size.width;
+ _bounds.height = size.height;
+ }
+
+ // documentation inherited
+ public void paint (Graphics2D gfx)
+ {
+ _label.render(gfx, _bounds.x, _bounds.y);
+ }
+
+ /** The label associated with this sprite. */
+ protected Label _label;
+}
diff --git a/src/java/com/threerings/media/sprite/Sprite.java b/src/java/com/threerings/media/sprite/Sprite.java
index 0872870b1..b283d1919 100644
--- a/src/java/com/threerings/media/sprite/Sprite.java
+++ b/src/java/com/threerings/media/sprite/Sprite.java
@@ -1,70 +1,70 @@
//
-// $Id: Sprite.java,v 1.38 2002/03/04 22:47:06 mdb Exp $
+// $Id: Sprite.java,v 1.39 2002/03/16 03:15:05 shaper Exp $
package com.threerings.media.sprite;
-import java.awt.*;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.image.BufferedImage;
+
import java.util.ArrayList;
import java.util.Iterator;
-import com.threerings.media.Log;
import com.threerings.util.DirectionCodes;
+import com.threerings.media.Log;
+
/**
* The sprite class represents a single moveable object in an animated
- * view. A sprite has a position within the view, and a set of images
- * used to render it (perhaps multiple frames for animation).
+ * view. A sprite has a position and orientation within the view, and can
+ * be moved along a path.
*/
-public class Sprite implements DirectionCodes
+public abstract class Sprite
+ implements DirectionCodes
{
- /** Default frame rate. */
- public static final int DEFAULT_FRAME_RATE = 15;
-
- /** Animation mode indicating no animation. */
- public static final int NO_ANIMATION = 0;
-
- /** Animation mode indicating movement cued animation. */
- public static final int MOVEMENT_CUED = 1;
-
- /** Animation mode indicating time based animation. */
- public static final int TIME_BASED = 2;
-
/**
- * Constructs a sprite without any associated frames and with a
- * default initial location of (0, 0). The sprite should
- * be populated with a set of frames used to display it via a
- * subsequent call to {@link #setFrames}, and its location can be
- * updated with {@link #setLocation}.
+ * Constructs a sprite with a default initial location of (0,
+ * 0).
*/
public Sprite ()
{
- init(0, 0, null);
+ this(0, 0);
}
/**
- * Constructs a sprite without any associated frames. The sprite
- * should be populated with a set of frames used to display it via a
- * subsequent call to {@link #setFrames}.
+ * Constructs a sprite initially positioned at the specified location.
*
* @param x the sprite x-position in pixels.
* @param y the sprite y-position in pixels.
*/
public Sprite (int x, int y)
{
- init(x, y, null);
+ _x = x;
+ _y = y;
}
/**
- * Constructs a sprite.
+ * Called by the sprite manager to initialize the sprite when a sprite
+ * is added to said manager for management.
*
- * @param x the sprite x-position in pixels.
- * @param y the sprite y-position in pixels.
- * @param frames the multi-frame image used to display the sprite.
+ * @param spritemgr the sprite manager.
*/
- public Sprite (int x, int y, MultiFrameImage frames)
+ protected void init (SpriteManager spritemgr)
{
- init(x, y, frames);
+ _spritemgr = spritemgr;
+
+ updateRenderOrigin();
+ }
+
+ /**
+ * Called by the sprite manager after the sprite is removed from
+ * service. Derived classes may override this method but should be
+ * sure to call super.shutdown().
+ */
+ protected void shutdown ()
+ {
+ _spritemgr = null;
}
/**
@@ -107,6 +107,50 @@ public class Sprite implements DirectionCodes
return _bounds;
}
+ /**
+ * Sprites have an orientation in one of the eight cardinal
+ * directions: NORTH, NORTHEAST, etc.
+ * Derived classes can choose to override this member function and
+ * select a different set of images based on their orientation, or
+ * they can ignore the orientation information.
+ *
+ * @see DirectionCodes
+ */
+ public void setOrientation (int orient)
+ {
+ _orient = orient;
+ }
+
+ /**
+ * Returns the sprite's orientation as one of the eight cardinal
+ * directions: NORTH, NORTHEAST, etc.
+ *
+ * @see DirectionCodes
+ */
+ public int getOrientation ()
+ {
+ return _orient;
+ }
+
+ /**
+ * Returns the render order of this sprite.
+ */
+ public int getRenderOrder ()
+ {
+ return _renderOrder;
+ }
+
+ /**
+ * Sets the render order associated with this animation. Sprites can
+ * be rendered in two layers; those with negative render order and
+ * those with positive render order. Someday sprites will be rendered
+ * in each layer according to render order.
+ */
+ public void setRenderOrder (int value)
+ {
+ _renderOrder = value;
+ }
+
/**
* Moves the sprite to the specified location.
*
@@ -123,7 +167,7 @@ public class Sprite implements DirectionCodes
_y = y;
// we need to update our draw position which is based on the
- // size of our current frame
+ // size of our current bounds
updateRenderOrigin();
if (dirty.intersects(_bounds)) {
@@ -140,57 +184,6 @@ public class Sprite implements DirectionCodes
invalidate(dirty);
}
- /**
- * Sprites have an orientation in one of the eight cardinal
- * directions: NORTH, NORTHEAST, etc. Sprite
- * derived classes can choose to override this member function and
- * select a different set of images based on their orientation, or
- * they can ignore the orientation information.
- */
- public void setOrientation (int orient)
- {
- _orient = orient;
- }
-
- /**
- * Returns the sprite's orientation as one of the eight cardinal
- * directions: NORTH, NORTHEAST, etc.
- */
- public int getOrientation ()
- {
- return _orient;
- }
-
- /**
- * Initialize the sprite object with its variegated parameters.
- */
- protected void init (int x, int y, MultiFrameImage frames)
- {
- _x = x;
- _y = y;
-
- updateRenderOrigin();
-
- // initialize frame animation member data
- _frameIdx = 0;
- _animMode = NO_ANIMATION;
- _frameDelay = 1000L/DEFAULT_FRAME_RATE;
-
- setFrames(frames);
- invalidate();
- }
-
- /**
- * Called by the sprite manager when a sprite is added to said manager
- * for management.
- *
- * @param mgr the sprite manager.
- */
- protected void setSpriteManager (SpriteManager mgr)
- {
- _spritemgr = mgr;
- }
-
/**
* Paint the sprite to the specified graphics context.
*
@@ -198,11 +191,7 @@ public class Sprite implements DirectionCodes
*/
public void paint (Graphics2D gfx)
{
- if (_frame != null) {
- gfx.drawImage(_frame, _bounds.x, _bounds.y, null);
- } else {
- gfx.draw(_bounds);
- }
+ gfx.draw(_bounds);
}
/**
@@ -228,31 +217,11 @@ public class Sprite implements DirectionCodes
/**
* Returns true if the sprite's bounds contain the specified point,
- * and if there is a non-transparent pixel in the sprite's image at
- * the specified point, false if not.
+ * false if not.
*/
public boolean hitTest (int x, int y)
{
- // first check to see that we're in the sprite's bounds and that
- // we've got a frame image (if we've got no image, there's nothing
- // to be hit)
- if (!_bounds.contains(x, y) || _frame == null) {
- return false;
- }
-
- if (_frame instanceof BufferedImage) {
- BufferedImage bimage = (BufferedImage)_frame;
- int argb = bimage.getRGB(x - _bounds.x, y - _bounds.y);
- int alpha = argb >> 24;
- // Log.info("Checking [x=" + x + ", y=" + y + ", bounds=" + _bounds + ", " + alpha);
- // it's only a hit if the pixel is non-transparent
- return (argb >> 24) != 0;
-
- } else {
- Log.warning("Can't check for transparent pixel " +
- "[image=" + _frame + "].");
- return true;
- }
+ return _bounds.contains(x, y);
}
/**
@@ -273,74 +242,6 @@ public class Sprite implements DirectionCodes
return shape.intersects(_bounds);
}
- /**
- * Sets the animation mode for this sprite. The available modes are:
- *
- * TIME_BASED: cues the animation based on a target
- * frame rate (specified via {@link #setFrameRate}).
- * MOVEMENT_CUED: ticks the animation to the next
- * frame every time the sprite is moved along its path.
- * NO_ANIMATION: disables animation.
- * TIME_BASED.
- *
- * @param fps the desired frames per second.
- */
- public void setFrameRate (int fps)
- {
- _frameDelay = 1000L/fps;
- }
-
- /**
- * Set the image array used to render the sprite.
- *
- * @param frames the sprite images.
- */
- public void setFrames (MultiFrameImage frames)
- {
- if (frames == null) {
- // Log.warning("Someone set up us the null frames! " +
- // "[sprite=" + this + "].");
- return;
- }
-
- // start with our old bounds
- Rectangle dirty = new Rectangle(_bounds);
-
- _frames = frames;
- _frameIdx %= _frames.getFrameCount();
- _frame = _frames.getFrame(_frameIdx);
-
- // determine our drawing offsets and rendered rectangle size
- if (_frame == null) {
- _bounds.width = 0;
- _bounds.height = 0;
-
- } else {
- _bounds.width = _frame.getWidth(null);
- _bounds.height = _frame.getHeight(null);
- }
-
- // add our new bounds
- dirty.add(_bounds);
-
- updateRenderOffset();
- updateRenderOrigin();
- invalidate(dirty);
- }
-
/**
* Returns true if this sprite is currently following a path, false if
* it is not.
@@ -396,7 +297,6 @@ public class Sprite implements DirectionCodes
_path = null;
// inform observers that we've finished our path
notifyObservers(new PathCompletedEvent(this, oldpath));
-
}
/**
@@ -416,10 +316,6 @@ public class Sprite implements DirectionCodes
*/
protected void invalidate (Rectangle r)
{
- if (_frame == null) {
- return;
- }
-
if (_spritemgr != null) {
_spritemgr.addDirtyRect((r != null) ? r : new Rectangle(_bounds));
@@ -439,44 +335,9 @@ public class Sprite implements DirectionCodes
*/
public void tick (long timestamp)
{
- // if we have no frames, we're hosulated (to use a Greenwell term)
- if (_frames == null) {
- return;
- }
-
- int fcount = _frames.getFrameCount();
- boolean moved = false;
-
- // move the sprite along toward its destination, if any
+ // if we've a path, move the sprite along toward its destination
if (_path != null) {
- moved = _path.updatePosition(this, timestamp);
- }
-
- // increment the display image if performing image animation
- int nfidx = _frameIdx;
- switch (_animMode) {
- case NO_ANIMATION:
- // nothing doing
- break;
-
- case TIME_BASED:
- nfidx = (int)((timestamp/_frameDelay) % fcount);
- break;
-
- case MOVEMENT_CUED:
- // update the frame if the sprite moved
- if (moved) {
- nfidx = (_frameIdx + 1) % fcount;
- }
- break;
- }
-
- // only update the sprite if our frame index changed
- if (nfidx != _frameIdx) {
- _frameIdx = nfidx;
- _frame = _frames.getFrame(_frameIdx);
- // dirty our rectangle since we've altered our display image
- invalidate();
+ _path.updatePosition(this, timestamp);
}
}
@@ -544,8 +405,7 @@ public class Sprite implements DirectionCodes
*/
public String toString ()
{
- StringBuffer buf = new StringBuffer();
- buf.append("[");
+ StringBuffer buf = new StringBuffer("[");
toString(buf);
return buf.append("]").toString();
}
@@ -559,21 +419,8 @@ public class Sprite implements DirectionCodes
{
buf.append("x=").append(_x);
buf.append(", y=").append(_y);
- buf.append(", fidx=").append(_frameIdx);
}
- /** The images used to render the sprite. */
- protected MultiFrameImage _frames;
-
- /** The current frame being rendered. */
- protected Image _frame;
-
- /** The current frame index to render. */
- protected int _frameIdx;
-
- /** The orientation of this sprite. */
- protected int _orient = NONE;
-
/** The location of the sprite in pixel coordinates. */
protected int _x, _y;
@@ -583,15 +430,15 @@ public class Sprite implements DirectionCodes
/** Our rendered bounds in pixel coordinates. */
protected Rectangle _bounds = new Rectangle();
- /** What type of animation is desired for this sprite. */
- protected int _animMode;
-
- /** For how many milliseconds to display an animation frame. */
- protected long _frameDelay;
+ /** The orientation of this sprite. */
+ protected int _orient = NONE;
/** When moving, the path the sprite is traversing. */
protected Path _path;
+ /** The render order of this sprite. */
+ protected int _renderOrder;
+
/** The sprite observers observing this sprite. */
protected ArrayList _observers;
diff --git a/src/java/com/threerings/media/sprite/SpriteManager.java b/src/java/com/threerings/media/sprite/SpriteManager.java
index 2048d7515..fd75d1401 100644
--- a/src/java/com/threerings/media/sprite/SpriteManager.java
+++ b/src/java/com/threerings/media/sprite/SpriteManager.java
@@ -1,5 +1,5 @@
//
-// $Id: SpriteManager.java,v 1.26 2002/02/28 23:25:15 mdb Exp $
+// $Id: SpriteManager.java,v 1.27 2002/03/16 03:15:05 shaper Exp $
package com.threerings.media.sprite;
@@ -25,6 +25,15 @@ import com.threerings.media.Log;
*/
public class SpriteManager
{
+ /** Constant for the front layer of sprites. */
+ public static final int FRONT = 0;
+
+ /** Constant for the back layer of sprites. */
+ public static final int BACK = 1;
+
+ /** Constant for all layers of sprites. */
+ public static final int ALL = 2;
+
/**
* Construct and initialize the SpriteManager object.
*/
@@ -129,8 +138,8 @@ public class SpriteManager
*/
public void addSprite (Sprite sprite)
{
- // let the sprite know about us
- sprite.setSpriteManager(this);
+ // initialize the sprite
+ sprite.init(this);
// add the sprite to our list
_sprites.add(sprite);
// and invalidate the sprite's original position
@@ -150,17 +159,21 @@ public class SpriteManager
// remove the sprite from our list
_sprites.remove(sprite);
// clear out our manager reference
- sprite.setSpriteManager(null);
+ sprite.shutdown();
}
/**
- * Render the sprites residing within the given shape to the given
- * graphics context.
+ * Render the sprites residing within the given shape and layer to the
+ * given graphics context.
*
* @param gfx the graphics context.
* @param bounds the bounding shape.
+ * @param layer the layer to render; one of {@link #FRONT}, {@link
+ * #BACK}, or {@link #ALL}. The front layer contains all sprites with
+ * a positive render order; the back layer contains all sprites with a
+ * negative render order; all, both.
*/
- public void renderSprites (Graphics2D gfx, Shape bounds)
+ public void renderSprites (Graphics2D gfx, Shape bounds, int layer)
{
// TODO: optimize to store sprites based on quadrants they're
// in (or somesuch), and sorted, so that we can more quickly
@@ -169,7 +182,11 @@ public class SpriteManager
int size = _sprites.size();
for (int ii = 0; ii < size; ii++) {
Sprite sprite = (Sprite)_sprites.get(ii);
- if (sprite.intersects(bounds)) {
+ int order = sprite.getRenderOrder();
+ if (((layer == ALL) ||
+ (layer == FRONT && order >= 0) ||
+ (layer == BACK && order < 0)) &&
+ sprite.intersects(bounds)) {
sprite.paint(gfx);
}
}
diff --git a/src/java/com/threerings/miso/client/IsoSceneView.java b/src/java/com/threerings/miso/client/IsoSceneView.java
index 865ec9440..0a49a53c5 100644
--- a/src/java/com/threerings/miso/client/IsoSceneView.java
+++ b/src/java/com/threerings/miso/client/IsoSceneView.java
@@ -1,5 +1,5 @@
//
-// $Id: IsoSceneView.java,v 1.101 2002/02/19 19:57:46 mdb Exp $
+// $Id: IsoSceneView.java,v 1.102 2002/03/16 03:15:05 shaper Exp $
package com.threerings.miso.scene;
@@ -188,7 +188,7 @@ public class IsoSceneView implements SceneView
// drawDirtyRegions(gfx);
// render any animations
- _animmgr.renderAnimations(gfx);
+ _animmgr.renderAnimations(gfx, AnimationManager.ALL);
// clear out the dirty tiles and rectangles
clearDirtyRegions();
diff --git a/src/java/com/threerings/miso/client/TilePath.java b/src/java/com/threerings/miso/client/TilePath.java
index 6714f8994..c18df8d19 100644
--- a/src/java/com/threerings/miso/client/TilePath.java
+++ b/src/java/com/threerings/miso/client/TilePath.java
@@ -1,5 +1,5 @@
//
-// $Id: TilePath.java,v 1.3 2001/12/17 03:33:18 mdb Exp $
+// $Id: TilePath.java,v 1.4 2002/03/16 03:15:05 shaper Exp $
package com.threerings.miso.scene;
@@ -8,6 +8,8 @@ import java.util.List;
import com.threerings.media.sprite.*;
+import com.threerings.util.DirectionCodes;
+
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil;
@@ -18,6 +20,7 @@ import com.threerings.miso.scene.util.IsoUtil;
* tile coordinates are updated as the path is traversed.
*/
public class TilePath extends LineSegmentPath
+ implements DirectionCodes
{
/**
* Constructs a tile path.
@@ -108,7 +111,7 @@ public class TilePath extends LineSegmentPath
// 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.NORTH);
+ addNode(stx, sty, sx, sy, NORTH);
// TODO: make more visually appealing path segments from start
// to second tile, and penultimate to ultimate tile.
diff --git a/src/java/com/threerings/miso/client/util/IsoUtil.java b/src/java/com/threerings/miso/client/util/IsoUtil.java
index cc505278f..931896740 100644
--- a/src/java/com/threerings/miso/client/util/IsoUtil.java
+++ b/src/java/com/threerings/miso/client/util/IsoUtil.java
@@ -1,9 +1,11 @@
//
-// $Id: IsoUtil.java,v 1.21 2002/02/19 04:02:50 mdb Exp $
+// $Id: IsoUtil.java,v 1.22 2002/03/16 03:15:06 shaper Exp $
package com.threerings.miso.scene.util;
-import java.awt.*;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
import com.samskivert.swing.SmartPolygon;
@@ -11,14 +13,18 @@ import com.threerings.media.sprite.Sprite;
import com.threerings.media.tile.ObjectTile;
import com.threerings.media.util.MathUtil;
+import com.threerings.util.DirectionCodes;
+
import com.threerings.miso.Log;
-import com.threerings.miso.scene.*;
+import com.threerings.miso.scene.IsoSceneViewModel;
+import com.threerings.miso.scene.MisoCharacterSprite;
/**
* The IsoUtil class is a holding place for miscellaneous
* isometric-display-related utility routines.
*/
public class IsoUtil
+ implements DirectionCodes
{
/**
* Sets the given character sprite's tile and fine coordinate
@@ -190,7 +196,7 @@ public class IsoUtil
// compare tile coordinates to determine direction
int dir = getIsoDirection(tax, tay, tbx, tby);
- if (dir != Sprite.NONE) return dir;
+ if (dir != DirectionCodes.NONE) return dir;
// destination point is in the same tile as the
// origination point, so consider fine coordinates
@@ -206,7 +212,7 @@ public class IsoUtil
dir = getIsoDirection(fax, fay, fbx, fby);
// arbitrarily return southwest if fine coords were also equivalent
- return (dir == -1) ? Sprite.SOUTHWEST : dir;
+ return (dir == -1) ? SOUTHWEST : dir;
}
/**
@@ -222,28 +228,28 @@ public class IsoUtil
* @param by the y-position of point B.
*
* @return the direction specified as one of the Sprite
- * class's direction constants, or Sprite.NONE
- * if point B is equivalent to point A.
+ * class's direction constants, or DirectionCodes.NONE if
+ * point B is equivalent to point A.
*/
public static int getIsoDirection (int ax, int ay, int bx, int by)
{
if (bx > ax) {
if (by == ay) {
- return Sprite.SOUTH;
+ return SOUTH;
}
- return (by < ay) ? Sprite.SOUTHEAST : Sprite.SOUTHWEST;
+ return (by < ay) ? SOUTHEAST : SOUTHWEST;
} else if (bx == ax) {
if (by == ay) {
- return Sprite.NONE;
+ return DirectionCodes.NONE;
}
- return (by < ay) ? Sprite.EAST : Sprite.WEST;
+ return (by < ay) ? EAST : WEST;
} else { // bx < ax
if (by == ay) {
- return Sprite.NORTH;
+ return NORTH;
}
- return (by < ay) ? Sprite.NORTHEAST : Sprite.NORTHWEST;
+ return (by < ay) ? NORTHEAST : NORTHWEST;
}
}