• Advertisement
Sign in to follow this  

Simple ramp timer. Going from one value to another in a period of time.

This topic is 2775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've created a small class that ramps between one value and another in the amount of time specified:


class RampTimer
{
float currentValue;
bool isFinished = true;
float period;
int start;
int end;
float stepSize;

public RampTimer(int start, int end, float period)
{
this.end = end;
this.period = period;
this.start = start;

currentValue = start;
isFinished = true;
stepSize = (end - start) / period;
}

public void Start()
{
currentValue = start;
isFinished = false;
}

public void Update(GameTime gameTime)
{
if (!isFinished)
{
currentValue += stepSize * gameTime.ElapsedGameTime.Milliseconds;
isFinished = Math.Abs(currentValue) >= Math.Abs(end);
}
}

public float CurrentValue
{
get { return currentValue; }
}




The timer starts by invoking the Start() method but it appears to have a small problem. When going from -ve to +ve the timer seems to hang on the value of 0 longer than expected.

Can anyone explain why this is? Does my code look correct?

Also my terminology of ramp timer is probably incorrect, if anyone knows what category this falls under then please let me know so I can name the class correctly and research that area.

Thanks.

Share this post


Link to post
Share on other sites
Advertisement
It probably isn't in that code. Rather, you're probably taking CurrentValue and truncating it to an int, meaning that (-1,1) will evaluate to 0.

And I've never heard "ramp timer" before; what you're doing there is known as linear interpolation. I'd be inclined to split that into the interpolation part and the cumulative time part:


class Lerp implements ICurve {
public Lerp(float start, float end) { ... }
public float Eval(float t) { return start + (end-start)*t; }
};

class TimedCurve {
private float timeSinceStart = 0;
public TimedCurve(ICurve base, float period) { ... }
public void Update(float dt) { timeSinceStart += dt; }
public float CurrentValue {
get { return base.Eval(timeSinceStart/period); }
}
}


Share this post


Link to post
Share on other sites
Thanks Sneftel that makes sense. I've adjusted the class so it looks like the following:


// Linear Interpolation
class Lerp
{
float end;
float start;

public Lerp(float start, float end)
{
this.end = end;
this.start = start;
}

public float Evaluate(float t)
{
return start + (end - start) * t;
}
}

class LerpTimer
{
private bool isFinished = true;
private float period;
private float timeSinceStart = 0;
private Lerp lerp;

public LerpTimer(float start, float end, float period)
{
lerp = new Lerp(start, end);
this.period = period;
}

public void Start()
{
timeSinceStart = 0;
isFinished = false;
}

public void Update(GameTime gameTime)
{
if (!isFinished)
{
timeSinceStart += gameTime.ElapsedGameTime.Milliseconds;
isFinished = timeSinceStart >= period;
}
}

public float CurrentValue
{
get { return lerp.Evaluate(timeSinceStart / period); }
}
}



I'm going to look up some alternative interpolation techniques so I can create different curves.

Share this post


Link to post
Share on other sites
I also wouldn't bother with the "isFinished" stuff. Instead, just Evaluate() with min(t,1) instead of t. That will have the side benefit of making sure the value is actually end after the time period is over, rather something just below it.

Share this post


Link to post
Share on other sites
Good call, thank you.


// Linear Interpolation
class Lerp
{
float end;
float start;

public Lerp(float start, float end)
{
this.end = end;
this.start = start;
}

public float Evaluate(float t)
{
return start + (end - start) * Math.Min(t, 1);
}
}

class LerpTimer
{
private float period;
private float timeSinceStart = 0;
private Lerp lerp;

public LerpTimer(float start, float end, float period)
{
lerp = new Lerp(start, end);
this.period = period;
}

public void Start()
{
timeSinceStart = 0;
}

public void Update(GameTime gameTime)
{
timeSinceStart += gameTime.ElapsedGameTime.Milliseconds;
}

public float CurrentValue
{
get { return lerp.Evaluate(timeSinceStart / period); }
}
}



This does mean that the timer starts right away when invoked but I guess I can just call Start() to reset the timer. Perhaps I should rename Start() to Reset() as it makes more sense?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement