------------------------------BallisticSimulator--------------------- using System; using System.Drawing; namespace CannonBallGame { /// /// A simple Ballistics simulator class /// public class BallisticSimulator { public float InitialAngle = 0.0f; public float InitialVelocity = 100.0f; public float ElapsedTime = 0.0f; public float Timestep = 1.0f; public BallisticSimulator() { } /// /// Gets the next position of the simulator by incrementing the ElapsedTime /// /// The next position as a PointF public PointF GetNextPosition() { ElapsedTime += Timestep; // Convert InitialAngle to radian, radian = degrees * (PI/180) float fIA = InitialAngle * (float)(Math.PI/180.0f); // Find X and Y values at time “current“ float fX = (float)((InitialVelocity * Math.Cos(fIA) * ElapsedTime)) / 2.0f; float fY = (float)(((InitialVelocity * Math.Sin(fIA) * ElapsedTime) - (0.5f * 9.8f * (ElapsedTime * ElapsedTime))) / 2.0f); PointF pt = new PointF(fX, fY); return pt; } } } -------------------------CannonBallForm------------------------------------ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Windows.Forms; using System.Threading; namespace CannonBallGame { public partial class CannonBallForm : Form { private int angle; private int velocity; private int height; private Thread projectile; private BallisticSimulator cannonSim; // The next position to plot private PointF pointNextPosition = new PointF(); // The size of the dot to draw private SizeF projectileSize = new SizeF(5.0f, 5.0f); public CannonBallForm() { InitializeComponent(); cannonSim = new BallisticSimulator(); } /// /// The main entry point for the application. /// [STAThread] static void Main() { //Application.EnableVisualStyles(); //Application.SetCompatibleTextRenderingDefault(false); Application.Run(new CannonBallForm()); } private void Run() { try { Cannon c = new Cannon(graphicsPanel, angle, velocity, height); c.fire(); } catch (ThreadAbortException) { } finally { bigRedButton.Enabled = true; } } private void angleSelect_ValueChanged(object sender, EventArgs e) { angle = (int)angleSelect.Value; } private void velocitySelect_ValueChanged(object sender, EventArgs e) { velocity = (int)velocitySelect.Value; } private void heightSelect_ValueChanged(object sender, EventArgs e) { height = (int)heightSelect.Value; } private void bigRedButton_Click(object sender, EventArgs e) { bigRedButton.Enabled = false; timer1.Enabled = true; cannonSim.InitialAngle = angle; cannonSim.InitialVelocity = velocity; } private void timer1_Tick(object sender, EventArgs e) { // On tick, increment simulator and plot next point on trajectory PlotPoint(cannonSim.GetNextPosition()); } public void Reset() { pointNextPosition = new Point(0, 0); } public void PlotPoint(PointF point) { pointNextPosition = point; // We could invalidate just around this point for better performance //graphicsPanel.Invalidate(); Graphics g = graphicsPanel.CreateGraphics(); // Setup a transform that puts (0,0) at the bottom left corner Matrix xform = new Matrix(); xform.Scale(1.0f, -1.0f); xform.Translate(0, -(graphicsPanel.Height - height)); g.Transform = xform; // Smooooth! g.SmoothingMode = SmoothingMode.AntiAlias; // Draw the projectile RectangleF rect = new RectangleF(pointNextPosition, projectileSize); rect.Offset(-projectileSize.Width / 2.0f, -projectileSize.Height / 2.0f); g.FillEllipse(Brushes.Blue, rect); } } }