Rolling multiple balls as multiple threads

In this example, we roll multiple balls as multiple threads.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Media;
using System.Drawing.Drawing2D;
using System.Threading;
using System.Collections;

namespace howto_bouncing_ball
{
    // Each thread must have its own data
    // otherwise all threads will use
    // same x,y values
    public struct ThreadData
    {
        public int BallX, BallY;   // Position.
        public int BallVx, BallVy; // Displacement
    }
    public partial class Form1 : Form
    {
        // declare an array list to store threads
        ArrayList threadBalls = new ArrayList();

        public Form1()
        {
            InitializeComponent();
        }

        // The below width and height are shared by all threads
        private const int BallWidth = 50;
        private const int BallHeight = 50;
       

        // Initialize some random stuff.
        private void Form1_Load(object sender, EventArgs e)
        {
          
            // Use double buffering to reduce flicker.
            this.SetStyle(
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer,
                true);
            this.UpdateStyles();
        }

        
        private void btnAddBall_Click(object sender, EventArgs e)
        {
            // Set the data of each thread
        Random rnd = new Random(1);

            ThreadData td = new ThreadData
            {
                BallX = rnd.Next(pictureBox1.Left + 50, pictureBox1.Right + 50),
                BallY = rnd.Next(pictureBox1.Top + 50, pictureBox1.Bottom - 50),
                BallVx = 1,
                BallVy = 1
        };

            var t = new Thread(MoveBall);
            t.Start(td);
            threadBalls.Add(t);
            this.Refresh();

            
        }

        public void MoveBall(object o)
        {
            Graphics dc = this.CreateGraphics();
            Random r = new Random();

// create random color of each ball
   SolidBrush solidBrush = new SolidBrush(
   Color.FromArgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255)));
            
            // retrieve the data of this thread only
            ThreadData d = (ThreadData)o;
            
            while (true)
            {
                d.BallX += d.BallVx;
            if (d.BallX < 0)
            {
            d.BallVx = -d.BallVx;           
            }
            else if (d.BallX + BallWidth > pictureBox1.Width)
            {
             d.BallVx = -d.BallVx;              
            }

            d.BallY += d.BallVy;
            if (d.BallY < 0)
            {
             d.BallVy = -d.BallVy;              
            }
            else if (d.BallY + BallHeight > pictureBox1.Height)
            {
             d.BallVy = -d.BallVy;        
            }

                dc.SmoothingMode = SmoothingMode.HighQuality;

                dc.DrawEllipse(Pens.Black, d.BallX, d.BallY, BallWidth, BallHeight);
                dc.FillEllipse(solidBrush, d.BallX, d.BallY, BallWidth, BallHeight);
                this.Invalidate();
            }

           

        }

        protected override void OnPaint(PaintEventArgs e)
        {
            label2.Text = threadBalls.Count.ToString();
            
        }

        private void btnRemoveBall_Click(object sender, EventArgs e)
        {
            if(threadBalls.Count>0)
            { 
            Thread t = (Thread)threadBalls[threadBalls.Count-1];
            t.Abort();
            threadBalls.RemoveAt(threadBalls.Count - 1);
                this.Refresh();
            }

        }
    }
}

The complete example can be downloaded from this LINK

Tags:
One Comment

Add a Comment

Your email address will not be published. Required fields are marked *