Use a sprite class to animate a control's motion in C#

Keeping track of where an object is as it moves can be tricky, particularly if you have more than one object moving at the same time. This example uses the following ControlSprite class to keep track of a control while it moves in a straight line.

// Information about a move in progress.
public class ControlSprite
{
public System.Windows.Forms.Control MovingControl;
public int EndX, EndY;
public float CurrentX, CurrentY;

private float Dx, Dy;
private DateTime LastMoveTime;
private TimeSpan TotalElapsed, MoveUntil;
private Timer MoveTimer;

public delegate void DoneEventHandler(object sender);
public event DoneEventHandler Done;

// Prepare to move the control.
public ControlSprite(System.Windows.Forms.Control control)
{
MovingControl = control;
}

// Start moving.
public void Start(int end_x, int end_y, int pixels_per_second)
{
CurrentX = MovingControl.Location.X;
CurrentY = MovingControl.Location.Y;
EndX = end_x;
EndY = end_y;

// Calculate the total distance.
float dx = EndX - CurrentX;
float dy = EndY - CurrentY;
float dist = (float)Math.Sqrt(dx * dx + dy * dy);

// Calculate the X and Y amounts to move per second.
Dx = pixels_per_second * dx / dist;
Dy = pixels_per_second * dy / dist;

// See how long the total move will take.
int milliseconds = (int)(1000.0f * dist / pixels_per_second);
MoveUntil = new TimeSpan(0, 0, 0, 0, milliseconds);
TotalElapsed = new TimeSpan(0);

// Make the timer.
MoveTimer = new Timer();
MoveTimer.Interval = 10;
MoveTimer.Tick += MoveTimer_Tick;

// Start moving.
Start();
}

// Resume moving.
public void Start()
{
LastMoveTime = DateTime.Now;
MoveTimer.Enabled = true;
}

// Stop moving.
public void Stop()
{
MoveTimer.Enabled = false;
}

// Move the control.
private void MoveTimer_Tick(object sender, EventArgs e)
{
// See how long it's been since the last move.
DateTime now = DateTime.Now;
TimeSpan elapsed_since_last = now - LastMoveTime;
LastMoveTime = DateTime.Now;

// See if we should stop.
TotalElapsed += elapsed_since_last;
if (TotalElapsed >= MoveUntil)
{
// Stop.
MoveTimer.Enabled = false;
CurrentX = EndX;
CurrentY = EndY;
if (Done != null) Done(this);
}
else
{
// Continue.
CurrentX += (float)(Dx * elapsed_since_last.TotalSeconds);
CurrentY += (float)(Dy * elapsed_since_last.TotalSeconds);
}

// Move the control to its new location.
MovingControl.Location = new Point((int)CurrentX, (int)CurrentY);
}
}

The class starts with some relatively straightforward declarations. The only really interesting part here is the declaration of the Done even, which the class raises when its control has finished moving.

The class's constructor takes as a parameter the control that it will move.

The first overloaded version of the Start method gets things moving. It saves the control's current and end locations. It calculates the total distance the control must travel. It then uses that distance and the pixels_per_second parameter to determine how much it must increment the control's X and Y coordinate per second to achieve the desired movement in pixels per second. The Start method calculates the total amount of time the movement will take, creates a Timer to control the movement, and then calls the second overloaded version of Start.

The second version of Start saves the current time in the LastMoveTime variable and enables the Timer.

The Stop method simply disables the sprite's Timer.

When the Timer raises its Tick event, the sprite determines how long it's been since the last time it updated the control's position and adds the elapsed time to the total elapsed time so far. If the control has been moving for long enough to reach its destination, the code disables the Timer, moves the control to its final position, and raises the Done event. If the control has not been moving long enough to reach its destination, the code increments the control's X and Y coordinates.

The example program uses two sprites to animate a Button and a Label moving at the same time.

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.