Monday, September 29, 2008

Things have been moving along in the as-yet-unnamed 2d project. Whilst making the particle system I came up with a small template class that I think is really rather useful. I needed a way to blend between a list of values of arbitrary type. The only type specific functionality required was a linear interpolation (Lerp) function... so a delegate was required. The beauty of it is that the Lerp method signature is pretty standard across the XNA framework, so I stuck with that. Here's the code (damn I really need a better way to post code):

// Generic class to store a list of times & values and
// interpolate between them.
public class FunctionLinear<T>
{
// The method signature for interpolating between two values of T
public delegate T Lerp<T>(T a, T b, float amt);

// Lerp function provided by the user
Lerp<T> Lerper;

// The sorted list of items
SortedList<float, T> Items = new SortedList<float, T>();

public FunctionLinear(Lerp<T> lerpMethod)
{
Lerper = lerpMethod;
}

public void AddItem(float time, T item)
{
Items.Add(time, item);
}

public T GetValue(float time)
{
if (Items.Count == 0)
return default(T);

// Determine the Items before and after the given time
int i = 0;
while (i <> Items.Keys[i + 1])
i++;

if (i >= Items.Count - 1)
return Items.Values[i - 1];

// Get proportion between values
float amt = (time - Items.Keys[i]) / (Items.Keys[i + 1] - Items.Keys[i]);

// Call the interpolator
return Lerper(Items.Values[i], Items.Values[i + 1], amt);
}
}

Thats it. As an example, here's how you would use it to create a function that describe a square in 2 seconds:

FunctionLinear f = new FunctionLinear(Vector2.Lerp);
f.AddItem(0.0f, Vector2.Zero);
f.AddItem(0.5f, Vector2.UnitX);
f.AddItem(1.0f, Vector2.One);
f.AddItem(1.5f, Vector2.UnitY);
f.AddItem(2.0f, Vector2.Zero);

1 comment:

Tim said...

updates please :P