diff --git a/src/java/com/threerings/media/animation/BlendAnimation.java b/src/java/com/threerings/media/animation/BlendAnimation.java new file mode 100644 index 000000000..cce1b288a --- /dev/null +++ b/src/java/com/threerings/media/animation/BlendAnimation.java @@ -0,0 +1,87 @@ +// +// $Id: BlendAnimation.java,v 1.1 2004/09/18 22:58:39 mdb Exp $ + +package com.threerings.media.animation; + +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; + +import com.threerings.media.image.Mirage; +import com.threerings.media.util.LinearTimeFunction; +import com.threerings.media.util.TimeFunction; + +/** + * Blends between a series of images using alpha. + */ +public class BlendAnimation extends Animation +{ + /** + * Blends from the starting image through each successive image in the + * specified amount of time (blending between each image takes place + * in delay milliseconds). + */ + public BlendAnimation (int x, int y, Mirage[] images, int delay) + { + super(new Rectangle(x, y, images[0].getWidth(), images[0].getHeight())); + _images = images; + int fades = images.length-1; + _tfunc = new LinearTimeFunction(0, 100 * fades, delay * fades); + } + + // documentation inherited + public void tick (long timestamp) + { + // check to see if our blend level has changed + int level = _tfunc.getValue(timestamp); + if (level == _level) { + return; + } + // stop if we reach the end + if (level == 100*(_images.length-1)) { + _finished = true; + } + _level = level; + invalidate(); + } + + // documentation inherited + public void fastForward (long timeDelta) + { + _tfunc.fastForward(timeDelta); + } + + // documentation inherited + public void paint (Graphics2D gfx) + { + int index = _level / 100; + float alpha = 1f - (_level % 100) / 100f; + + Composite ocomp = gfx.getComposite(); + gfx.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, alpha)); + _images[index].paint(gfx, _bounds.x, _bounds.y); + if (index < _images.length-1) { + gfx.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, 1f-alpha)); + _images[index+1].paint(gfx, _bounds.x, _bounds.y); + } + gfx.setComposite(ocomp); + } + + /** The images between which we are blending. */ + protected Mirage[] _images; + + /** The time function we're using to time our blends. */ + protected TimeFunction _tfunc; + + /** Our current blend level and image index all wrapped into one. */ + protected int _level; + + /** The alpha composite used to render our current image. */ + protected AlphaComposite _currentComp; + + /** The alpha composite used to render our "next" image. */ + protected AlphaComposite _nextComp; +} diff --git a/src/java/com/threerings/media/animation/GleamAnimation.java b/src/java/com/threerings/media/animation/GleamAnimation.java new file mode 100644 index 000000000..c4317df4d --- /dev/null +++ b/src/java/com/threerings/media/animation/GleamAnimation.java @@ -0,0 +1,150 @@ +// +// $Id: GleamAnimation.java,v 1.1 2004/09/18 22:58:39 mdb Exp $ + +package com.threerings.media.animation; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Transparency; + +import com.threerings.media.sprite.Sprite; +import com.threerings.media.sprite.SpriteManager; +import com.threerings.media.util.LinearTimeFunction; +import com.threerings.media.util.TimeFunction; + +/** + * Washes all non-transparent pixels in a sprite with a particular color + * (by compositing them with the solid color with progressively higher + * alpha values) and then back again. + */ +public class GleamAnimation extends Animation +{ + /** + * Creates a gleam animation with the supplied sprite. The sprite will + * be faded to the specified color and then back again. The sprite may + * be already added to the supplied sprite manager or not, but when + * the animation is complete, it will have been added. + * + * @param fadeIn if true, the sprite itself will be faded in as we + * fade up to the gleam color and the gleam color will fade out, + * leaving just the sprite imagery. + */ + public GleamAnimation (SpriteManager spmgr, Sprite sprite, Color color, + int upmillis, int downmillis, boolean fadeIn) + { + super(sprite.getBounds()); + _spmgr = spmgr; + _sprite = sprite; + _color = color; + _upfunc = new LinearTimeFunction(0, 750, upmillis); + _downfunc = new LinearTimeFunction(750, 0, downmillis); + _fadeIn = fadeIn; + } + + // documentation inherited + public void tick (long timestamp) + { + int alpha; + if (_upfunc != null) { + if ((alpha = _upfunc.getValue(timestamp)) == 750) { + _upfunc = null; + } + } else if (_downfunc != null) { + if ((alpha = _downfunc.getValue(timestamp)) == 0) { + _downfunc = null; + } + } else { + _finished = true; + _spmgr.addSprite(_sprite); + return; + } + + if (_alpha != alpha) { + _alpha = alpha; + invalidate(); + } + } + + // documentation inherited + public void fastForward (long timeDelta) + { + if (_upfunc != null) { + _upfunc.fastForward(timeDelta); + } else if (_downfunc != null) { + _downfunc.fastForward(timeDelta); + } + } + + // documentation inherited + public void paint (Graphics2D gfx) + { + // TODO: recreate our off image if the sprite bounds changed; we + // also need to change the bounds of our animation which might + // require some jockeying (especially if we shrink) + if (_offimg == null) { + _offimg = gfx.getDeviceConfiguration().createCompatibleImage( + _bounds.width, _bounds.height, Transparency.TRANSLUCENT); + } + + // create a mask image with our sprite and the appropriate color + Graphics2D ogfx = (Graphics2D)_offimg.getGraphics(); + try { + ogfx.setColor(_color); + ogfx.fillRect(0, 0, _bounds.width, _bounds.height); + ogfx.setComposite(AlphaComposite.DstAtop); + ogfx.translate(-_sprite.getX(), -_sprite.getY()); + _sprite.paint(ogfx); + } finally { + ogfx.dispose(); + } + + Composite ocomp = null; + Composite ncomp = AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, _alpha/1000f); + + // if we're fading the sprite in on the way up, set our alpha + // composite before we render the sprite + if (_fadeIn && _upfunc != null) { + ocomp = gfx.getComposite(); + gfx.setComposite(ncomp); + } + + // next render the sprite + _sprite.paint(gfx); + + // if we're not fading in, we still need to alpha the white bits + if (ocomp == null) { + ocomp = gfx.getComposite(); + gfx.setComposite(ncomp); + } + + // now alpha composite our mask atop the sprite + gfx.drawImage(_offimg, _sprite.getX(), _sprite.getY(), null); + gfx.setComposite(ocomp); + } + + // documentation inherited + protected void willStart (long tickStamp) + { + super.willStart(tickStamp); + + // remove the sprite we're fiddling with from the manager; we'll + // add it back when we're done + if (_spmgr.isManaged(_sprite)) { + _spmgr.removeSprite(_sprite); + } + } + + protected SpriteManager _spmgr; + protected Sprite _sprite; + protected Color _color; + protected Image _offimg; + protected boolean _fadeIn; + + protected TimeFunction _upfunc; + protected TimeFunction _downfunc; + protected int _alpha = -1; +}