使眼球看起来 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;
    }

}