// ------------------------------------------------------ // Using Directives // ------------------------------------------------------ using System.Collections.Generic; using System.Windows.Forms; using System.Drawing; using System; // ------------------------------------------------------ // Ball // ------------------------------------------------------ public class Ball { // ------------------------------------------------------ // Ball - Create a Ball object using 'size' and 'fill'. // The drawing area's 'width' and 'height' are also used // ------------------------------------------------------ public Ball(int size, Brush fill, int width, int height) { // 'mHeight' and 'mWidth' are used in 'GetX' and 'GetY' // so ensure those variables are initialized right away mSize = size; mFill = fill; mWidth = width; mHeight = height; mBallX = GetX(); mBallY = GetY(); mBallXSpeed = GetSpeed(); mBallYSpeed = GetSpeed(); } // ------------------------------------------------------ // Update - Update the ball's x and y location, also // handle colliding with a wall // ------------------------------------------------------ public void Update() { mBallX += mBallXSpeed; if (mBallX < 0 || mBallX + mSize > mWidth) mBallXSpeed = -mBallXSpeed; mBallY += mBallYSpeed; if (mBallY < 0 || mBallY + mSize > mHeight) mBallYSpeed = -mBallYSpeed; } // ------------------------------------------------------ // Render - Draw the ball at its current location // ------------------------------------------------------ public void Render(Graphics g) { g.FillEllipse(mFill, mBallX, mBallY, mSize, mSize); g.DrawEllipse(Pens.Black, mBallX, mBallY, mSize, mSize); } // ------------------------------------------------------ // Get a random 'speed', 'x' or 'y' location // ------------------------------------------------------ private int GetSpeed() { return(mRandom.Next(MIN_SPEED, MAX_SPEED)); } private int GetX() { return(mRandom.Next(0, mWidth - mSize)); } private int GetY() { return(mRandom.Next(0, mHeight - mSize)); } // ------------------------------------------------------ // The min/max speed of the ball, MIN_SPEED should be >= 1 // otherwise the ball will not move // ------------------------------------------------------ private const int MIN_SPEED = 1; private const int MAX_SPEED = 5; private int mSize; private Brush mFill; private int mBallX; private int mBallY; private int mBallXSpeed; private int mBallYSpeed; private int mWidth; private int mHeight; private static Random mRandom = new Random(); } // ------------------------------------------------------ // BallInfo - A Ball's 'size' and 'fill' values // ------------------------------------------------------ public class BallInfo { public BallInfo(int size, Brush fill) { Size = size; Fill = fill; } public int Size { get; private set; } public Brush Fill { get; private set; } } // ------------------------------------------------------ // BallsForm // ------------------------------------------------------ public class BallsForm : Form { public BallsForm() { // ------------------------------------------------------ // Size our form // ------------------------------------------------------ Size = new Size(FORM_WIDTH, FORM_HEIGHT); // ------------------------------------------------------ // Create our balls // ------------------------------------------------------ var info = new BallInfo[] { new BallInfo(40, Brushes.Blue), new BallInfo(20, Brushes.Red), new BallInfo(30, Brushes.Green), new BallInfo(35, Brushes.Cyan), new BallInfo(15, Brushes.Magenta), new BallInfo(25, Brushes.Yellow) }; foreach(var entry in info) { mList.Add( new Ball( entry.Size, entry.Fill, ClientSize.Width, ClientSize.Height ) ); } // ------------------------------------------------------ // Set up our timer and our form // ------------------------------------------------------ mMoveBallsTimer.Enabled = true; mMoveBallsTimer.Interval = 10; mMoveBallsTimer.Tick += new System.EventHandler(MoveBallsTick); // ------------------------------------------------------ // Use double buffering to reduce flicker // ------------------------------------------------------ FormBorderStyle = FormBorderStyle.Fixed3D; Text = "Bouncing Balls"; Paint += new PaintEventHandler(RenderBalls); SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true ); UpdateStyles(); } // ------------------------------------------------------ // MoveBallsTick - Update the location of each ball // ------------------------------------------------------ private void MoveBallsTick(object sender, EventArgs e) { mList.ForEach(delegate(Ball b) { b.Update(); }); Refresh(); } // ------------------------------------------------------ // RenderBalls - Draw each ball at its current location // ------------------------------------------------------ private void RenderBalls(object sender, PaintEventArgs e) { e.Graphics.Clear(BackColor); mList.ForEach(delegate(Ball b) { b.Render(e.Graphics); }); } // ------------------------------------------------------ // Settings // ------------------------------------------------------ private const int FORM_WIDTH = 500; private const int FORM_HEIGHT = 500; // ------------------------------------------------------ // Member variables // ------------------------------------------------------ private Timer mMoveBallsTimer = new System.Windows.Forms.Timer(); private List mList = new List(); // ------------------------------------------------------ // Main // ------------------------------------------------------ [STAThread] static void Main() { Application.Run(new BallsForm()); } }