RFC: Generic Control Dimension

[java]

/****************************************************************************

  • <h1>• Generic Control Dimension • </h1>
  • This class implements delayed massive movement in a single dimension (may
  • be rotation or direction).
  • <h1><b>Usage:</b></h1>
  • doAccelerate() and doBreak() functions modify current movement.<br/>
  • setCurrent() sets value directly.<br/>
  • update(timePerFrame) updates the values according to the current tpf.<br/>
  • getCurrent() returns the actual value for your calculation.
  • @author .rhavin Grobert
  • @version 0.2.2 */

    public class CtrlDimension

    {

    //

// public members
/** The dimensions acceleration capability */
public float flAccel = 0.4f;
/** The dimensions breaking capability */
public float flBreak = 0.4f;
/** The dimensions standard decay */
public float flDecay = 0.1f;
/** The dimensions positive maximum modifier */
public float flPositive = 1.0f;
/** The dimensions negative minimum modifier */
public float flNegative = -1.0f;

//
// private members
/** The currently set dimensional modifier */
private float flCurrent = 0f;
/** The yet-to-reach dimensional modifier */
private float flGoal = 0f;

//
// constructors
/** default constructor */
public CtrlDimension() {}
/** parameter constructor */
public CtrlDimension(float acceleration, float breaking,
float positive, float negative, float decay)
{
flAccel = acceleration;
flBreak = breaking;
flPositive = positive;
flNegative = negative;
flDecay = decay;
}

//
// methods

/** get current movement modifier */
public float getCurrent() {return flCurrent;}
/** get current to-reach modifier */
public float getGoal() {return flGoal;}

/*****************************************************************
* Let control accelerate in given direction.
* @param positive Use true for an increase in positive direction,
* false for a decrease in negative direction. */
public void doAccelerate(boolean positive)
{
doAccelerate(positive, 1f);
}

/*****************************************************************
* Let control accelerate in given direction.
* @param positive Use true for an increase in positive direction,
* false for a decrease in negative direction.
* @param factor how much acceleration should we use */
public void doAccelerate(boolean positive, float factor)
{
if (positive)
{
flGoal += flAccel * factor;
if (flGoal > flPositive)
flGoal = flPositive;
return;
}
flGoal -= flAccel * factor;
if (flGoal < flNegative)
flGoal = flNegative;
}

/*****************************************************************
* Let control break (reaching movement zero) in given direction.
* @param positive Use true for a decrease in positive direction,
* false for an increase in negative direction. */
public void doBreak(boolean positive)
{
doBreak(positive, 1f);
}

/*****************************************************************
* Let control break (reaching movement zero) in given direction.
* @param positive Use true for a decrease in positive direction,
* false for an increase in negative direction.
* @param factor how much breaking we use */
public void doBreak(boolean positive, float factor)
{
if (positive)
{
flGoal -= flAccel * factor;
if (flGoal < 0f)
flGoal = 0f;
return;
}
flGoal += flAccel * factor;
if (flGoal > 0f)
flGoal = 0f;
}

/*****************************************************************
* Directly set current movement to given value and check bounds.
* @param current The new value to set. */
public void setCurrent(float current)
{
flCurrent = current;
if (flCurrent > flPositive)
flCurrent = flPositive;
if (flCurrent < flNegative)
flCurrent = flNegative;
setGoal(current);
}

/*****************************************************************
* Directly set to-reach movement to given value and check bounds.
* @param goal The new value to set. */
public void setGoal(float goal)
{
flGoal = goal;
if (flGoal > flPositive)
flGoal = flPositive;
if (flGoal < flNegative)
flGoal = flNegative;
}

/*****************************************************************
* Update values according to given time-frame.
* @param timeFrame Time-frame factor for modifiers */
public void update(float tpf)
{
// fast skip: do nothing if nothing is to do
if (flGoal == 0f && flCurrent == 0f)
return;
if (flGoal > flCurrent)
{
// we have to increase value
flCurrent += flAccel * tpf;
// if we're below zero, we may add breaking
if (flCurrent < 0f)
{
flCurrent += flBreak * tpf;
// can't break over zero
if (flCurrent > 0f)
flCurrent = 0f;
}
// can't cross to-reach value
if (flCurrent > flGoal)
flCurrent = flGoal;
}
else
{
// we have to decrease value
flCurrent -= flAccel * tpf;
// if we're above zero, we may add breaking
if (flCurrent > 0f)
{
flCurrent -= flBreak * tpf;
// can't break over zero
if (flCurrent < 0f)
flCurrent = 0f;
}
// can't cross to-reach value
if (flCurrent < flGoal)
flCurrent = flGoal;
}

// apply dimensional decay (if any)
if (flDecay == 0f)
return;
if (flGoal > 0)
{
flGoal -= flDecay * tpf;
if (flGoal < 0)
flGoal = 0f;
}
else
{
flGoal += flDecay * tpf;
if (flGoal > 0)
flGoal = 0f;
}
}
}
[/java]