使眼球看起来 at/follow 光标移动 (C#)
Making eyeball look at/follow cursor movement (C#)
我被困在这里了。我想在 'looking' 处于光标(的角度)时绘制眼睛。此外,它应该包含在更大的 circle/quadrant 中(就像眼球一样)。可悲的是,它不会在右侧 position/angle 和每次鼠标移动时吸引我的眼球。它唯一要做的就是最初在 (0,0) 处绘制一个椭圆,但这不是我想要的。
我的想法是用勾股定理计算三角形的比值。然后在 drawEllipse();
方法中应用正确的坐标(具有正确的比例)。每次移动光标时都应重复此操作。
你可以查看我的图片进行数学推理。
这是我的代码,请注意面板是在设计器模式下制作的,此代码中未包含此内容,但应该没什么大不了的:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace oogjes2
{
public partial class Form1 : Form
{
public int mousex;
public int mousey;
public Form1()
{
InitializeComponent();
panel1.Paint += paintpanel;
panel1.MouseMove += panel1_MouseMove;
}
//panel1 cover the screen from (0.0) and onwards,
void panel1_MouseMove(object sender, MouseEventArgs mea)
{
int mousex = mea.X;
int mousey = mea.Y;
}
void paintpanel(object obj, PaintEventArgs pea)
{
Pen blackpen = new Pen(Color.Black, 3);
// the black outer circle which doesnt move
pea.Graphics.DrawEllipse(blackpen, -125, -125, 250, 250);
// e = 63. Diagonal distance from (0,0) to starting point drawEllipse
// factor = multiplication from mea.x and mea.y to the respective ex and ey of the small circle.
// ey = factor * mousex (mea.X). Same for ex.
float e = (float)Math.Sqrt(45 * 45 + 45 * 45); //=63
float factor = (e / (float)Math.Sqrt(mousex * mousex + mousey * mousey));
int ex = mousex * (int)factor;
int ey = mousey * (int)factor;
// the eye that should be redrawn at every mousemovement
pea.Graphics.DrawEllipse(blackpen, ex, ey, 50, 50);
this.Invalidate();
}
}
}
如果你想让一只眼睛跟随光标,你需要计算从眼睛到光标的角度。
您只需要知道三件事:
眼睛的位置,鼠标的位置,瞳孔中心离眼睛中心有多远(我叫你的内圈是瞳孔,外圈是眼睛)。
因为眼睛永远不会移动(只围绕它的中心旋转)你已经知道它的位置。
void direction_to_cursor(){
float p = Math.sqrt((45 + r)*(45 + r)*2); // Distance from outer circle center to inner circle center
// assuming you want the top left corner 63 away from 0, 0
// r is radius of inner circle
int x = mouseX - EyeX; // In your picture it looks like your eye is at 0,0
int y = -(mouseY - EyeY); // inverted y axis (0 is at top)
float dir = Math.atan2(x, y);
int px = p * Math.cos(dir); // x Center of inner circle
int py = p * Math.cos(dir); // y Center of inner circle
px -= r; // Get left x coordinate of circle
py -= r; // get right x coordinate of circle
pea.Graphics.DrawEllipse(blackpen, px, py, 50, 50);
}
step1: Calculate distance from center of Eye to center of pupil
step2: Calculate x and y difference between the Mouse and Eye
step3: Calculate direction from eye to mouse.
step4: Calculate position of pupil from direction and distance from center of eye
您可以使用以下内容
void paintpanel(object obj, PaintEventArgs pea)
{
Pen blackpen = new Pen(Color.Black, 3);
pea.Graphics.DrawEllipse(blackpen, -125, -125, 250, 250);
float p = Math.sqrt(2*70*70); // (45+25)*(45+25)+(45+25)*(45+25)
float dir = Math.atan(y, x);
int ex = Math.cos(dir) * p - 25;
int ey = Math.sin(dir) * p - 25;
// the eye that should be redrawn at every mousemovement
pea.Graphics.DrawEllipse(blackpen, ex, ey, 50, 50);
this.Invalidate();
}
试试这个:
public partial class Form1 : Form
{
private Timer tmr;
private int PupilRadius = 20;
private int EyeBallRadius = 50;
private int DistanceBetweenEyes = 20;
public Form1()
{
InitializeComponent();
this.panel1.Paint += panel1_Paint;
tmr = new Timer();
tmr.Interval = 100;
tmr.Tick += tmr_Tick;
tmr.Start();
}
void tmr_Tick(object sender, EventArgs e)
{
panel1.Invalidate();
}
void panel1_Paint(object sender, PaintEventArgs e)
{
Point center = new Point(panel1.ClientSize.Width / 2, panel1.ClientSize.Height / 2);
Point LeftEyeCenter = new Point(center.X - EyeBallRadius - (DistanceBetweenEyes / 2), center.Y);
Point RightEyeCenter = new Point(center.X + EyeBallRadius + (DistanceBetweenEyes / 2), center.Y);
Rectangle rc = new Rectangle(LeftEyeCenter, new Size(1, 1));
rc.Inflate(EyeBallRadius, EyeBallRadius);
e.Graphics.DrawEllipse(Pens.Black, rc);
rc = new Rectangle(RightEyeCenter, new Size(1, 1));
rc.Inflate(EyeBallRadius, EyeBallRadius);
e.Graphics.DrawEllipse(Pens.Black, rc);
Point curPos = panel1.PointToClient(Cursor.Position);
Double DistanceFromLeftEyeToCursor = getDistance(LeftEyeCenter.X, LeftEyeCenter.Y, curPos.X, curPos.Y);
Double DistanceFromRightEyeToCursor = getDistance(RightEyeCenter.X, RightEyeCenter.Y, curPos.X, curPos.Y);
double angleLeft = getAngleInDegrees(LeftEyeCenter.X, LeftEyeCenter.Y, curPos.X, curPos.Y);
double angleRight = getAngleInDegrees(RightEyeCenter.X, RightEyeCenter.Y, curPos.X, curPos.Y);
rc = new Rectangle(new Point(Math.Min((int)DistanceFromLeftEyeToCursor, EyeBallRadius - PupilRadius), 0), new Size(1, 1));
rc.Inflate(PupilRadius, PupilRadius);
e.Graphics.TranslateTransform(LeftEyeCenter.X, LeftEyeCenter.Y);
e.Graphics.RotateTransform((float)angleLeft);
e.Graphics.FillEllipse(Brushes.Blue, rc);
rc = new Rectangle(new Point(Math.Min((int)DistanceFromRightEyeToCursor, EyeBallRadius - PupilRadius), 0), new Size(1, 1));
rc.Inflate(PupilRadius, PupilRadius);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(RightEyeCenter.X, RightEyeCenter.Y);
e.Graphics.RotateTransform((float)angleRight);
e.Graphics.FillEllipse(Brushes.Blue, rc);
}
private Double getDistance(int Ax, int Ay, int Bx, int By)
{
return Math.Sqrt(Math.Pow((Double)Ax - Bx, 2) + Math.Pow((Double)Ay - By, 2));
}
private Double getAngleInDegrees(int cx, int cy, int X, int Y)
{
// draw a line from the center of the circle
// to the where the cursor is...
// If the line points:
// up = 0 degrees
// right = 90 degrees
// down = 180 degrees
// left = 270 degrees
Double angle;
int dy = Y - cy;
int dx = X - cx;
if (dx == 0) // Straight up and down | avoid divide by zero error!
{
if (dy <= 0)
{
angle = 0;
}
else
{
angle = 180;
}
}
else
{
angle = Math.Atan((Double)dy / (Double)dx);
angle = angle * ((Double)180 / Math.PI);
if (X <= cx)
{
angle = 180 + angle;
}
}
return angle;
}
}
我被困在这里了。我想在 'looking' 处于光标(的角度)时绘制眼睛。此外,它应该包含在更大的 circle/quadrant 中(就像眼球一样)。可悲的是,它不会在右侧 position/angle 和每次鼠标移动时吸引我的眼球。它唯一要做的就是最初在 (0,0) 处绘制一个椭圆,但这不是我想要的。
我的想法是用勾股定理计算三角形的比值。然后在 drawEllipse();
方法中应用正确的坐标(具有正确的比例)。每次移动光标时都应重复此操作。
你可以查看我的图片进行数学推理。
这是我的代码,请注意面板是在设计器模式下制作的,此代码中未包含此内容,但应该没什么大不了的:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace oogjes2
{
public partial class Form1 : Form
{
public int mousex;
public int mousey;
public Form1()
{
InitializeComponent();
panel1.Paint += paintpanel;
panel1.MouseMove += panel1_MouseMove;
}
//panel1 cover the screen from (0.0) and onwards,
void panel1_MouseMove(object sender, MouseEventArgs mea)
{
int mousex = mea.X;
int mousey = mea.Y;
}
void paintpanel(object obj, PaintEventArgs pea)
{
Pen blackpen = new Pen(Color.Black, 3);
// the black outer circle which doesnt move
pea.Graphics.DrawEllipse(blackpen, -125, -125, 250, 250);
// e = 63. Diagonal distance from (0,0) to starting point drawEllipse
// factor = multiplication from mea.x and mea.y to the respective ex and ey of the small circle.
// ey = factor * mousex (mea.X). Same for ex.
float e = (float)Math.Sqrt(45 * 45 + 45 * 45); //=63
float factor = (e / (float)Math.Sqrt(mousex * mousex + mousey * mousey));
int ex = mousex * (int)factor;
int ey = mousey * (int)factor;
// the eye that should be redrawn at every mousemovement
pea.Graphics.DrawEllipse(blackpen, ex, ey, 50, 50);
this.Invalidate();
}
}
}
如果你想让一只眼睛跟随光标,你需要计算从眼睛到光标的角度。
您只需要知道三件事:
眼睛的位置,鼠标的位置,瞳孔中心离眼睛中心有多远(我叫你的内圈是瞳孔,外圈是眼睛)。 因为眼睛永远不会移动(只围绕它的中心旋转)你已经知道它的位置。
void direction_to_cursor(){
float p = Math.sqrt((45 + r)*(45 + r)*2); // Distance from outer circle center to inner circle center
// assuming you want the top left corner 63 away from 0, 0
// r is radius of inner circle
int x = mouseX - EyeX; // In your picture it looks like your eye is at 0,0
int y = -(mouseY - EyeY); // inverted y axis (0 is at top)
float dir = Math.atan2(x, y);
int px = p * Math.cos(dir); // x Center of inner circle
int py = p * Math.cos(dir); // y Center of inner circle
px -= r; // Get left x coordinate of circle
py -= r; // get right x coordinate of circle
pea.Graphics.DrawEllipse(blackpen, px, py, 50, 50);
}
step1: Calculate distance from center of Eye to center of pupil
step2: Calculate x and y difference between the Mouse and Eye
step3: Calculate direction from eye to mouse.
step4: Calculate position of pupil from direction and distance from center of eye
您可以使用以下内容
void paintpanel(object obj, PaintEventArgs pea)
{
Pen blackpen = new Pen(Color.Black, 3);
pea.Graphics.DrawEllipse(blackpen, -125, -125, 250, 250);
float p = Math.sqrt(2*70*70); // (45+25)*(45+25)+(45+25)*(45+25)
float dir = Math.atan(y, x);
int ex = Math.cos(dir) * p - 25;
int ey = Math.sin(dir) * p - 25;
// the eye that should be redrawn at every mousemovement
pea.Graphics.DrawEllipse(blackpen, ex, ey, 50, 50);
this.Invalidate();
}
试试这个:
public partial class Form1 : Form
{
private Timer tmr;
private int PupilRadius = 20;
private int EyeBallRadius = 50;
private int DistanceBetweenEyes = 20;
public Form1()
{
InitializeComponent();
this.panel1.Paint += panel1_Paint;
tmr = new Timer();
tmr.Interval = 100;
tmr.Tick += tmr_Tick;
tmr.Start();
}
void tmr_Tick(object sender, EventArgs e)
{
panel1.Invalidate();
}
void panel1_Paint(object sender, PaintEventArgs e)
{
Point center = new Point(panel1.ClientSize.Width / 2, panel1.ClientSize.Height / 2);
Point LeftEyeCenter = new Point(center.X - EyeBallRadius - (DistanceBetweenEyes / 2), center.Y);
Point RightEyeCenter = new Point(center.X + EyeBallRadius + (DistanceBetweenEyes / 2), center.Y);
Rectangle rc = new Rectangle(LeftEyeCenter, new Size(1, 1));
rc.Inflate(EyeBallRadius, EyeBallRadius);
e.Graphics.DrawEllipse(Pens.Black, rc);
rc = new Rectangle(RightEyeCenter, new Size(1, 1));
rc.Inflate(EyeBallRadius, EyeBallRadius);
e.Graphics.DrawEllipse(Pens.Black, rc);
Point curPos = panel1.PointToClient(Cursor.Position);
Double DistanceFromLeftEyeToCursor = getDistance(LeftEyeCenter.X, LeftEyeCenter.Y, curPos.X, curPos.Y);
Double DistanceFromRightEyeToCursor = getDistance(RightEyeCenter.X, RightEyeCenter.Y, curPos.X, curPos.Y);
double angleLeft = getAngleInDegrees(LeftEyeCenter.X, LeftEyeCenter.Y, curPos.X, curPos.Y);
double angleRight = getAngleInDegrees(RightEyeCenter.X, RightEyeCenter.Y, curPos.X, curPos.Y);
rc = new Rectangle(new Point(Math.Min((int)DistanceFromLeftEyeToCursor, EyeBallRadius - PupilRadius), 0), new Size(1, 1));
rc.Inflate(PupilRadius, PupilRadius);
e.Graphics.TranslateTransform(LeftEyeCenter.X, LeftEyeCenter.Y);
e.Graphics.RotateTransform((float)angleLeft);
e.Graphics.FillEllipse(Brushes.Blue, rc);
rc = new Rectangle(new Point(Math.Min((int)DistanceFromRightEyeToCursor, EyeBallRadius - PupilRadius), 0), new Size(1, 1));
rc.Inflate(PupilRadius, PupilRadius);
e.Graphics.ResetTransform();
e.Graphics.TranslateTransform(RightEyeCenter.X, RightEyeCenter.Y);
e.Graphics.RotateTransform((float)angleRight);
e.Graphics.FillEllipse(Brushes.Blue, rc);
}
private Double getDistance(int Ax, int Ay, int Bx, int By)
{
return Math.Sqrt(Math.Pow((Double)Ax - Bx, 2) + Math.Pow((Double)Ay - By, 2));
}
private Double getAngleInDegrees(int cx, int cy, int X, int Y)
{
// draw a line from the center of the circle
// to the where the cursor is...
// If the line points:
// up = 0 degrees
// right = 90 degrees
// down = 180 degrees
// left = 270 degrees
Double angle;
int dy = Y - cy;
int dx = X - cx;
if (dx == 0) // Straight up and down | avoid divide by zero error!
{
if (dy <= 0)
{
angle = 0;
}
else
{
angle = 180;
}
}
else
{
angle = Math.Atan((Double)dy / (Double)dx);
angle = angle * ((Double)180 / Math.PI);
if (X <= cx)
{
angle = 180 + angle;
}
}
return angle;
}
}