Files
narya/src/java/com/threerings/media/animation/ExplodeAnimation.java
T
Walter Korman 04ab7fe8c1 Added support for expiring an explode animation after a set time delay.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@907 542714f4-19e9-0310-aa3c-eee0fc999fb1
2002-01-31 17:34:20 +00:00

267 lines
7.8 KiB
Java

//
// $Id: ExplodeAnimation.java,v 1.6 2002/01/31 17:34:20 shaper Exp $
package com.threerings.media.animation;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import com.threerings.media.Log;
import com.threerings.media.util.RandomUtil;
/**
* An animation that displays an object exploding into chunks. The
* animation ends when all chunks have exited the animation bounds.
*/
public class ExplodeAnimation extends Animation
{
/**
* A class that describes an explosion's attributes.
*/
public static class ExplodeInfo {
/** The bounds within which to animate. */
public Rectangle bounds;
/** The number of image chunks on each axis. */
public int xchunk, ychunk;
/** The maximum chunk velocity on each axis in pixels per
* millisecond. */
public float xvel, yvel;
/** The y-axis chunk acceleration in pixels per millisecond. */
public float yacc;
/** The chunk rotational velocity in rotations per millisecond. */
public float rvel;
/** The animation length in milliseconds, or -1 if the animation
* should continue until all pieces are outside the bounds. */
public long delay;
}
/**
* Constructs an explode animation with the chunks represented as
* filled rectangles of the specified color.
*
* @param color the color to render the chunks in.
* @param info the explode info object.
* @param x the x-position of the object.
* @param y the y-position of the object.
* @param width the width of the object.
* @param height the height of the object.
*/
public ExplodeAnimation (
Color color, ExplodeInfo info, int x, int y, int width, int height)
{
super(info.bounds);
_color = color;
init(info, x, y, width, height);
}
/**
* Constructs an explode animation with the chunks represented as
* portions of the actual image.
*
* @param image the image to animate.
* @param info the explode info object.
* @param x the x-position of the object.
* @param y the y-position of the object.
* @param width the width of the object.
* @param height the height of the object.
*/
public ExplodeAnimation (
Image image, ExplodeInfo info, int x, int y, int width, int height)
{
super(info.bounds);
_image = image;
init(info, x, y, width, height);
}
/**
* Initializes the animation with the attributes of the given explode
* info object.
*/
protected void init (ExplodeInfo info, int x, int y, int width, int height)
{
_info = info;
_ox = x;
_oy = y;
_owid = width;
_ohei = height;
_info.rvel = (float)((2.0f * Math.PI) * _info.rvel);
_chunkcount = (_info.xchunk * _info.ychunk);
_cpos = new int[_chunkcount];
_sxvel = new float[_chunkcount];
_syvel = new float[_chunkcount];
// determine chunk dimensions
_cwid = _owid / _info.xchunk;
_chei = _ohei / _info.ychunk;
_hcwid = _cwid / 2;
_hchei = _chei / 2;
// initialize all chunks
for (int ii = 0; ii < _chunkcount; ii++) {
// initialize chunk position
int xpos = ii % _info.xchunk;
int ypos = ii / _info.xchunk;
_cpos[ii] = ((_ox + (xpos * _cwid)) << 16 |
(_oy + (ypos * _chei)));
// initialize chunk velocity
_sxvel[ii] = RandomUtil.getFloat(_info.xvel) *
((xpos < (_info.xchunk / 2)) ? -1.0f : 1.0f);
_syvel[ii] = -(RandomUtil.getFloat(_info.yvel));
}
// initialize the chunk rotation angle
_angle = 0.0f;
}
/**
* Sets the animation starting time.
*/
public void setStartTime (long timestamp)
{
_start = timestamp;
}
// documentation inherited
public void tick (long timestamp)
{
// figure out the distance the chunks have travelled
long msecs = timestamp - _start;
// move all chunks and check whether any remain to be animated
int inside = 0;
for (int ii = 0; ii < _chunkcount; ii++) {
// retrieve the current chunk position
int x = _cpos[ii] >> 16;
int y = _cpos[ii] & 0xFFFF;
// determine the chunk travel distance
int xtrav = (int)(_sxvel[ii] * msecs);
int ytrav = (int)((_syvel[ii] * msecs) +
(0.5f * _info.yacc * (msecs * msecs)));
// determine the chunk movement direction
int xpos = ii % _info.xchunk;
int ypos = ii / _info.xchunk;
// update the chunk position
x = _ox + (xpos * _cwid) + xtrav;
y = _oy + (ypos * _chei) + ytrav;
_cpos[ii] = (x << 16 | y);
// note whether this chunk is still within our bounds
if (_bounds.contains(x, y)) {
inside++;
}
}
// increment the rotation angle
_angle += _info.rvel;
_finished = (inside == 0) ||
(_info.delay > -1 && timestamp >= (_start + _info.delay));
invalidate();
}
// documentation inherited
public void paint (Graphics2D gfx)
{
for (int ii = 0; ii < _chunkcount; ii++) {
// get the chunk location on-screen
int x = _cpos[ii] >> 16;
int y = _cpos[ii] & 0xFFFF;
// get the chunk position within the image
int xpos = ii % _info.xchunk;
int ypos = ii / _info.xchunk;
// calculate image chunk offset
int xoff = -(xpos * _cwid);
int yoff = -(ypos * _chei);
// draw the chunk
Shape oclip = gfx.getClip();
// translate the origin to center on the chunk
int tx = x + _hcwid, ty = y + _hchei;
gfx.translate(tx, ty);
// set up the desired rotation
gfx.rotate(_angle);
if (_image != null) {
// draw the image chunk
gfx.clipRect(-_hcwid, -_hchei, _cwid, _chei);
gfx.drawImage(_image, -_hcwid + xoff, -_hchei + yoff, null);
gfx.setClip(oclip);
} else {
// draw the color chunk
gfx.setColor(_color);
gfx.fillRect(-_hcwid, -_hchei, _cwid, _chei);
}
// restore the original transform
gfx.rotate(-_angle);
gfx.translate(-tx, -ty);
}
}
// documentation inherited
protected void toString (StringBuffer buf)
{
super.toString(buf);
buf.append(", sx=").append(_ox);
buf.append(", sy=").append(_oy);
}
/** The current chunk rotation. */
protected float _angle;
/** The starting x-axis velocity of each chunk. */
protected float[] _sxvel;
/** The starting y-axis velocity of each chunk. */
protected float[] _syvel;
/** The current position of each chunk. */
protected int[] _cpos;
/** The individual chunk dimensions in pixels. */
protected int _cwid, _chei;
/** The individual chunk dimensions in pixels, halved for handy use in
* repeated calculations. */
protected int _hcwid, _hchei;
/** The total number of image chunks. */
protected int _chunkcount;
/** The explode info. */
protected ExplodeInfo _info;
/** The exploding object position and dimensions. */
protected int _ox, _oy, _owid, _ohei;
/** The color to render the object chunks in if we're using a color. */
protected Color _color;
/** The image to animate if we're using an image. */
protected Image _image;
/** The starting animation time. */
protected long _start;
}