Created a path for moving things along the arc of a circle or ellipse.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1691 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2002-09-17 04:00:37 +00:00
parent 9ee8dde710
commit 88e423bdfa
@@ -0,0 +1,172 @@
//
// $Id: ArcPath.java,v 1.1 2002/09/17 04:00:37 mdb 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.
*/
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)));
}
// 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); break;
case FINE: orient = DirectionUtil.getFineDirection(theta); 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();
}
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;
/** A temporary point used when computing our position along the
* path. */
protected Point _tpos = new Point();
}