VB/C# Shape follow cursor but constrain bounds

90 Views Asked by At

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

1

There are 1 best solutions below

5
On BEST ANSWER

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