Reputation: 179
I have code that will paint a ball when I click the mouse in my panel. Now, what I want is when I click on the panel, not only does a ball appear, but it also moves at some velocity. Right now I don't really care if the ball travels past the panel's boundaries. How do I do this?
public partial class Form1 : Form
{
ArrayList dotPts = new ArrayList();
public Form1()
{
InitializeComponent();
}
private void mainPanel_Paint(object sender, PaintEventArgs e)
{
foreach (Point p in dotPts)
{
e.Graphics.FillEllipse(Brushes.Black, p.X, p.Y, 20, 20);
}
}
private void mainPanel_MouseUp(object sender, MouseEventArgs e)
{
Graphics g = Graphics.FromHwnd(this.Handle);
dotPts.Add(new Point(e.X - 10, e.Y - 10));
mainPanel.Invalidate();
}
}
InitializeComponent():
private void InitializeComponent()
{
this.mainPanel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// mainPanel
//
this.mainPanel.BackColor = System.Drawing.SystemColors.GradientInactiveCaption;
this.mainPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.mainPanel.Location = new System.Drawing.Point(12, 12);
this.mainPanel.Name = "mainPanel";
this.mainPanel.Size = new System.Drawing.Size(790, 424);
this.mainPanel.TabIndex = 0;
this.mainPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.mainPanel_Paint);
this.mainPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.mainPanel_MouseUp);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(821, 447);
this.Controls.Add(this.mainPanel);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
Upvotes: 2
Views: 5907
Reputation: 18430
I have got an example (quick and dirty) code i tried to give you an idea.. (run it in LINQPAD)
using System.Drawing;
using System.Windows.Forms;
void Main()
{
Application.Run(new Form1());
}
public class Form1 : Form
{
float time3 = 0, time = 0, time2 = 1000000;
int a = -1;
float BallHeight = 20, BallWidth = 20;
PointF BallLocation = new PointF(0, 0);
PointF BallVelocity = new PointF(50, 50);
DateTime dt;
float x = 0;
System.Timers.Timer tmr = new System.Timers.Timer();
System.Timers.Timer gmlp = new System.Timers.Timer();
public Form1()
{
this.Size = new Size(700, 700);
Label lb = new Label();
tmr.Interval = 20;
tmr.Elapsed += (s, e) =>
{
//if(BallLocation.X >= 500) BallVelocity.X *= a;
//if(time3 >= 1000) time=0; else
time3 += 20;// (DateTime.Now.Ticks - dt.Ticks)/10000;
BallLocation.X = BallVelocity.X * (time3 / 1000);
BallLocation.Y = BallVelocity.Y * (time3 / 1000);
this.Invalidate();
if (time >= time2) { tmr.Stop(); tmr.Enabled = false; gmlp.Stop(); gmlp.Enabled = false; }
};
this.DoubleBuffered = true;
gmlp.Interval = 1000;
gmlp.Elapsed += (s, e) =>
{
//dt = dt.AddSeconds(1);
lb.Text =
"time: " + time +
"\ntime2: " + time2 +
"\ntime3: " + time3 +
"\nlocx: " + BallLocation.X +
"\ntimespan: " + (DateTime.Now.Ticks - dt.Ticks) / 10000 +
"\nx moved: " + (BallLocation.X - x);
};
gmlp.Enabled = true;
gmlp.Start();
tmr.Enabled = true;
tmr.Start();
lb.Location = new Point(20, 20);
lb.Size = new Size(80, 200);
this.Controls.Add(lb);
dt = DateTime.Now;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
pe.Graphics.FillEllipse(Brushes.Tomato,
new Rectangle((int)BallLocation.X, (int)BallLocation.Y, (int)BallHeight, (int)BallWidth));
}
}
Upvotes: 1
Reputation: 941625
You need a Timer. In the Tick event handler calculate a new position for the object and call the panel's Invalidate() method so it gets repainted. You can use a PictureBox instead of a Panel if the flicker is getting too noticeable.
Work on the ArrayList as well. This needs to become a List<Ball>
where the Ball class stores the position as well as the velocity vector. Plus whatever other properties you'll add in the future like color or radius.
Upvotes: 2
Reputation: 1516
The general solution to get something to move smoothly over time is to make a timer-object to change the position of the ball by the velocity (or some fraction of it) every tick:
ball.x += xVelocity;
ball.y += yVelocity;
Upvotes: 0