6552b5bd8b
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2020 542714f4-19e9-0310-aa3c-eee0fc999fb1
200 lines
6.8 KiB
Java
200 lines
6.8 KiB
Java
//
|
|
// $Id: ArcPath.java,v 1.3 2002/12/04 02:45:09 shaper Exp $
|
|
|
|
package com.threerings.media.util;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Point;
|
|
|
|
import com.samskivert.util.StringUtil;
|
|
|
|
import com.threerings.media.Log;
|
|
import com.threerings.util.DirectionUtil;
|
|
|
|
/**
|
|
* The line path is used to cause a pathable to go from point A to point B
|
|
* along the arc of an ellipse in a certain number of milliseconds.
|
|
*/
|
|
public class ArcPath extends TimedPath
|
|
{
|
|
/** An orientation constant indicating that the normal (eight)
|
|
* directions should be used to orient the pathable being made to
|
|
* follow this path. */
|
|
public static final int NORMAL = 0;
|
|
|
|
/** An orientation constant indicating that the fine (sixteen)
|
|
* directions should be used to orient the pathable being made to
|
|
* follow this path. */
|
|
public static final int FINE = 1;
|
|
|
|
/**
|
|
* Creates an arc path that will animate a pathable from the specified
|
|
* starting position along an ellipse defined by the supplied
|
|
* parameters. The pathable will travel the specified number of
|
|
* radians along the arc of that ellipse. A positive number of radians
|
|
* indicates counter-clockwise travel along the circle, a negative
|
|
* number, clockwise rotation.
|
|
*
|
|
* @param start the starting point for the pathable.
|
|
* @param xradius the length of the x radius.
|
|
* @param yradius the length of the y radius.
|
|
* @param sangle the starting angle.
|
|
* @param delta the angle through which the pathable should be moved.
|
|
* @param duration the number of milliseconds during which to effect
|
|
* the animation.
|
|
* @param orient an orientation code indicating how the pathable
|
|
* should be oriented when following the path, either {@link #NORMAL},
|
|
* or {@link #FINE}.
|
|
*/
|
|
public ArcPath (Point start, double xradius, double yradius,
|
|
double sangle, double delta, long duration,
|
|
int orient)
|
|
{
|
|
super(duration);
|
|
_xradius = xradius;
|
|
_yradius = yradius;
|
|
_sangle = sangle;
|
|
_delta = delta;
|
|
_orient = orient;
|
|
|
|
// compute the center of the ellipse
|
|
_center = new Point(
|
|
(int)(start.x - Math.round(Math.cos(sangle) * xradius)),
|
|
(int)(start.y - Math.round(Math.sin(sangle) * yradius)));
|
|
}
|
|
|
|
/**
|
|
* Sets the offset that is applied to the pathable whenever it is
|
|
* oriented. This offset is in clockwise units whose granularity is
|
|
* specified by the {@link #NORMAL} or {@link #FINE} setting supplied
|
|
* to the path at construct time. The intent here is to allow arc
|
|
* paths to be applied that don't orient the pathable in the direction
|
|
* they are traveling but instead in some fixed offset from that
|
|
* direction.
|
|
*/
|
|
public void setOrientOffset (int offset)
|
|
{
|
|
_orientOffset = offset;
|
|
}
|
|
|
|
// documentation inherited
|
|
public boolean tick (Pathable pable, long timestamp)
|
|
{
|
|
double angle;
|
|
boolean modified = false;
|
|
|
|
// if we've blown past our arrival time...
|
|
if (timestamp >= _startStamp + _duration) {
|
|
// ...force the angle to the destination angle
|
|
angle = _sangle + _delta;
|
|
|
|
} else {
|
|
// otherwise, compute the angle at which we should place the
|
|
// pathable based on the elapsed time
|
|
long elapsed = timestamp - _startStamp;
|
|
angle = _sangle + _delta * elapsed / _duration;
|
|
}
|
|
|
|
// determine where we should be along the path
|
|
computePosition(_center, _xradius, _yradius, angle, _tpos);
|
|
|
|
// compute the pathable's new orientation
|
|
double theta = angle + ((_delta > 0) ? Math.PI/2 : -Math.PI/2);
|
|
int orient;
|
|
switch (_orient) {
|
|
default:
|
|
case NORMAL:
|
|
orient = DirectionUtil.getDirection(theta);
|
|
// adjust it appropriately
|
|
orient = DirectionUtil.rotateCW(orient, 2*_orientOffset);
|
|
break;
|
|
|
|
case FINE:
|
|
orient = DirectionUtil.getFineDirection(theta);
|
|
// adjust it appropriately
|
|
orient = DirectionUtil.rotateCW(orient, _orientOffset);
|
|
break;
|
|
}
|
|
|
|
// update the pathable's location if it moved
|
|
if (pable.getX() != _tpos.x || pable.getY() != _tpos.y) {
|
|
pable.setLocation(_tpos.x, _tpos.y);
|
|
modified = true;
|
|
}
|
|
|
|
// update the pathable's orientation if it changed
|
|
if (pable.getOrientation() != orient) {
|
|
pable.setOrientation(orient);
|
|
modified = true;
|
|
}
|
|
|
|
// if we completed our path, let the sprite know
|
|
if (angle == _sangle + _delta) {
|
|
pable.pathCompleted(timestamp);
|
|
}
|
|
|
|
return modified;
|
|
}
|
|
|
|
// documentation inherited
|
|
public void paint (Graphics2D gfx)
|
|
{
|
|
int x = (int)(_center.x - _xradius), y = (int)(_center.y - _yradius);
|
|
int width = (int)(2*_xradius), height = (int)(2*_yradius);
|
|
int sangle = (int)(Math.round(180 * _sangle / Math.PI)),
|
|
delta = (int)(Math.round(180 * _delta / Math.PI));
|
|
|
|
gfx.setColor(Color.blue);
|
|
gfx.drawRect(x, y, width-1, height-1);
|
|
|
|
gfx.setColor(Color.yellow);
|
|
gfx.drawArc(x, y, width-1, height-1, 0, 360);
|
|
|
|
gfx.setColor(Color.red);
|
|
gfx.drawArc(x, y, width-1, height-1, 360-sangle, -delta);
|
|
}
|
|
|
|
// documentation inherited
|
|
protected void toString (StringBuffer buf)
|
|
{
|
|
super.toString(buf);
|
|
buf.append(", center=").append(StringUtil.toString(_center));
|
|
buf.append(", sangle=").append(_sangle);
|
|
buf.append(", delta=").append(_delta);
|
|
buf.append(", radii=").append(_xradius).append("/").append(_yradius);
|
|
}
|
|
|
|
/**
|
|
* Computes the position of an entity along the path defined by the
|
|
* supplied parameters assuming that it must finish the path in the
|
|
* specified duration (in millis) and has been traveling the path for
|
|
* the specified number of elapsed milliseconds.
|
|
*/
|
|
public static void computePosition (
|
|
Point center, double xradius, double yradius, double angle, Point pos)
|
|
{
|
|
pos.x = (int)Math.round(center.x + xradius * Math.cos(angle));
|
|
pos.y = (int)Math.round(center.y + yradius * Math.sin(angle));
|
|
}
|
|
|
|
/** The center of our ellipse. */
|
|
protected Point _center;
|
|
|
|
/** Our ellipse radii. */
|
|
protected double _xradius, _yradius;
|
|
|
|
/** Our starting and delta angles. */
|
|
protected double _sangle, _delta;
|
|
|
|
/** The method to be used to orient the pathable. */
|
|
protected int _orient;
|
|
|
|
/** An orientation offset used when orienting our pathable. */
|
|
protected int _orientOffset = 0;
|
|
|
|
/** A temporary point used when computing our position along the
|
|
* path. */
|
|
protected Point _tpos = new Point();
|
|
}
|