
com.threerings.media.util.BobblePath Maven / Gradle / Ivy
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
// https://github.com/threerings/nenya
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.media.util;
import java.awt.Color;
import java.awt.Graphics2D;
import com.samskivert.util.RandomUtil;
/**
* Bobble a Pathable.
*/
public class BobblePath implements Path
{
/**
* Construct a bobble path that updates as often as possible.
*
* @param dx the variance in the x direction.
* @param dy the variance in the y direction.
* @param duration the duration to bobble, or -1 to bobble until stop() is called.
*/
public BobblePath (int dx, int dy, long duration)
{
this(dx, dy, duration, 1L);
}
/**
* Construct a bobble path.
*
* @param dx the variance in the x direction.
* @param dy the variance in the y direction.
* @param duration the duration to bobble, or -1 to bobble until stop() is called.
* @param updateFreq how often to update the Pathable's location.
*/
public BobblePath (int dx, int dy, long duration, long updateFreq)
{
_updateFreq = updateFreq;
_duration = duration;
setVariance(dx, dy);
}
/**
* Set the variance of bobblin' in each direction.
*/
public void setVariance (int dx, int dy)
{
if ((dx < 0) || (dy < 0) || ((dx == 0) && (dy == 0))) {
throw new IllegalArgumentException(
"Variance values must be positive, and at least one must be non-zero.");
} else {
_dx = dx;
_dy = dy;
}
}
/**
* Set a new update frequency.
*/
public void setUpdateFrequency (long freq)
{
_updateFreq = freq;
}
/**
* Have the Pathable stop bobbling asap.
*/
public void stop ()
{
// it will stop on the next tick..
_stopTime = 0L;
}
// documentation inherited from interface Path
public void init (Pathable pable, long tickstamp)
{
_sx = pable.getX();
_sy = pable.getY();
// change the duration to a real stop time
if (_duration == -1L) {
_stopTime = Long.MAX_VALUE;
} else {
_stopTime = tickstamp + _duration;
}
_nextMove = tickstamp;
}
// documentation inherited from interface Path
public boolean tick (Pathable pable, long tickStamp)
{
// see if we need to stop
if (_stopTime <= tickStamp) {
boolean updated = updatePositionTo(pable, _sx, _sy);
pable.pathCompleted(tickStamp);
return updated;
}
// see if it's time to move..
if (_nextMove > tickStamp) {
return false;
}
// when bobbling, it's bad form to bobble into the same position
int newx, newy;
do {
newx = _sx + RandomUtil.getInt(_dx * 2 + 1) - _dx;
newy = _sy + RandomUtil.getInt(_dy * 2 + 1) - _dy;
} while (! updatePositionTo(pable, newx, newy));
// and update the next time to move
_nextMove = tickStamp + _updateFreq;
return true;
}
// documentation inherited from interface Path
public void fastForward (long timeDelta)
{
_stopTime += timeDelta;
_nextMove += timeDelta;
}
// documentation inherited from interface Path
public void paint (Graphics2D gfx)
{
// for debugging, show the bobble bounds
gfx.setColor(Color.RED);
gfx.drawRect(_sx - _dx, _sy - _dy, _dx * 2, _dy * 2);
}
// documentation inherited from interface
public void wasRemoved (Pathable pable)
{
// reset the pathable to its initial location
pable.setLocation(_sx, _sy);
}
/**
* Update the position of the pathable or return false if it's already there.
*/
protected boolean updatePositionTo (Pathable pable, int x, int y)
{
if ((pable.getX() == x) && (pable.getY() == y)) {
return false;
} else {
pable.setLocation(x, y);
return true;
}
}
/** The initial position of the pathable. */
protected int _sx, _sy;
/** The variance we will bobble around that initial position. */
protected int _dx, _dy;
/** How long we'll bobble. */
protected long _duration;
/** How often we update the locations. */
protected long _updateFreq;
/** The time at which we'll stop pathin'. */
protected long _stopTime;
/** The time at which we'll next update the position of the pathable. */
protected long _nextMove = 0L;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy