December 15, 2017
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