diff --git a/src/java/com/threerings/media/sprite/Sprite.java b/src/java/com/threerings/media/sprite/Sprite.java
index 029ef22a6..01f9371d1 100644
--- a/src/java/com/threerings/media/sprite/Sprite.java
+++ b/src/java/com/threerings/media/sprite/Sprite.java
@@ -1,5 +1,5 @@
//
-// $Id: Sprite.java,v 1.18 2001/09/05 21:51:43 shaper Exp $
+// $Id: Sprite.java,v 1.19 2001/09/07 23:01:53 shaper Exp $
package com.threerings.media.sprite;
@@ -335,7 +335,7 @@ public class Sprite
{
if (!_path.hasNext()) {
// inform observers that we've finished our path
- notifyObservers(SpriteObserver.FINISHED_PATH, _path);
+ notifyObservers(SpriteEvent.FINISHED_PATH, _path);
// clear out our path and bail
stop();
return;
@@ -343,7 +343,7 @@ public class Sprite
if (_dest != null) {
// inform observers that we've finished a path node
- notifyObservers(SpriteObserver.FINISHED_PATH_NODE, _dest);
+ notifyObservers(SpriteEvent.FINISHED_PATH_NODE, _dest);
}
// grab the next node in our path
@@ -492,11 +492,8 @@ public class Sprite
{
if (_observers == null) return;
- int size = _observers.size();
- for (int ii = 0; ii < size; ii++) {
- SpriteObserver obs = (SpriteObserver)_observers.get(ii);
- obs.spriteChanged(this, eventCode, arg);
- }
+ SpriteEvent evt = new SpriteEvent(this, eventCode, arg);
+ _spritemgr.notifySpriteObservers(_observers, evt);
}
/**
diff --git a/src/java/com/threerings/media/sprite/SpriteEvent.java b/src/java/com/threerings/media/sprite/SpriteEvent.java
new file mode 100644
index 000000000..a025ce54b
--- /dev/null
+++ b/src/java/com/threerings/media/sprite/SpriteEvent.java
@@ -0,0 +1,77 @@
+//
+// $Id: SpriteEvent.java,v 1.1 2001/09/07 23:01:53 shaper Exp $
+
+package com.threerings.media.sprite;
+
+/**
+ * A sprite event is sent to all sprite observers for a sprite
+ * whenever one of the various possible sprite events takes place.
+ */
+public class SpriteEvent
+{
+ /**
+ * Create a sprite event.
+ *
+ * @param sprite the involved sprite.
+ * @param eventCode the event code.
+ * @param arg the event argument.
+ */
+ public SpriteEvent (Sprite sprite, int eventCode, Object arg)
+ {
+ _sprite = sprite;
+ _eventCode = eventCode;
+ _arg = arg;
+ }
+
+ /**
+ * Return the sprite involved in the event.
+ */
+ public Sprite getSprite ()
+ {
+ return _sprite;
+ }
+
+ /**
+ * Return the event code for the event.
+ */
+ public int getEventCode ()
+ {
+ return _eventCode;
+ }
+
+ /**
+ * Return the argument associated with the event.
+ */
+ public Object getArgument ()
+ {
+ return _arg;
+ }
+
+ /**
+ * Event code noting that the sprite completed a path node. The
+ * argument to the event is the {@link PathNode} completed.
+ */
+ public static final int FINISHED_PATH_NODE = 0;
+
+ /**
+ * Event code noting that the sprite completed its entire path.
+ * The argument to the event is the {@link Path} completed.
+ */
+ public static final int FINISHED_PATH = 1;
+
+ /**
+ * Event code noting that the sprite collided with another
+ * sprite. The argument to the event is the {@link Sprite} the
+ * observed sprite collided with.
+ */
+ public static final int COLLIDED_SPRITE = 2;
+
+ /** The sprite associated with this event. */
+ protected Sprite _sprite;
+
+ /** The event code. */
+ protected int _eventCode;
+
+ /** The argument associated with this event. */
+ protected Object _arg;
+}
diff --git a/src/java/com/threerings/media/sprite/SpriteManager.java b/src/java/com/threerings/media/sprite/SpriteManager.java
index 9f37c8b8f..ed47f4220 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.11 2001/09/05 00:40:33 shaper Exp $
+// $Id: SpriteManager.java,v 1.12 2001/09/07 23:01:53 shaper Exp $
package com.threerings.media.sprite;
@@ -20,6 +20,7 @@ public class SpriteManager
public SpriteManager ()
{
_sprites = new ArrayList();
+ _notify = new ArrayList();
_dirty = new DirtyRectList();
}
@@ -163,6 +164,14 @@ public class SpriteManager
// notify sprite observers of any collisions
handleCollisions();
+
+ // notify sprite observers of any sprite events. note that we
+ // explicitly queue up events while ticking and checking for
+ // collisions, and we only notify observers once we're
+ // finished with all of those antics so that any actions the
+ // observers may take, such as sprite removal, won't screw us
+ // up elsewhere.
+ handleSpriteEvents();
}
/**
@@ -175,9 +184,9 @@ public class SpriteManager
int size = _sprites.size();
for (int ii = 0; ii < size; ii++) {
Sprite sprite = (Sprite)_sprites.get(ii);
- sprite.tick();
+ sprite.tick();
}
- }
+ }
/**
* Sort the sprite list in order of ascending x-coordinate.
@@ -201,40 +210,23 @@ public class SpriteManager
{
// gather a list of all sprite collisions
int size = _sprites.size();
- ArrayList collisions = new ArrayList();
for (int ii = 0; ii < size; ii++) {
Sprite sprite = (Sprite)_sprites.get(ii);
- checkCollisions(ii, size, sprite, collisions);
- }
-
- // observers are notified of sprite collisions after all
- // collision-detection is performed so that modifications to
- // the sprite, e.g. location or velocity, won't impact the
- // validity of our checking.
- int csize = collisions.size();
- for (int ii = 0; ii < csize; ii++) {
- Tuple tup = (Tuple)collisions.get(ii);
- Sprite a = (Sprite)tup.left, b = (Sprite)tup.right;
-
- // inform sprite observers for both sprites of the collision
- a.notifyObservers(SpriteObserver.COLLIDED_SPRITE, b);
- b.notifyObservers(SpriteObserver.COLLIDED_SPRITE, a);
+ checkCollisions(ii, size, sprite);
}
}
/**
* Check a sprite for collision with any other sprites in the
- * sprite list. The sprites involved in a collision are added to
- * the collisions list of {@link Tuple} objects.
+ * sprite list and notify the sprite observers associated with any
+ * sprites that do indeed collide.
*
* @param idx the starting sprite index.
* @param size the total number of sprites.
* @param sprite the sprite to check against other sprites for
* collisions.
- * @param collisions the list of collisions gathered so far.
*/
- protected void checkCollisions (int idx, int size, Sprite sprite,
- ArrayList collisions)
+ protected void checkCollisions (int idx, int size, Sprite sprite)
{
// TODO: make this handle quickly moving objects that may pass
// through each other.
@@ -254,9 +246,6 @@ public class SpriteManager
Sprite other = (Sprite)_sprites.get(ii);
Rectangle obounds = other.getBounds();
-// Log.info("Checking collision [bounds=" + bounds +
-// ", obounds=" + obounds + "].");
-
if (obounds.x > edgeX) {
// since sprites are stored in the list sorted by
// ascending x-position, we know this sprite and any
@@ -267,11 +256,47 @@ public class SpriteManager
}
if (obounds.intersects(bounds)) {
- collisions.add(new Tuple(sprite, other));
+ sprite.notifyObservers(SpriteEvent.COLLIDED_SPRITE, other);
+ other.notifyObservers(SpriteEvent.COLLIDED_SPRITE, sprite);
}
}
}
+ /**
+ * Notify all sprite observers of any sprite events that took
+ * place during our most recent tick().
+ */
+ protected void handleSpriteEvents ()
+ {
+ int size = _notify.size();
+ for (int ii = 0; ii < size; ii++) {
+ Tuple tup = (Tuple)_notify.remove(0);
+ ArrayList observers = (ArrayList)tup.left;
+ SpriteEvent evt = (SpriteEvent)tup.right;
+
+ int osize = observers.size();
+ for (int jj = 0; jj < osize; jj++) {
+ SpriteObserver obs = (SpriteObserver)observers.get(jj);
+ obs.spriteChanged(evt);
+ }
+ }
+ }
+
+ /**
+ * Called by {@link Sprite#notifyObservers} to note that the
+ * sprite's observers should be informed of a sprite event once
+ * the current tick() is complete.
+ *
+ * @param observers the list of sprite observers.
+ * @param event the sprite event to notify the observers of.
+ */
+ protected void notifySpriteObservers (ArrayList observers,
+ SpriteEvent event)
+ {
+ // throw it on the list of events for later
+ _notify.add(new Tuple(observers, event));
+ }
+
/** The comparator used to sort sprites by horizontal position. */
protected static final Comparator SPRITE_COMP = new SpriteComparator();
@@ -281,6 +306,9 @@ public class SpriteManager
/** The dirty rectangles created by sprites. */
protected DirtyRectList _dirty;
+ /** The list of pending sprite notifications. */
+ protected ArrayList _notify;
+
protected static class SpriteComparator implements Comparator
{
public int compare (Object o1, Object o2)
diff --git a/src/java/com/threerings/media/sprite/SpriteObserver.java b/src/java/com/threerings/media/sprite/SpriteObserver.java
index 4b9db6842..5e9866765 100644
--- a/src/java/com/threerings/media/sprite/SpriteObserver.java
+++ b/src/java/com/threerings/media/sprite/SpriteObserver.java
@@ -1,5 +1,5 @@
//
-// $Id: SpriteObserver.java,v 1.1 2001/09/05 00:40:33 shaper Exp $
+// $Id: SpriteObserver.java,v 1.2 2001/09/07 23:01:53 shaper Exp $
package com.threerings.media.sprite;
@@ -16,27 +16,7 @@ public interface SpriteObserver
* sprite.
*
* @param sprite the involved sprite.
- * @param eventCode the type of sprite event.
- * @param arg the argument associated with the event.
+ * @param event the sprite event.
*/
- public void spriteChanged (Sprite sprite, int eventCode, Object arg);
-
- /**
- * Event code noting that the sprite completed a path node. The
- * argument to the event is the {@link PathNode} completed.
- */
- public static final int FINISHED_PATH_NODE = 0;
-
- /**
- * Event code noting that the sprite completed its entire path.
- * The argument to the event is the {@link Path} completed.
- */
- public static final int FINISHED_PATH = 1;
-
- /**
- * Event code noting that the sprite collided with another
- * sprite. The argument to the event is the {@link Sprite} the
- * observed sprite collided with.
- */
- public static final int COLLIDED_SPRITE = 2;
+ public void spriteChanged (SpriteEvent event);
}