04ab7fe8c1
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@907 542714f4-19e9-0310-aa3c-eee0fc999fb1
267 lines
7.8 KiB
Java
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;
|
|
}
|