What you're looking for is a chase camera, but you might have to do some tweaks to go from the usual 3D chase camera to the 2D chase camera.
I've got a small snippet here for you that I used a long time ago. It's in C# for XNA, but I think you will get the general idea.
It's a bit long, sorry for that.
public class ChaseCamera
{
#region Chased object properties (set externally each frame, or via Update)
/// <summary>
/// Position of object being chased.
/// </summary>
public Vector3 ChasePosition
{
get { return chasePosition; }
set { chasePosition = value; }
}
private Vector3 chasePosition;
/// <summary>
/// Direction the chased object is facing.
/// </summary>
public Vector3 ChaseDirection
{
get { return chaseDirection; }
set { chaseDirection = value; }
}
private Vector3 chaseDirection;
/// <summary>
/// Chased object's Up vector.
/// </summary>
public Vector3 Up
{
get { return up; }
set { up = value; }
}
private Vector3 up = Vector3.Up;
#endregion
#region Desired camera positioning (set when creating camera or changing view)
/// <summary>
/// Desired camera position in the chased object's coordinate system.
/// </summary>
public Vector3 DesiredPositionOffset
{
get { return desiredPositionOffset; }
set { desiredPositionOffset = value; }
}
private Vector3 desiredPositionOffset = new Vector3(0, 6.0f, 15.0f);
/// <summary>
/// Desired camera position in world space.
/// </summary>
public Vector3 DesiredPosition
{
get
{
// Ensure correct value even if update has not been called this frame
UpdateWorldPositions();
return desiredPosition;
}
}
private Vector3 desiredPosition;
/// <summary>
/// Look at point in the chased object's coordinate system.
/// </summary>
public Vector3 LookAtOffset
{
get { return lookAtOffset; }
set { lookAtOffset = value; }
}
private Vector3 lookAtOffset = new Vector3(0, 2.8f, 0);
/// <summary>
/// Look at point in world space.
/// </summary>
public Vector3 LookAt
{
get
{
// Ensure correct value even if update has not been called this frame
UpdateWorldPositions();
return lookAt;
}
}
private Vector3 lookAt;
#endregion
#region Camera physics (typically set when creating camera)
/// <summary>
/// Physics coefficient which controls the influence of the camera's position
/// over the spring force. The stiffer the spring, the closer it will stay to
/// the chased object.
/// </summary>
public float Stiffness
{
get { return stiffness; }
set { stiffness = value; }
}
private float stiffness;
/// <summary>
/// Physics coefficient which approximates internal friction of the spring.
/// Sufficient damping will prevent the spring from oscillating infinitely.
/// </summary>
public float Damping
{
get { return damping; }
set { damping = value; }
}
private float damping;
/// <summary>
/// Mass of the camera body. Heaver objects require stiffer springs with less
/// damping to move at the same rate as lighter objects.
/// </summary>
public float Mass
{
get { return mass; }
set { mass = value; }
}
private float mass;
#endregion
#region Current camera properties (updated by camera physics)
/// <summary>
/// Position of camera in world space.
/// </summary>
public Vector3 Position
{
get { return position; }
}
private Vector3 position;
/// <summary>
/// Velocity of camera.
/// </summary>
public Vector3 Velocity
{
get { return velocity; }
}
private Vector3 velocity;
#endregion
public ChaseCamera(float aspectRatio) : this(aspectRatio, 7500, 750, 50){}
public ChaseCamera(float aspectRatio, float stiffness, float damping, float mass)
{
this.aspectRatio = aspectRatio;
this.stiffness = stiffness;
this.damping = damping;
this.mass = mass;
}
#region Helper Methods
/// <summary>
/// Rebuilds object space values in world space. Invoke before publicly
/// returning or privately accessing world space values.
/// </summary>
private void UpdateWorldPositions()
{
// Construct a matrix to transform from object space to worldspace
Matrix transform = Matrix.Identity;
transform.Forward = ChaseDirection;
transform.Up = Up;
transform.Right = Vector3.Cross(Up, ChaseDirection);
// Calculate desired camera properties in world space
desiredPosition = ChasePosition +
Vector3.TransformNormal(DesiredPositionOffset, transform);
lookAt = ChasePosition +
Vector3.TransformNormal(LookAtOffset, transform);
}
/// <summary>
/// Forces camera to be at desired position and to stop moving. The is useful
/// when the chased object is first created or after it has been teleported.
/// Failing to call this after a large change to the chased object's position
/// will result in the camera quickly flying across the world.
/// </summary>
public void Reset()
{
UpdateWorldPositions();
// Stop motion
velocity = Vector3.Zero;
// Force desired position
position = desiredPosition;
}
#endregion
/// <summary>
/// Animates the camera from its current position towards the desired offset
/// behind the chased object. The camera's animation is controlled by a simple
/// physical spring attached to the camera and anchored to the desired position.
/// </summary>
public void Update(GameTime gameTime, Vector3 chasePosition, Vector3 chaseDirection, Vector3 chaseUp)
{
this.chasePosition = chasePosition;
this.chaseDirection = chaseDirection;
this.Up = up;
UpdateWorldPositions();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
// Calculate spring force
Vector3 stretch = position - desiredPosition;
Vector3 force = -stiffness * stretch - damping * velocity;
// Apply acceleration
Vector3 acceleration = force / mass;
velocity += acceleration * elapsed;
// Apply velocity
position += velocity * elapsed;
}
}
Edit: oh btw, I didn't come up with this myself, I think the above code was a modified version of the chase camera on creators.xna.com, but I'm not 100% sure anymore.