Title: Make silly eyes that track the mouse in C#
This example uses a Timer named tmrTick to track the mouse. Its Tick event handler, which is shown in the following code, updates the eyes.
// The previous mouse location.
private Point OldMousePos = new Point(-1, -1);
// See if the mouse has moved.
private void tmrTick_Tick(object sender, EventArgs e)
{
// See if the cursor has moved.
Point new_pos = Control.MousePosition;
if (new_pos.Equals(OldMousePos)) return;
OldMousePos = new_pos;
// Redraw.
this.Invalidate();
}
The Tick event handler uses the MousePosition method to track the mouse position. If the position has changed since the last time this event handler ran, the code invalidates the form to make the following Paint event handler redraw the form.
// Draw the eyes.
private void Form1_Paint(object sender, PaintEventArgs e)
{
DrawEyes(e.Graphics);
}
The Paint event handler simply calls the DrawEyes method shown in the following code.
// Draw the eyes.
private void DrawEyes(Graphics gr)
{
// Convert the cursor position into form units.
Point local_pos = this.PointToClient(OldMousePos);
// Calculate the size of the eye.
int hgt = (int)(this.ClientSize.Height * 0.9);
int wid = (int)(this.ClientSize.Width * 0.45);
// Find the positions of the eyes.
int y = (this.ClientSize.Height - hgt) / 2;
int x1 = (int)((this.ClientSize.Width - wid * 2) / 3);
int x2 = wid + 2 * x1;
// Create a Bitmap on which to draw.
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.Clear(this.BackColor);
// Draw the eyes.
DrawEye(gr, local_pos, x1, y, wid, hgt);
DrawEye(gr, local_pos, x2, y, wid, hgt);
}
The DrawEyes method performs some calculations to see where the eyes should be drawn so they track the mouse position. It uses the PointToClient method to convert the mouse's position into the form's coordinate system. It then calculates the size for the eyes, determines their positions, and calls the following DrawEye method twice to actually draw the eyes.
private Pen ThickPen = new Pen(Color.Black, 3);
...
// Draw an eye here.
private void DrawEye(Graphics gr, Point local_pos,
int x1, int y1, int wid, int hgt)
{
// Draw the outside.
gr.FillEllipse(Brushes.White, x1, y1, wid, hgt);
gr.DrawEllipse(ThickPen, x1, y1, wid, hgt);
// Find the center of the eye.
int cx = x1 + wid / 2;
int cy = y1 + hgt / 2;
// Get the unit vector pointing towards the mouse position.
double dx = local_pos.X - cx;
double dy = local_pos.Y - cy;
double dist = Math.Sqrt(dx * dx + dy * dy);
dx /= dist;
dy /= dist;
// This point is 1/4 of the way
// from the center to the edge of the eye.
double px = cx + dx * wid / 4;
double py = cy + dy * hgt / 4;
// Draw an ellipse 1/2 the size of the eye
// centered at (px, py).
gr.FillEllipse(Brushes.Blue, (int)(px - wid / 4),
(int)(py - hgt / 4), wid / 2, hgt / 2);
}
The DrawEye method draws a white exterior for an eye. It then calculates a unit vector pointing from the eye's center towards the mouse's current position. It moves along this direction 1/4 of the way from the eye's center to its edge. The routine then draws the pupil centered at this position.
If you run the program, you will probably notice a slight flicker as the eyes move. In my next post I'll show you the amazingly easy way to fix that. See if you can figure out how to fix it before you read the next post.
Download the example to experiment with it and to see additional details.
|