@@ -19,6 +19,8 @@ local ResourceManager = require("eyes.utils.resource_manager")
1919--- @field reflection table {intensity =number , x =number , y =number } Reflection properties
2020--- @field pupilDilation number Current pupil dilation value (0-1 )
2121--- @field isTouching boolean Whether the eye is currently being touched
22+ --- @field pupilTarget table {x =number , y =number } Target position for the pupil
23+ --- @field pupilCurrent table {x =number , y =number } Current position of the pupil
2224local Eye = {}
2325Eye .__index = Eye
2426
@@ -51,6 +53,11 @@ function Eye.new(id, x, y, size, phaseX, phaseY)
5153 }
5254 self .pupilDilation = 0
5355 self .isTouching = false
56+
57+ -- Initialize pupil tracking properties
58+ self .pupilTarget = {x = x , y = y }
59+ self .pupilCurrent = {x = x , y = y }
60+
5461 return self
5562end
5663
@@ -178,6 +185,23 @@ function Eye:updatePupilDilation(targetDilation, fadeSpeed, dt)
178185 (targetDilation - self .pupilDilation ) * dt * fadeSpeed
179186end
180187
188+ --- Updates the tracking position of the pupil with inertia
189+ --- @param dt number Delta time
190+ --- @param targetX number Target X position
191+ --- @param targetY number Target Y position
192+ --- @param trackingSpeed number How quickly the pupil tracks the target
193+ function Eye :updatePupilTracking (dt , targetX , targetY , trackingSpeed )
194+ -- Update the target position
195+ self .pupilTarget .x = targetX
196+ self .pupilTarget .y = targetY
197+
198+ -- Move current position toward target with inertia
199+ self .pupilCurrent .x = self .pupilCurrent .x +
200+ (self .pupilTarget .x - self .pupilCurrent .x ) * dt * trackingSpeed
201+ self .pupilCurrent .y = self .pupilCurrent .y +
202+ (self .pupilTarget .y - self .pupilCurrent .y ) * dt * trackingSpeed
203+ end
204+
181205-- The public module
182206local eyes = {
183207 -- Configuration
@@ -208,6 +232,13 @@ local eyes = {
208232 dampingFactor = 0.85 , -- How quickly attraction velocity decays
209233 },
210234
235+ -- Eye tracking configuration
236+ tracking = {
237+ speed = 15.0 , -- Base speed of eye tracking (higher = faster tracking)
238+ touchedSpeedFactor = 0.3 , -- When touched, tracking is this much slower
239+ maxTrackingDistance = 0.5 , -- Max percentage of eye size the pupil can move from center
240+ },
241+
211242 -- Reflection state for fire effects
212243 reflection = {
213244 fadeSpeed = 3 , -- How quickly reflection fades in/out
@@ -356,21 +387,28 @@ end
356387--- @param eyeY number Y position of the eye
357388--- @param eyeSize number Size of the eye
358389--- @param fadeValue number 0-1 fade value for oscillation
390+ --- @param currentPupilX number Current X position of the pupil (for inertia )
391+ --- @param currentPupilY number Current Y position of the pupil (for inertia )
359392--- @return number irisX X position of the iris
360393--- @return number irisY Y position of the iris
361394--- @return number pupilX X position of the pupil
362395--- @return number pupilY Y position of the pupil
363396--- @return number angle Direction angle
364- local function calculatePupilPosition (eyeX , eyeY , eyeSize , fadeValue )
365- -- Calculate tracking position (where pupil would be when tracking mouse)
397+ local function calculatePupilPosition (eyeX , eyeY , eyeSize , fadeValue , currentPupilX , currentPupilY )
366398 local mouseX , mouseY = love .mouse .getPosition ()
367399 local distanceX = mouseX - eyeX
368400 local distanceY = mouseY - eyeY
369- local distance = math.min (math.sqrt (distanceX ^ 2 + distanceY ^ 2 ), eyeSize / 2 )
401+
402+ -- Calculate the maximum distance the pupil can move
403+ local maxDistance = eyeSize * eyes .tracking .maxTrackingDistance
404+
405+ -- Calculate tracking position
406+ local distance = math.min (math.sqrt (distanceX ^ 2 + distanceY ^ 2 ), maxDistance )
370407 local angle = math.atan2 (distanceY , distanceX )
371408
372- local trackingX = eyeX + (math.cos (angle ) * distance )
373- local trackingY = eyeY + (math.sin (angle ) * distance )
409+ -- Use the current position from the eye's tracking system
410+ local trackingX = currentPupilX
411+ local trackingY = currentPupilY
374412
375413 -- Calculate oscillation position (where pupil would be when eye is touched)
376414 local oscillationRange = eyeSize / 16
@@ -546,8 +584,11 @@ local function drawEye(eye, isOnline)
546584 drawEyeBase (eyeX , eyeY , eyeSize , eyeColor , shadedEyeColor , dirX , dirY )
547585 drawBloodVeins (eyeX , eyeY , eyeSize , fadeValue )
548586
549- -- Calculate iris and pupil positions
550- local irisX , irisY , pupilX , pupilY = calculatePupilPosition (eyeX , eyeY , eyeSize , fadeValue )
587+ -- Calculate iris and pupil positions using current tracked position
588+ local irisX , irisY , pupilX , pupilY = calculatePupilPosition (
589+ eyeX , eyeY , eyeSize , fadeValue ,
590+ eye .pupilCurrent .x , eye .pupilCurrent .y
591+ )
551592
552593 drawIris (irisX , irisY , eyeSize , pupilColor )
553594 drawPupil (pupilX , pupilY , eyeSize , dilationFactor )
@@ -743,6 +784,50 @@ function eyes.update(dt)
743784 eyes .shakeX = eyes .stateManager .shake .x
744785 eyes .shakeY = eyes .stateManager .shake .y
745786
787+ -- Update eye pupil tracking with inertia
788+ local leftEye = eyes .eyes .left
789+ local rightEye = eyes .eyes .right
790+ local leftEyeX , leftEyeY = leftEye :getPosition ()
791+ local rightEyeX , rightEyeY = rightEye :getPosition ()
792+
793+ -- Calculate target positions for both eyes
794+ local function calculateTargetPosition (eyeX , eyeY , eyeSize )
795+ local mouseX , mouseY = love .mouse .getPosition ()
796+ local distanceX = mouseX - eyeX
797+ local distanceY = mouseY - eyeY
798+
799+ -- Limit how far the pupil can move from center
800+ local maxDistance = eyeSize * eyes .tracking .maxTrackingDistance
801+ local distance = math.sqrt (distanceX ^ 2 + distanceY ^ 2 )
802+
803+ if distance > maxDistance then
804+ local factor = maxDistance / distance
805+ distanceX = distanceX * factor
806+ distanceY = distanceY * factor
807+ end
808+
809+ return eyeX + distanceX , eyeY + distanceY
810+ end
811+
812+ -- Calculate tracking speed based on touch state
813+ local leftTrackingSpeed = eyes .tracking .speed
814+ local rightTrackingSpeed = eyes .tracking .speed
815+
816+ if leftEye .isTouching then
817+ leftTrackingSpeed = leftTrackingSpeed * eyes .tracking .touchedSpeedFactor
818+ end
819+
820+ if rightEye .isTouching then
821+ rightTrackingSpeed = rightTrackingSpeed * eyes .tracking .touchedSpeedFactor
822+ end
823+
824+ -- Get target positions and update pupil tracking
825+ local leftTargetX , leftTargetY = calculateTargetPosition (leftEyeX , leftEyeY , leftEye .size )
826+ local rightTargetX , rightTargetY = calculateTargetPosition (rightEyeX , rightEyeY , rightEye .size )
827+
828+ leftEye :updatePupilTracking (dt , leftTargetX , leftTargetY , leftTrackingSpeed )
829+ rightEye :updatePupilTracking (dt , rightTargetX , rightTargetY , rightTrackingSpeed )
830+
746831 -- Update audio system with current state and cursor position
747832 audio :update (dt , {
748833 touching = eyes .stateManager .touching ,
0 commit comments