Pulled out gobs of Sprite/Animation functionality into AbstractMedia.
Pulled out gobs of SpriteManager/AnimationManager functionality into AbstractMediaManager. The big change: sprites can have their render order fine-tuned like animations. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1787 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
//
|
||||
// $Id: AbstractMedia.java,v 1.1 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Something that can be rendered on the media panel.
|
||||
*/
|
||||
public abstract class AbstractMedia
|
||||
{
|
||||
/**
|
||||
* Instantiate an abstract media object.
|
||||
*/
|
||||
public AbstractMedia (Rectangle bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically by this media's manager to give it
|
||||
* a chance to do its thing.
|
||||
*
|
||||
* @param tickStamp the system time for this tick.
|
||||
*/
|
||||
public abstract void tick (long tickStamp);
|
||||
|
||||
/**
|
||||
* Called by the appropriate manager to request that the
|
||||
* media render itself with the given graphics context. The
|
||||
* media may wish to inspect the clipping region that has been set
|
||||
* on the graphics context to render itself more efficiently. This
|
||||
* method will only be called after it has been established that this
|
||||
* media's bounds intersect the clipping region.
|
||||
*/
|
||||
public abstract void paint (Graphics2D gfx);
|
||||
|
||||
/**
|
||||
* Called when the appropriate media manager has been paused for some
|
||||
* length of time and is then unpaused. Media should adjust any time stamps
|
||||
* that are maintained internally forward by the delta so that time
|
||||
* maintains the illusion of flowing smoothly forward.
|
||||
*/
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the media's bounding rectangle for later painting.
|
||||
*/
|
||||
public void invalidate ()
|
||||
{
|
||||
if (_mgr != null) {
|
||||
_mgr.getRegionManager().invalidateRegion(_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location.
|
||||
*/
|
||||
public void setLocation (int x, int y)
|
||||
{
|
||||
_bounds.x = x;
|
||||
_bounds.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle containing all the pixels rendered by this media.
|
||||
*/
|
||||
public Rectangle getBounds ()
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the render order associated with this media. Media
|
||||
* can be rendered in two layers; those with negative render order and
|
||||
* those with positive render order. In the same layer, they
|
||||
* will be rendered according to their render order's cardinal value
|
||||
* (least to greatest). Those with the same render order value will be
|
||||
* rendered in arbitrary order.
|
||||
*
|
||||
* <p> This must be set <em>before</em> the media is added to the
|
||||
* appropriate manager and must not change while the manager is
|
||||
* managing it. If you wish to change the render order, remove the
|
||||
* media from the manager, change the order and add it back again.
|
||||
*/
|
||||
public void setRenderOrder (int renderOrder)
|
||||
{
|
||||
_renderOrder = renderOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the render order of this media element.
|
||||
*/
|
||||
public int getRenderOrder ()
|
||||
{
|
||||
return _renderOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the media.
|
||||
*/
|
||||
protected final void init (AbstractMediaManager manager)
|
||||
{
|
||||
_mgr = manager;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the media has had its manager set.
|
||||
* Derived classes may override this method, but should be sure to
|
||||
* call <code>super.init()</code>.
|
||||
*/
|
||||
protected void init ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the media manager after the media is removed from service.
|
||||
* Derived classes may override this method, but should be sure to
|
||||
* call <code>super.shutdown()</code>.
|
||||
*/
|
||||
protected void shutdown ()
|
||||
{
|
||||
_mgr = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified observer to this media element.
|
||||
*/
|
||||
protected void addObserver (Object obs)
|
||||
{
|
||||
if (_observers == null) {
|
||||
_observers = new ArrayList();
|
||||
|
||||
} else if (_observers.contains(obs)) {
|
||||
Log.info("Attempt to observe media already observing " +
|
||||
"[media=" + this + ", obs=" + obs + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
_observers.add(obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps this media to a String object.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("[");
|
||||
toString(buf);
|
||||
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 information to the string buffer.
|
||||
*/
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("bounds=").append(StringUtil.toString(_bounds));
|
||||
buf.append(", renderOrder=").append(_renderOrder);
|
||||
}
|
||||
|
||||
/** The layer in which to render. */
|
||||
protected int _renderOrder = 0;
|
||||
|
||||
/** The bounds of the media's rendering area. */
|
||||
protected Rectangle _bounds;
|
||||
|
||||
/** Our manager. */
|
||||
protected AbstractMediaManager _mgr;
|
||||
|
||||
/** Our observers. */
|
||||
protected ArrayList _observers = null;
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// $Id: AbstractMediaManager.java,v 1.1 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Manages, ticks, and paints AbstractMedia.
|
||||
*/
|
||||
public abstract class AbstractMediaManager
|
||||
implements MediaConstants
|
||||
{
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AbstractMediaManager (RegionManager remgr)
|
||||
{
|
||||
_remgr = remgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the region manager that the mediamanager is using.
|
||||
*/
|
||||
public RegionManager getRegionManager ()
|
||||
{
|
||||
return _remgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all registered media in the given layer that intersect
|
||||
* the supplied clipping rectangle to the given graphics context.
|
||||
*
|
||||
* @param layer the layer to render; one of {@link #FRONT}, {@link
|
||||
* #BACK}, or {@link #ALL}. The front layer contains all animations
|
||||
* with a positive render order; the back layer contains all
|
||||
* animations with a negative render order; all, both.
|
||||
*/
|
||||
public void renderMedia (Graphics2D gfx, int layer, Shape clip)
|
||||
{
|
||||
for (int ii=0, nn=_media.size(); ii < nn; ii++) {
|
||||
AbstractMedia media = (AbstractMedia) _media.get(ii);
|
||||
int order = media.getRenderOrder();
|
||||
try {
|
||||
if (((layer == ALL) ||
|
||||
(layer == FRONT && order >= 0) ||
|
||||
(layer == BACK && order < 0)) &&
|
||||
clip.intersects(media.getBounds())) {
|
||||
media.paint(gfx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.warning("Failed to render media " +
|
||||
"[media=" + media + ", e=" + e + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called every frame so that the media can be properly
|
||||
* updated.
|
||||
*/
|
||||
public void tick (long tickStamp)
|
||||
{
|
||||
tickAllMedia(tickStamp);
|
||||
dispatchNotifications();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the manager is paused for some length of time, it should
|
||||
* be fast forwarded by the appropriate number of milliseconds. This
|
||||
* allows media to smoothly pick up where they left off rather than
|
||||
* abruptly jumping into the future, thinking that some outrageous
|
||||
* amount of time passed since their last tick.
|
||||
*/
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
for (int ii=0, nn=_media.size(); ii < nn; ii++) {
|
||||
((AbstractMedia) _media.get(ii)).fastForward(timeDelta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link AbstractMedia#tick} on all media to give
|
||||
* them a chance to move about, change their look, generate dirty
|
||||
* regions, and so forth.
|
||||
*/
|
||||
protected void tickAllMedia (long tickStamp)
|
||||
{
|
||||
// we tick media in reverse order, because some may remove
|
||||
// themselves on the tick
|
||||
for (int ii=_media.size() - 1; ii >= 0; ii--) {
|
||||
((AbstractMedia) _media.get(ii)).tick(tickStamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the specified media into this manager, return true on success.
|
||||
*/
|
||||
protected boolean insertMedia (AbstractMedia media)
|
||||
{
|
||||
if (_media.contains(media)) {
|
||||
Log.warning("Attempt to insert media more than once " +
|
||||
"[media=" + media + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
_media.insertSorted(media, RENDER_ORDER);
|
||||
media.init(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified media from this manager, return true on success.
|
||||
*/
|
||||
protected boolean removeMedia (AbstractMedia media)
|
||||
{
|
||||
if (_media.remove(media)) {
|
||||
media.invalidate();
|
||||
media.shutdown();
|
||||
return true;
|
||||
}
|
||||
Log.warning("Attempt to remove media that wasn't inserted " +
|
||||
"[media=" + media + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all media from the manager. This does not invalidate
|
||||
* their vacated bounds, it is assumed that it will be ok.
|
||||
*/
|
||||
protected void clearMedia ()
|
||||
{
|
||||
for (int ii=_media.size() - 1; ii >= 0; ii--) {
|
||||
AbstractMedia media = (AbstractMedia) _media.remove(ii);
|
||||
media.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue the event for dispatching after we've ticked all
|
||||
* the media.
|
||||
*/
|
||||
public void queueNotification (ArrayList observers, Object event)
|
||||
{
|
||||
_notify.add(new Object[] {observers, event});
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch all queued events.
|
||||
*/
|
||||
protected void dispatchNotifications ()
|
||||
{
|
||||
for (int ii=0, nn=_notify.size(); ii < nn; ii++) {
|
||||
Object[] junk = (Object[]) _notify.remove(0);
|
||||
ArrayList observers = (ArrayList) junk[0];
|
||||
Object event = junk[1];
|
||||
|
||||
dispatchEvent(observers, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the specified event to the specified observers.
|
||||
*/
|
||||
protected abstract void dispatchEvent (ArrayList observers, Object event);
|
||||
|
||||
/** The Region Manager. */
|
||||
protected RegionManager _remgr;
|
||||
|
||||
/** List of observers to notify at the end of the tick. */
|
||||
protected ArrayList _notify = new ArrayList();
|
||||
|
||||
/** Our render-order sorted list of media. */
|
||||
protected SortableArrayList _media = new SortableArrayList();
|
||||
|
||||
/** Used to sort media by render order. */
|
||||
protected static final Comparator RENDER_ORDER = new Comparator() {
|
||||
public int compare (Object o1, Object o2) {
|
||||
int result = (((AbstractMedia)o1)._renderOrder -
|
||||
((AbstractMedia)o2)._renderOrder);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
|
||||
} else {
|
||||
// find some other way to keep them stable relative to each
|
||||
// other.
|
||||
return o1.hashCode() - o2.hashCode();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: MediaPanel.java,v 1.17 2002/06/25 17:31:16 mdb Exp $
|
||||
// $Id: MediaPanel.java,v 1.18 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
@@ -371,8 +371,8 @@ public class MediaPanel extends JComponent
|
||||
*/
|
||||
protected void paintBits (Graphics2D gfx, int layer, Rectangle dirty)
|
||||
{
|
||||
_animmgr.renderAnimations(gfx, layer, dirty);
|
||||
_spritemgr.renderSprites(gfx, layer, dirty);
|
||||
_animmgr.renderMedia(gfx, layer, dirty);
|
||||
_spritemgr.renderMedia(gfx, layer, dirty);
|
||||
}
|
||||
|
||||
/** The frame manager with whom we register. */
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
//
|
||||
// $Id: Animation.java,v 1.8 2002/09/20 21:28:20 mdb Exp $
|
||||
// $Id: Animation.java,v 1.9 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.animation;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.AbstractMedia;
|
||||
import com.threerings.media.Log;
|
||||
|
||||
/**
|
||||
@@ -17,7 +13,7 @@ import com.threerings.media.Log;
|
||||
* provide animation functionality. It is generally used in conjunction
|
||||
* with an {@link AnimationManager}.
|
||||
*/
|
||||
public abstract class Animation
|
||||
public abstract class Animation extends AbstractMedia
|
||||
{
|
||||
/**
|
||||
* Constructs an animation.
|
||||
@@ -26,80 +22,7 @@ public abstract class Animation
|
||||
*/
|
||||
public Animation (Rectangle bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the render order of this animation.
|
||||
*/
|
||||
public int getRenderOrder ()
|
||||
{
|
||||
return _renderOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the render order associated with this animation. Animations
|
||||
* can be rendered in two layers; those with negative render order and
|
||||
* those with positive render order. In the same layer, animations
|
||||
* will be rendered according to their render order's cardinal value
|
||||
* (least to greatest). Those with the same render order value will be
|
||||
* rendered in arbitrary order.
|
||||
*
|
||||
* <p> This must be set <em>before</em> the animation is handed to the
|
||||
* {@link AnimationManager} and must not change while the {@link
|
||||
* AnimationManager} is managing the animation. If you wish to change
|
||||
* the render order, remove the animation from the manager, change the
|
||||
* order and add it back again.
|
||||
*/
|
||||
public void setRenderOrder (int value)
|
||||
{
|
||||
_renderOrder = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location at which this animation will be rendered.
|
||||
*/
|
||||
public void setLocation (int x, int y)
|
||||
{
|
||||
_bounds.x = x;
|
||||
_bounds.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle containing all pixels rendered by this
|
||||
* animation.
|
||||
*/
|
||||
public Rectangle getBounds ()
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically by the {@link AnimationManager} to give the
|
||||
* animation a chance to do its thing.
|
||||
*
|
||||
* @param tickStamp the system time for this tick.
|
||||
*/
|
||||
public abstract void tick (long tickStamp);
|
||||
|
||||
/**
|
||||
* Called by the {@link AnimationManager} to request that the
|
||||
* animation render itself with the given graphics context. The
|
||||
* animation may wish to inspect the clipping region that has been set
|
||||
* on the graphics context to render itself more efficiently. This
|
||||
* method will only be called after it has been established that this
|
||||
* animation's bounds intersect the clipping region.
|
||||
*/
|
||||
public abstract void paint (Graphics2D gfx);
|
||||
|
||||
/**
|
||||
* This is called if the animation manager is paused for some length
|
||||
* of time and then unpaused. Animations should adjust any time stamps
|
||||
* they are maintaining internally by the delta so that time maintains
|
||||
* the illusion of flowing smoothly forward.
|
||||
*/
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
super(bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,14 +43,6 @@ public abstract class Animation
|
||||
_finished = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the bounds of this animation.
|
||||
*/
|
||||
public void invalidate ()
|
||||
{
|
||||
_animmgr.getRegionManager().invalidateRegion(_bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the animation is finished and the animation manager has
|
||||
* removed it from service.
|
||||
@@ -142,76 +57,20 @@ public abstract class Animation
|
||||
*/
|
||||
public void addAnimationObserver (AnimationObserver obs)
|
||||
{
|
||||
// create the observer list if it doesn't yet exist
|
||||
if (_observers == null) {
|
||||
_observers = new ArrayList();
|
||||
}
|
||||
|
||||
// make sure each observer observes only once
|
||||
if (_observers.contains(obs)) {
|
||||
Log.info("Attempt to observe animation already observing " +
|
||||
"[anim=" + this + ", obs=" + obs + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// add the observer
|
||||
_observers.add(obs);
|
||||
addObserver(obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies any animation observers that the given animation event has
|
||||
* occurred.
|
||||
*/
|
||||
public void notifyObservers (AnimationEvent e)
|
||||
public void notifyObservers (AnimationEvent event)
|
||||
{
|
||||
int size = (_observers == null) ? 0 : _observers.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
((AnimationObserver)_observers.get(ii)).handleEvent(e);
|
||||
if (_observers != null) {
|
||||
_mgr.queueNotification(_observers, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the animation.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("[");
|
||||
toString(buf);
|
||||
return buf.append("]").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called automatically when an animation is added to an animation
|
||||
* manager for management.
|
||||
*/
|
||||
protected void setAnimationManager (AnimationManager animmgr)
|
||||
{
|
||||
_animmgr = animmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by derived classes (which should be sure
|
||||
* to call <code>super.toString()</code>) to append the derived class
|
||||
* specific animation information to the string buffer.
|
||||
*/
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("bounds=").append(StringUtil.toString(_bounds));
|
||||
}
|
||||
|
||||
/** Our animation manager. */
|
||||
protected AnimationManager _animmgr;
|
||||
|
||||
/** Whether the animation is finished. */
|
||||
protected boolean _finished = false;
|
||||
|
||||
/** The animation bounds. */
|
||||
protected Rectangle _bounds;
|
||||
|
||||
/** The render order of this animation. */
|
||||
protected int _renderOrder;
|
||||
|
||||
/** The list of animation observers. */
|
||||
protected ArrayList _observers;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
//
|
||||
// $Id: AnimationManager.java,v 1.13 2002/09/20 21:28:20 mdb Exp $
|
||||
// $Id: AnimationManager.java,v 1.14 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.animation;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.SortableArrayList;
|
||||
|
||||
import com.threerings.media.AbstractMediaManager;
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.MediaConstants;
|
||||
import com.threerings.media.RegionManager;
|
||||
|
||||
/**
|
||||
@@ -19,8 +16,7 @@ import com.threerings.media.RegionManager;
|
||||
* manager itself is ticked and generating events when animations finish
|
||||
* and suchlike.
|
||||
*/
|
||||
public class AnimationManager
|
||||
implements MediaConstants
|
||||
public class AnimationManager extends AbstractMediaManager
|
||||
{
|
||||
/**
|
||||
* Construct and initialize the animation manager which readies itself
|
||||
@@ -28,7 +24,7 @@ public class AnimationManager
|
||||
*/
|
||||
public AnimationManager (RegionManager remgr)
|
||||
{
|
||||
_remgr = remgr;
|
||||
super(remgr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,14 +33,7 @@ public class AnimationManager
|
||||
*/
|
||||
public void registerAnimation (Animation anim)
|
||||
{
|
||||
if (_anims.contains(anim)) {
|
||||
Log.warning("Attempt to register animation more than once " +
|
||||
"[anim=" + anim + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
anim.setAnimationManager(this);
|
||||
_anims.insertSorted(anim, RENDER_ORDER);
|
||||
insertMedia(anim);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,43 +44,17 @@ public class AnimationManager
|
||||
*/
|
||||
public void unregisterAnimation (Animation anim)
|
||||
{
|
||||
// un-register the animation
|
||||
if (!_anims.remove(anim)) {
|
||||
Log.warning("Attempt to un-register animation that isn't " +
|
||||
"registered [anim=" + anim + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// invalidate its bounds
|
||||
_remgr.invalidateRegion(anim.getBounds());
|
||||
removeMedia(anim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the region manager that the animation manager is
|
||||
* using to collect invalid regions every frame. This should generally
|
||||
* only be used by animations that want to invalidate themselves.
|
||||
*/
|
||||
public RegionManager getRegionManager ()
|
||||
// documentation inherited
|
||||
protected void tickAllMedia (long tickStamp)
|
||||
{
|
||||
return _remgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles updating animations and generating associated events.
|
||||
*
|
||||
* @param tickStamp the system clock at the time of the tick.
|
||||
*/
|
||||
public void tick (long tickStamp)
|
||||
{
|
||||
// tick all of our animations
|
||||
int size = _anims.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
((Animation)_anims.get(ii)).tick(tickStamp);
|
||||
}
|
||||
super.tickAllMedia(tickStamp);
|
||||
|
||||
// remove any finished animations
|
||||
for (int ii = size - 1; ii >= 0; ii--) {
|
||||
Animation anim = (Animation)_anims.get(ii);
|
||||
for (int ii=_media.size() - 1; ii >= 0; ii--) {
|
||||
Animation anim = (Animation)_media.get(ii);
|
||||
if (anim.isFinished()) {
|
||||
// let any animation observers know that we're done
|
||||
anim.notifyObservers(new AnimationCompletedEvent(anim));
|
||||
@@ -104,68 +67,12 @@ public class AnimationManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the animation manager is paused for some length of time, it
|
||||
* should be fast forwarded by the appropriate number of milliseconds.
|
||||
* This allows animations to smoothly pick up where they left off
|
||||
* rather than abruptly jumping into the future, thinking that some
|
||||
* outrageous amount of time passed since their last tick.
|
||||
*/
|
||||
public void fastForward (long timeDelta)
|
||||
// documentation inherited
|
||||
protected void dispatchEvent (ArrayList observers, Object event)
|
||||
{
|
||||
// fast forward all of our animations
|
||||
int size = _anims.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
((Animation)_anims.get(ii)).fastForward(timeDelta);
|
||||
AnimationEvent aevt = (AnimationEvent) event;
|
||||
for (int ii=0, nn=observers.size(); ii < nn; ii++) {
|
||||
((AnimationObserver) observers.get(ii)).handleEvent(aevt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all registered animations in the given layer that intersect
|
||||
* the supplied clipping rectangle to the given graphics context.
|
||||
*
|
||||
* @param layer the layer to render; one of {@link #FRONT}, {@link
|
||||
* #BACK}, or {@link #ALL}. The front layer contains all animations
|
||||
* with a positive render order; the back layer contains all
|
||||
* animations with a negative render order; all, both.
|
||||
*/
|
||||
public void renderAnimations (Graphics2D gfx, int layer, Shape clip)
|
||||
{
|
||||
// now paint them
|
||||
int size = _anims.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Animation anim = (Animation)_anims.get(ii);
|
||||
int order = anim.getRenderOrder();
|
||||
try {
|
||||
if (((layer == ALL) ||
|
||||
(layer == FRONT && order >= 0) ||
|
||||
(layer == BACK && order < 0)) &&
|
||||
clip.intersects(anim.getBounds())) {
|
||||
anim.paint(gfx);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Failed to render animation " +
|
||||
"[anim=" + anim + ", e=" + e + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Used to accumulate dirty regions. */
|
||||
protected RegionManager _remgr;
|
||||
|
||||
/** The list of animations. */
|
||||
protected SortableArrayList _anims = new SortableArrayList();
|
||||
|
||||
/** Used to sort animations prior to painting. */
|
||||
protected static final Comparator RENDER_ORDER = new Comparator() {
|
||||
public int compare (Object o1, Object o2) {
|
||||
return (((Animation)o1)._renderOrder -
|
||||
((Animation)o2)._renderOrder);
|
||||
}
|
||||
public boolean equals (Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: ImageSprite.java,v 1.14 2002/09/17 20:21:19 mdb Exp $
|
||||
// $Id: ImageSprite.java,v 1.15 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.sprite;
|
||||
|
||||
@@ -81,9 +81,9 @@ public class ImageSprite extends Sprite
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void init (SpriteManager spritemgr)
|
||||
protected void init ()
|
||||
{
|
||||
super.init(spritemgr);
|
||||
super.init();
|
||||
|
||||
// now that we have our spritemanager, we can initialize our frames
|
||||
setFrameIndex(0, true);
|
||||
@@ -187,8 +187,8 @@ public class ImageSprite extends Sprite
|
||||
dirty.add(_bounds);
|
||||
|
||||
// give the dirty rectangle to the region manager
|
||||
if (_spritemgr != null) {
|
||||
_spritemgr.getRegionManager().addDirtyRegion(dirty);
|
||||
if (_mgr != null) {
|
||||
_mgr.getRegionManager().addDirtyRegion(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: LabelSprite.java,v 1.3 2002/07/08 21:15:35 mdb Exp $
|
||||
// $Id: LabelSprite.java,v 1.4 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.sprite;
|
||||
|
||||
@@ -35,9 +35,9 @@ public class LabelSprite extends Sprite
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void init (SpriteManager spritemgr)
|
||||
protected void init ()
|
||||
{
|
||||
super.init(spritemgr);
|
||||
super.init();
|
||||
|
||||
// size the bounds to fit our label
|
||||
Dimension size = _label.getSize();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Sprite.java,v 1.50 2002/07/08 21:15:35 mdb Exp $
|
||||
// $Id: Sprite.java,v 1.51 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.sprite;
|
||||
|
||||
@@ -7,10 +7,9 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.threerings.util.DirectionCodes;
|
||||
|
||||
import com.threerings.media.AbstractMedia;
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.util.Path;
|
||||
import com.threerings.media.util.Pathable;
|
||||
@@ -20,7 +19,7 @@ import com.threerings.media.util.Pathable;
|
||||
* view. A sprite has a position and orientation within the view, and can
|
||||
* be moved along a path.
|
||||
*/
|
||||
public abstract class Sprite
|
||||
public abstract class Sprite extends AbstractMedia
|
||||
implements DirectionCodes, Pathable
|
||||
{
|
||||
/**
|
||||
@@ -33,27 +32,7 @@ public abstract class Sprite
|
||||
*/
|
||||
public Sprite ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the sprite manager to initialize the sprite when a sprite
|
||||
* is added to said manager for management.
|
||||
*
|
||||
* @param spritemgr the sprite manager.
|
||||
*/
|
||||
protected void init (SpriteManager spritemgr)
|
||||
{
|
||||
_spritemgr = spritemgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the sprite manager after the sprite is removed from
|
||||
* service. Derived classes may override this method but should be
|
||||
* sure to call <code>super.shutdown()</code>.
|
||||
*/
|
||||
protected void shutdown ()
|
||||
{
|
||||
_spritemgr = null;
|
||||
super(new Rectangle());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,14 +71,6 @@ public abstract class Sprite
|
||||
return _bounds.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sprite's rendered bounds in pixels.
|
||||
*/
|
||||
public Rectangle getBounds ()
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sprites have an orientation in one of the eight cardinal
|
||||
* directions: <code>NORTH</code>, <code>NORTHEAST</code>, etc.
|
||||
@@ -125,31 +96,7 @@ public abstract class Sprite
|
||||
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.
|
||||
*
|
||||
* @param x the x-position in pixels.
|
||||
* @param y the y-position in pixels.
|
||||
*/
|
||||
// documentation inherited
|
||||
public void setLocation (int x, int y)
|
||||
{
|
||||
// start with our current bounds
|
||||
@@ -165,24 +112,20 @@ public abstract class Sprite
|
||||
|
||||
// grow the dirty rectangle to incorporate our new bounds and pass
|
||||
// the dirty region to our region manager
|
||||
if (_spritemgr != null) {
|
||||
if (_mgr != null) {
|
||||
// if our new bounds intersect our old bounds, grow a single
|
||||
// dirty rectangle to incorporate them both
|
||||
if (_bounds.intersects(dirty)) {
|
||||
dirty.add(_bounds);
|
||||
} else {
|
||||
// otherwise invalidate our new bounds separately
|
||||
_spritemgr.getRegionManager().invalidateRegion(_bounds);
|
||||
_mgr.getRegionManager().invalidateRegion(_bounds);
|
||||
}
|
||||
_spritemgr.getRegionManager().addDirtyRegion(dirty);
|
||||
_mgr.getRegionManager().addDirtyRegion(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the sprite to the specified graphics context.
|
||||
*
|
||||
* @param gfx the graphics context.
|
||||
*/
|
||||
// documentation inherited
|
||||
public void paint (Graphics2D gfx)
|
||||
{
|
||||
gfx.draw(_bounds);
|
||||
@@ -302,24 +245,7 @@ public abstract class Sprite
|
||||
notifyObservers(new PathCompletedEvent(this, oldpath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the sprite's bounding rectangle for later repainting.
|
||||
*/
|
||||
public void invalidate ()
|
||||
{
|
||||
if (_spritemgr != null) {
|
||||
_spritemgr.getRegionManager().invalidateRegion(_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called periodically by the sprite manager to give
|
||||
* the sprite a chance to update its state. The sprite manager will
|
||||
* attempt to call this with the desired refresh rate, but will drop
|
||||
* calls to tick if it can't keep up. Thus, a sprite should rely on
|
||||
* the timestamp information to compute elapsed progress if it wishes
|
||||
* to handle heavy loads gracefully.
|
||||
*/
|
||||
// documentation inherited
|
||||
public void tick (long tickStamp)
|
||||
{
|
||||
// if we've a path, move the sprite along toward its destination
|
||||
@@ -328,12 +254,7 @@ public abstract class Sprite
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called if the sprite manager is paused for some length of
|
||||
* time and then unpaused. Sprites should adjust any time stamps they
|
||||
* are maintaining internally by the delta so that time maintains the
|
||||
* illusion of flowing smoothly forward.
|
||||
*/
|
||||
// documentation inherited
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
// fast forward any path we're following
|
||||
@@ -360,20 +281,7 @@ public abstract class Sprite
|
||||
*/
|
||||
public void addSpriteObserver (SpriteObserver obs)
|
||||
{
|
||||
// create the observer list if it doesn't yet exist
|
||||
if (_observers == null) {
|
||||
_observers = new ArrayList();
|
||||
}
|
||||
|
||||
// make sure each observer observes only once
|
||||
if (_observers.contains(obs)) {
|
||||
Log.info("Attempt to observe sprite already observing " +
|
||||
"[sprite=" + this + ", obs=" + obs + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// add the observer
|
||||
_observers.add(obs);
|
||||
addObserver(obs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,39 +292,20 @@ public abstract class Sprite
|
||||
protected void notifyObservers (SpriteEvent event)
|
||||
{
|
||||
if (_observers != null) {
|
||||
// we pass this notification off to the sprite manager so that
|
||||
// it can dispatch all of the notifications at once after all
|
||||
// ticking has been completed
|
||||
_spritemgr.notifySpriteObservers(_observers, event);
|
||||
_mgr.queueNotification(_observers, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the sprite.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer("[");
|
||||
toString(buf);
|
||||
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 sprite information to the string buffer.
|
||||
*/
|
||||
// documentation inherited
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("ox=").append(_ox);
|
||||
super.toString(buf);
|
||||
buf.append(", ox=").append(_ox);
|
||||
buf.append(", oy=").append(_oy);
|
||||
buf.append(", oxoff=").append(_oxoff);
|
||||
buf.append(", oyoff=").append(_oyoff);
|
||||
}
|
||||
|
||||
/** The sprite manager. */
|
||||
protected SpriteManager _spritemgr;
|
||||
|
||||
/** The location of the sprite's origin in pixel coordinates. If the
|
||||
* sprite positions itself via a hotspot that is not the upper left
|
||||
* coordinate of the sprite's bounds, the offset to the hotspot should
|
||||
@@ -429,18 +318,9 @@ public abstract class Sprite
|
||||
* its bounds. */
|
||||
protected int _oxoff, _oyoff;
|
||||
|
||||
/** Our rendered bounds in pixel coordinates. */
|
||||
protected Rectangle _bounds = new Rectangle();
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,32 @@
|
||||
//
|
||||
// $Id: SpriteManager.java,v 1.37 2002/09/20 02:19:53 mdb Exp $
|
||||
// $Id: SpriteManager.java,v 1.38 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.media.sprite;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
import com.samskivert.util.SortableArrayList;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
import com.threerings.media.AbstractMediaManager;
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.MediaConstants;
|
||||
import com.threerings.media.RegionManager;
|
||||
|
||||
/**
|
||||
* The sprite manager manages the sprites running about in the game.
|
||||
*/
|
||||
public class SpriteManager
|
||||
implements MediaConstants
|
||||
public class SpriteManager extends AbstractMediaManager
|
||||
{
|
||||
/**
|
||||
* Construct and initialize the sprite manager.
|
||||
*/
|
||||
public SpriteManager (RegionManager remgr)
|
||||
{
|
||||
_sprites = new SortableArrayList();
|
||||
_notify = new ArrayList();
|
||||
_remgr = remgr;
|
||||
super(remgr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,9 +43,9 @@ public class SpriteManager
|
||||
*/
|
||||
public void getIntersectingSprites (List list, Shape shape)
|
||||
{
|
||||
int size = _sprites.size();
|
||||
int size = _media.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
Sprite sprite = (Sprite)_media.get(ii);
|
||||
if (sprite.intersects(shape)) {
|
||||
list.add(sprite);
|
||||
}
|
||||
@@ -75,9 +65,9 @@ public class SpriteManager
|
||||
*/
|
||||
public void getHitSprites (List list, int x, int y)
|
||||
{
|
||||
int size = _sprites.size();
|
||||
int size = _media.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
Sprite sprite = (Sprite)_media.get(ii);
|
||||
if (sprite.hitTest(x, y)) {
|
||||
list.add(sprite);
|
||||
}
|
||||
@@ -91,12 +81,10 @@ public class SpriteManager
|
||||
*/
|
||||
public void addSprite (Sprite sprite)
|
||||
{
|
||||
// initialize the sprite
|
||||
sprite.init(this);
|
||||
// add the sprite to our list
|
||||
_sprites.add(sprite);
|
||||
// and invalidate the sprite's original position
|
||||
sprite.invalidate();
|
||||
if (insertMedia(sprite)) {
|
||||
// and invalidate the sprite's original position
|
||||
sprite.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +94,7 @@ public class SpriteManager
|
||||
*/
|
||||
public List getSprites ()
|
||||
{
|
||||
return Collections.unmodifiableList(_sprites);
|
||||
return Collections.unmodifiableList(_media);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,12 +105,7 @@ public class SpriteManager
|
||||
*/
|
||||
public void removeSprite (Sprite sprite)
|
||||
{
|
||||
// invalidate the current sprite position
|
||||
sprite.invalidate();
|
||||
// remove the sprite from our list
|
||||
_sprites.remove(sprite);
|
||||
// clear out our manager reference
|
||||
sprite.shutdown();
|
||||
removeMedia(sprite);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,51 +116,7 @@ public class SpriteManager
|
||||
*/
|
||||
public void clearSprites ()
|
||||
{
|
||||
int size = _sprites.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
sprite.shutdown();
|
||||
}
|
||||
_sprites.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the region manager that the sprite manager is
|
||||
* using to collect invalid regions every frame. This should generally
|
||||
* only be used by sprites that want to invalidate themselves.
|
||||
*/
|
||||
public RegionManager getRegionManager ()
|
||||
{
|
||||
return _remgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render to the given graphics context the sprites intersecting the
|
||||
* given shape and residing in the specified layer.
|
||||
*
|
||||
* @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.
|
||||
* @param bounds the bounding shape.
|
||||
*/
|
||||
public void renderSprites (Graphics2D gfx, int layer, Shape bounds)
|
||||
{
|
||||
// TODO: optimize to store sprites based on quadrants they're in
|
||||
// (or somesuch), and sorted, so that we can more quickly
|
||||
// determine which sprites to draw.
|
||||
|
||||
int size = _sprites.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
int order = sprite.getRenderOrder();
|
||||
if (((layer == ALL) ||
|
||||
(layer == FRONT && order >= 0) ||
|
||||
(layer == BACK && order < 0)) &&
|
||||
sprite.intersects(bounds)) {
|
||||
sprite.paint(gfx);
|
||||
}
|
||||
}
|
||||
clearMedia();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,187 +126,91 @@ public class SpriteManager
|
||||
*/
|
||||
public void renderSpritePaths (Graphics2D gfx)
|
||||
{
|
||||
int size = _sprites.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
for (int ii=0, nn=_media.size(); ii < nn; ii++) {
|
||||
Sprite sprite = (Sprite)_media.get(ii);
|
||||
sprite.paintPath(gfx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called every frame so that the sprites can be properly
|
||||
* updated. Normally a sprite manager is used in conjunction with an
|
||||
* animated panel which case this is called automatically.
|
||||
*/
|
||||
public void tick (long tickStamp)
|
||||
// documentation inherited
|
||||
protected void dispatchEvent (ArrayList observers, Object event)
|
||||
{
|
||||
// tick all sprites
|
||||
tickSprites(tickStamp);
|
||||
|
||||
// re-sort the sprite list to account for potential new positions
|
||||
_sprites.sort(SPRITE_COMP);
|
||||
|
||||
// // 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the sprite manager is paused for some length of time, it should
|
||||
* be fast forwarded by the appropriate number of milliseconds. This
|
||||
* allows sprites to smoothly pick up where they left off rather than
|
||||
* abruptly jumping into the future, thinking that some outrageous
|
||||
* amount of time passed since their last tick.
|
||||
*/
|
||||
public void fastForward (long timeDelta)
|
||||
{
|
||||
int size = _sprites.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
sprite.fastForward(timeDelta);
|
||||
SpriteEvent sevt = (SpriteEvent) event;
|
||||
for (int ii=0, nn=observers.size(); ii < nn; ii++) {
|
||||
((SpriteObserver) observers.get(ii)).handleEvent(sevt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link Sprite#tick} on all sprite objects to give them a
|
||||
* chance to move themselves about, change their display image,
|
||||
* generate dirty regions and so forth.
|
||||
*/
|
||||
protected void tickSprites (long tickStamp)
|
||||
{
|
||||
// we tick sprites in reverse order so as not to freak out if a
|
||||
// sprite is removed as a result of our calling tick() on it
|
||||
int size = _sprites.size();
|
||||
for (int ii = size-1; ii >= 0; ii--) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
sprite.tick(tickStamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all sprites for collisions with others and inform any
|
||||
* sprite observers.
|
||||
*/
|
||||
protected void handleCollisions ()
|
||||
{
|
||||
// gather a list of all sprite collisions
|
||||
int size = _sprites.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
checkCollisions(ii, size, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a sprite for collision with any other sprites in the
|
||||
* 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.
|
||||
*/
|
||||
protected void checkCollisions (int idx, int size, Sprite sprite)
|
||||
{
|
||||
// TODO: make this handle quickly moving objects that may pass
|
||||
// through each other.
|
||||
|
||||
// if we're the last sprite we know we've already handled any
|
||||
// collisions
|
||||
if (idx == (size - 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate the x-position of the right edge of the sprite we're
|
||||
// checking for collisions
|
||||
Rectangle bounds = sprite.getBounds();
|
||||
int edgeX = bounds.x + bounds.width;
|
||||
|
||||
for (int ii = (idx + 1); ii < size; ii++) {
|
||||
Sprite other = (Sprite)_sprites.get(ii);
|
||||
Rectangle obounds = other.getBounds();
|
||||
if (obounds.x > edgeX) {
|
||||
// since sprites are stored in the list sorted by
|
||||
// ascending x-position, we know this sprite and any
|
||||
// other sprites farther on in the list can't possibly
|
||||
// intersect with the sprite we're checking, so we're
|
||||
// done.
|
||||
return;
|
||||
|
||||
} else if (obounds.intersects(bounds)) {
|
||||
sprite.notifyObservers(new CollisionEvent(sprite, other));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all sprite observers of any sprite events that took place
|
||||
* during our most recent <code>tick()</code>.
|
||||
*/
|
||||
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.handleEvent(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link Sprite#notifyObservers} to note that the
|
||||
* sprite's observers should be informed of a sprite event once
|
||||
* the current <code>tick()</code> 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 sprite objects we're managing. */
|
||||
protected SortableArrayList _sprites;
|
||||
|
||||
/** The list of pending sprite notifications. */
|
||||
protected ArrayList _notify;
|
||||
|
||||
/** Used to accumulate dirty regions. */
|
||||
protected RegionManager _remgr;
|
||||
|
||||
/** The comparator used to sort sprites by horizontal position. */
|
||||
protected static final Comparator SPRITE_COMP = new SpriteComparator();
|
||||
|
||||
/** Used to sort sprites. */
|
||||
protected static class SpriteComparator implements Comparator
|
||||
{
|
||||
public int compare (Object o1, Object o2)
|
||||
{
|
||||
Sprite s1 = (Sprite)o1;
|
||||
Sprite s2 = (Sprite)o2;
|
||||
return (s2.getX() - s1.getX());
|
||||
}
|
||||
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
return (obj == this);
|
||||
}
|
||||
}
|
||||
// NOTE- collision handling code is turned off for now. To re-implement,
|
||||
// a new array should be kept with sprites sorted in some sort of x/y order
|
||||
//
|
||||
// /**
|
||||
// * Check all sprites for collisions with others and inform any
|
||||
// * sprite observers.
|
||||
// */
|
||||
// protected void handleCollisions ()
|
||||
// {
|
||||
// // gather a list of all sprite collisions
|
||||
// int size = _sprites.size();
|
||||
// for (int ii = 0; ii < size; ii++) {
|
||||
// Sprite sprite = (Sprite)_sprites.get(ii);
|
||||
// checkCollisions(ii, size, sprite);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Check a sprite for collision with any other sprites in the
|
||||
// * 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.
|
||||
// */
|
||||
// protected void checkCollisions (int idx, int size, Sprite sprite)
|
||||
// {
|
||||
// // TODO: make this handle quickly moving objects that may pass
|
||||
// // through each other.
|
||||
//
|
||||
// // if we're the last sprite we know we've already handled any
|
||||
// // collisions
|
||||
// if (idx == (size - 1)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // calculate the x-position of the right edge of the sprite we're
|
||||
// // checking for collisions
|
||||
// Rectangle bounds = sprite.getBounds();
|
||||
// int edgeX = bounds.x + bounds.width;
|
||||
//
|
||||
// for (int ii = (idx + 1); ii < size; ii++) {
|
||||
// Sprite other = (Sprite)_sprites.get(ii);
|
||||
// Rectangle obounds = other.getBounds();
|
||||
// if (obounds.x > edgeX) {
|
||||
// // since sprites are stored in the list sorted by
|
||||
// // ascending x-position, we know this sprite and any
|
||||
// // other sprites farther on in the list can't possibly
|
||||
// // intersect with the sprite we're checking, so we're
|
||||
// // done.
|
||||
// return;
|
||||
//
|
||||
// } else if (obounds.intersects(bounds)) {
|
||||
// sprite.notifyObservers(new CollisionEvent(sprite, other));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// /** The comparator used to sort sprites by horizontal position. */
|
||||
// protected static final Comparator SPRITE_COMP = new SpriteComparator();
|
||||
//
|
||||
// /** Used to sort sprites. */
|
||||
// protected static class SpriteComparator implements Comparator
|
||||
// {
|
||||
// public int compare (Object o1, Object o2)
|
||||
// {
|
||||
// Sprite s1 = (Sprite)o1;
|
||||
// Sprite s2 = (Sprite)o2;
|
||||
// return (s2.getX() - s1.getX());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: SceneViewPanel.java,v 1.44 2002/09/24 07:56:25 shaper Exp $
|
||||
// $Id: SceneViewPanel.java,v 1.45 2002/10/08 21:03:37 ray Exp $
|
||||
|
||||
package com.threerings.miso.scene;
|
||||
|
||||
@@ -169,7 +169,7 @@ public class SceneViewPanel extends VirtualMediaPanel
|
||||
*/
|
||||
protected void paintBits (Graphics2D gfx, int layer, Rectangle dirty)
|
||||
{
|
||||
_animmgr.renderAnimations(gfx, layer, dirty);
|
||||
_animmgr.renderMedia(gfx, layer, dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user