Interpolation: Polish's Best Friend
If there’s one thing I’ve learned from my work on games, it’s that interpolation is the key to polish in games. What’s interpolation? Put simply it’s the act of changing a value to move from a starting value to an ending value over a period of time. What is interpolation useful for? Let me name a few examples:
- Let’s say you’re working on a UI. You have a highlight you want to apply to the buttons when you mouse over them. You could just make the instantly appear when you mouse over and instantly disappear when you mouse off, but you could also interpolate the alpha channel to give a slick fading in and out appearance.
- Let’s say you’re making a game where you drag an object around, but when you let go the object should travel to some nearest valid position (i.e. a chess piece in a chess game). You could just make the piece instantly appear in place, but you could also interpolate its position to smoothly move it into place.
- In a shorter form: interpolation can be used to modify positions, sizes, colors, rotations, and pretty much any other value over a period of time to help smooth out transitions or movements.
So how do we do interpolation in code? Well you’d need a bunch of values that contain information like the start and end values, the current value, and information for managing the length of the interpolation. At a bare minimum you’d need four or five pieces of data per interpolation. This can quickly add up to a big mess if you want to add a lot of interpolation to your game. Solution? Make a nice wrapper class to do it for you.
The first thing I always tried was to create a generic Interpolator class so that I could interpolate a float value when necessary, a Vector2 other times, and maybe a Vector3 if I need that Z component. But what I found is that since there’s no way to constrain the type to types that implement the + and – operators, there’s no way to actually do the interpolation. So I decided to just stick with a single float value knowing I could use multiple interpolators for Vector2s or Vector3s.
If you recall my previous post on timers, I decided to stick with that pattern of fire-and-forget capable APIs. There’s a bit more need to hang onto these interpolators which I will get to, but I wanted the API to support fire-and-forget since it is useful in some scenarios. What does this look like? Let’s take a look at what it takes to interpolate a color from white to black:
Color someColor = Color.White; Interpolator.CreateWithTime( 1f, // start value 0f, // end value 1f, // length of interpolation i => someColor = new Color(i.Value, i.Value, i.Value); // step delegate null); // completion delegate
As you can see, it makes for very concise code to easily animate your values. It’s very similar to how I set up timers and it’s an API style that I find very useful when working on games. The more my framework can manage under the covers for me, the better.
So I whipped up my Interpolator class which you can see here. It uses my new Pool class to manage recycling the instances which can be found here. The code is well commented so you should be able to take a look through and see how it all basically works. The key is all in the Interpolator class’s Update method:
public static void Update(float dt)
{
for (int k = 0; k < interpolators.ValidCount; k++)
{
Interpolator i = interpolators[k];
// if the interpolator is already invalid, skip over it
if (!i.valid)
continue;
// increase the timer and value
i.timer += dt;
i.Value += i.Speed * dt;
// see if the interpolator is done
if (i.timer >= i.Length)
i.valid = false;
// if the interpolator is no longer valid make sure
// the value is the desired end value
if (!i.valid)
i.Value = i.End;
// then fire off the value changed action
if (i.valueChanged != null)
i.valueChanged(i);
// if the interpolator is done, fire off the completed action
if (!i.valid && i.completedOrStopped != null)
i.completedOrStopped(i);
}
// clean up the pool
interpolators.CleanUp();
}
We simply go through each of our interpolators, update their time and value, and then proceed to check if they are still valid. We then call our step delegate to let the game handle the value changing. Lastly if the interpolator is done we call the completion delegate.
From there we can easily use this class to do all number of things. I’ve uploaded a sample solution here that contains a couple examples of how one could use the Interpolator class I’ve provided here. There are countless other applications and it can become even more interesting if you expand upon this to include non-linear interpolations such as quadratic or cubic interpolation.
Possibly Related Posts
(Automatically Generated)Advancing Timing and Interpolation
Advancing Timing and Interpolation
Using interpolators and timers
More Timer/Interpolator Tweaks
Borrowing From The iPhone SDK

Useful idea!
And a funny title
I can’t tell, did you know that the word interpolate is derived from the Latin interpolare which shares roots with polire which means “to polish”? The word extrapolate seems to have no such derivation, it appears to have been created from interpolate by, well, extrapolation.
Hmm, I really want to get Data Storage working on my game and I tried this out. I copied and pasted the code exactly and I got 67 errors. They are mostly — does not exist errors so I am not sure if I put stuff in the right place. For ezample, in the StorageDeviceSelectorCallback method, storageDevice and DeviceSelected can not be found in the entire method. I put this method in the Game1.cs File. not sure if thats where it’s supposed to go.
OMG! I posted that comment on the wrong article, let me fix that.
Thanks for that, it was really helpful. I’ve now implemented it in my game in the form of a Vector3Interpolation class. I’m hoping to make it so that you can feed it a delegate that changes the value of i.Value based on i.Start, i.End and i.timer so it can do more fancy stuff such as easing. That would hopefully mean I could make a generic class to handle different types, and then write a manager class that makes it all a bit easier to use. Lots of fun things to think about anyway.