Title: Animate several bouncing balls in C#
Category: multimedia, animation, audio, graphics
Keywords: multimedia, animation, audio, graphics, sounds, SoundPlayer, resources, audio, C#, C# programming, example, example program, Windows Forms programming, boing, bouncing balls
This example modifies the earlier post Make a bouncing ball animation in C# to animate several bouncing balls. Much of the basic idea is the same so see that example first.
The big difference is that this version stores ball information in arrays instead of single variables. For example, instead of a single BallX variable to store one ball's position, this program uses a BallLocation array of Rectangle structures to store positions for many balls.
The following code shows how the program initializes its ball data.
// Some drawing parameters.
private Rectangle[] BallLocation;
private Point[] BallVelocity;
private Size FormSize;
// Initialize some random stuff.
private void Form1_Load(object sender, EventArgs e)
{
// Make random balls.
Random rand = new Random();
const int num_balls = 10;
BallLocation = new Rectangle[num_balls];
BallVelocity = new Point[num_balls];
for (int i = 0; i < num_balls; i++)
{
int width = rand.Next(10, 40);
BallLocation[i] = new Rectangle(
rand.Next(0, ClientSize.Width - 2 * width),
rand.Next(0, ClientSize.Height - 2 * width),
width, width);
int vx = rand.Next(2, 10);
int vy = rand.Next(2, 10);
if (rand.Next(0, 2) == 0) vx = -vx;
if (rand.Next(0, 2) == 0) vy = -vy;
BallVelocity[i] = new Point(vx, vy);
}
// Save the form's size.
FormSize = ClientSize;
// Use double buffering to reduce flicker.
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,
true);
this.UpdateStyles();
}
The following code moves the balls when the program's timer fires its Tick event.
// Move the balls and refresh.
private void tmrMoveBall_Tick(object sender, EventArgs e)
{
for (int ball_num = 0;
ball_num < BallLocation.Length;
ball_num++)
{
// Move the ball.
int new_x = BallLocation[ball_num].X +
BallVelocity[ball_num].X;
int new_y = BallLocation[ball_num].Y +
BallVelocity[ball_num].Y;
if (new_x < 0)
{
BallVelocity[ball_num].X = -BallVelocity[ball_num].X;
Boing();
}
else if (new_x + BallLocation[ball_num].Width >
FormSize.Width)
{
BallVelocity[ball_num].X = -BallVelocity[ball_num].X;
Boing();
}
if (new_y < 0)
{
BallVelocity[ball_num].Y = -BallVelocity[ball_num].Y;
Boing();
}
else if (new_y + BallLocation[ball_num].Height >
FormSize.Height)
{
BallVelocity[ball_num].Y = -BallVelocity[ball_num].Y;
Boing();
}
BallLocation[ball_num] = new Rectangle(
new_x, new_y,
BallLocation[ball_num].Width,
BallLocation[ball_num].Height);
}
Refresh();
}
In addition to updating each ball's position, this code also calls the Boing method to play a sound whenever a ball touches one of the form's edges. You may want to comment out those calls (or comment out the code in the Boing method) if you're going to run the program a lot. The sounds are amusing, but kind of noisy.
Finally the following code shows how the program redraws its surface after the balls move.
// Draw the ball at its current location.
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.Clear(BackColor);
for (int i = 0; i < BallLocation.Length; i++)
{
e.Graphics.FillEllipse(Brushes.Blue, BallLocation[i]);
e.Graphics.DrawEllipse(Pens.Black, BallLocation[i]);
}
}
Download the example to experiment with it and to see additional details.
|