0

I'm having a difficult time emulating an 'eyeball' effect. I have an OvalShape (as in PowerPack shape) and can constrain the movement to a specific x,y. However, I need a fresh eyes to help me out, I think I've been looking at it too long to make any sense of it.

The goal:

Emulate an eyeball movement experience by following the cursor position.

Specifics:

Cursor position is of PointToClient type, ergo, it's relative to the form. The object/shape is relative to a ShapeContainer so MousePosition 10,10 will translate to EyePupil position 10,10 because the location is based on it's parent

Here's a synopsis:

Class

Dim MousePosition As Drawing.Point

.....Handles MyBase.Load

    Dim ctrl As System.Windows.Forms.Control
    For Each ctrl In Me.Controls
        AddHandler ctrl.MouseMove, AddressOf OnMouseMoveHandler
    Next

    Dim canvas As New ShapeContainer
    canvas.Parent = Me.EyeIcon

    Me.EyePupilShape.Parent = canvas

Handling the events:

....OnMouseMoveHandler(..) 

    MousePosition = Me.PointToClient(Cursor.Position)
    Debug.Print("Mouse position : X = " & MousePosition.X & ", " & MousePosition.Y)

    Me.EyePupilShape.Location = New Drawing.Point(Clamp(MousePosition.X, 32, 50), Clamp(MousePosition.Y, 31, 50))

Where Clamp is just a custom version of MathHelper.clamp and the min/max values are where the 'pupil' of the eye should be constrained to within it's parent element

This works as in it confines the pupil to a specific x,y bounds

However, it doesn't 'follow' the cursor per sey. For example, if the cursor is on the bottom left, it doesn't recognize that, it's just based on x,y values, that's were I need help with what I have so far. For what it's worth I've gotten most of my info from MSDN

soulshined
  • 9,612
  • 5
  • 44
  • 79
  • Are you looking for a smooth "follow" effect? That is, if you move the mouse quickly, you want the pupil to gradually shfit towards the mouse, rather than "relocate" to that side instantly (which is what is happening with your code) - is that correct? – CoolBots Feb 05 '17 at 07:48
  • Honestly @CoolBots I'm looking for a solution that matches my needs, regardless of how it's implemented. I can always alter code to my specific needs. But what my goal is, is to have the 'pupil' 'look at' where the cursor location is, but constrain it within the bounds of the eyeball. Right now the shape follows my cursor x,y values but constrains it within 30points-50points both ways, but it doesn't 'look at' the cursor. In other words if i move the cursor to the right it doesn't 'look right' it stays at the x,y value constraint – soulshined Feb 05 '17 at 07:52
  • @CoolBots your way actually sounds better now that I think about it, but both avenues suffice – soulshined Feb 05 '17 at 08:10

1 Answers1

2

You need to take the angle to the mouse cursor into account, then calculate position on a unit circle based on that angle, and scale by radius of your "pupil movement area", adjusting for mouse position being inside the eye/pupil.

I wrote a sample in VB.NET, posted on Github.

Calculations are within the Eyeball.Pupil.Update(Point mouse) function, which receives the mouse coordinates translated using PointToClient() function, as in your case. Here's the code:

Public Sub Update(ByVal mouse As Point)
    'Calculate angle to mouse position
    Dim distanceVector = New PointF(mouse.X - _center.X, mouse.Y - _center.Y)
    Dim angleToMouse = Math.Atan2(distanceVector.Y, distanceVector.X)

    'If the mouse is within the movement radius, restrict movement
    Dim absDistanceVector As PointF = distanceVector
    If absDistanceVector.X < 0 Then absDistanceVector.X *= -1
    If absDistanceVector.Y < 0 Then absDistanceVector.Y *= -1

    'Calculate scale
    Dim scale = New PointF(Math.Min(absDistanceVector.X, _movementRadius.X),
                               Math.Min(absDistanceVector.Y, _movementRadius.Y))

    'Adjust X and Y of the pupil based on scaled vector to mouse cursor, offset by pupil origin
    X = CType(Math.Cos(angleToMouse), Single) * scale.X + _center.X - BoundingBox.Width / 2
    Y = CType(Math.Sin(angleToMouse), Single) * scale.Y + _center.Y - BoundingBox.Height / 2

End Sub 
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
CoolBots
  • 4,770
  • 2
  • 16
  • 30
  • This is an awesome start, doesn't translate completely for my specific needs, but that's ok! You answered the question in a way that can apply to many scenarios. Angle makes sense and quite frankly, I'm starting to regret my school days when we would all complain in Algebra class "We'll never use this crap" and not pay attention. You're the man (or woman). Also, thanks for taking time to put something on Github. People appreciate those that go the extra mile. Great answer – soulshined Feb 05 '17 at 17:28
  • 1
    Nice answer! If the code isn't colored correctly you can just add `` right before the code block and it'll be forced to use VB.NET's syntax highlighting. – Visual Vincent Feb 05 '17 at 22:12
  • More info can be found in the [help center](http://stackoverflow.com/editing-help#syntax-highlighting). – Visual Vincent Feb 05 '17 at 22:18
  • @VisualVincent that's really useful, thank you! I will use that for future posts. – CoolBots Feb 06 '17 at 02:51
  • @soulshined, I am glad you found my answer useful/adaptable for your case; it was fun to write the sample code for your question! :) – CoolBots Feb 06 '17 at 02:52