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); }