Home page > LÖVE tutorials

Eyes

A tutorial for Lua and LÖVE 11

Download eyes.love

The eyes follow the cursor.

Drawing an eye

The eye is drawn with a white circle and a smaller dark blue circle for the pupil.

Full code at this point

function love.draw()
    love.graphics.setColor(1, 1, 1)
    love.graphics.circle('fill', 200, 200, 50)

    love.graphics.setColor(0, 0, .4)
    love.graphics.circle('fill', 200, 200, 15)
end

Getting X and Y distance between cursor and eye

The distance between the center of the eye and the mouse cursor is displayed.

The X and Y positions of the eye are reused from drawing the eye, so variables are made for them.

Full code at this point

function love.draw()
    local eyeX = 200
    local eyeY = 200

    local distanceX = love.mouse.getX() - eyeX
    local distanceY = love.mouse.getY() - eyeY

    love.graphics.setColor(1, 1, 1)
    love.graphics.circle('fill', eyeX, eyeY, 50)

    love.graphics.setColor(0, 0, .4)
    love.graphics.circle('fill', 200, 200, 15)

    love.graphics.setColor(1, 1, 1)
    love.graphics.print(table.concat({
        'distance x: '..distanceX,
        'distance y: '..distanceY,
    }, '\n'))

end

Getting straight-line distance between cursor and eye

The distance in a straight line is calculated using the Pythagorean theorem.

The square root of the distance on the X axis squared plus the distance on the Y axis squared is the distance in a straight line.

Full code at this point

function love.draw()
    -- etc.

    local distance = math.sqrt(distanceX^2 + distanceY^2)

    -- etc.

    love.graphics.print(table.concat({
        'distance x: '..distanceX,
        'distance y: '..distanceY,
        'distance: '..distance,
    }, '\n'))
end

Getting angle between cursor and eye

The angle in radians between the mouse cursor and the center of the eye is calculated using math.atan2.

Full code at this point

function love.draw()
    -- etc.

    local angle = math.atan2(distanceY, distanceX)

    -- etc.

    love.graphics.print(table.concat({
        'distance x: '..distanceX,
        'distance y: '..distanceY,
        'distance: '..distance,
        'angle: '..angle,
    }, '\n'))
end

Moving pupil

The cosine/sine of the X/Y positions give the ratio between the X/Y positions and the straight-line distance.

For example, when the mouse is directly below the eye, all of the straight-line distance goes into the Y axis, so the cosine is 0 and the sine is 1.

For another example, when the sine is 0.5, the Y distance is 0.5 (i.e. half) of the straight-line distance, and the X distance is around 0.86 of the straight-line distance.

The pupil is moved by the cosine/sine of the angle multiplied by the distance, which brings the pupil to the mouse position.

Full code at this point

function love.draw()
    -- etc.

    local pupilX = eyeX + (math.cos(angle) * distance)
    local pupilY = eyeY + (math.sin(angle) * distance)

    -- etc.

    love.graphics.setColor(0, 0, .4)
    love.graphics.circle('fill', pupilX, pupilY, 15)

    -- etc.

    love.graphics.print(table.concat({
        'distance x: '..distanceX,
        'distance y: '..distanceY,
        'distance: '..distance,
        'angle: '..angle,
        'cos(angle): '..math.cos(angle),
        'sin(angle): '..math.sin(angle),
    }, '\n'))
end

Moving pupil maximum distance

The straight-line distance is limited to a certain number so that it can't move outside of the eye.

Full code at this point

function love.draw()
    -- etc.

    local distance = math.min(math.sqrt(distanceX^2 + distanceY^2), 30)

    -- etc.
end

Multiple eyes

The code is made into a function which takes an eye's X and Y positions.

Full code at this point

function love.draw()
    function drawEye(eyeX, eyeY)
        local distanceX = love.mouse.getX() - eyeX
        local distanceY = love.mouse.getY() - eyeY
        local distance = math.min(math.sqrt(distanceX^2 + distanceY^2), 30)
        local angle = math.atan2(distanceY, distanceX)

        local pupilX = eyeX + (math.cos(angle) * distance)
        local pupilY = eyeY + (math.sin(angle) * distance)

        love.graphics.setColor(1, 1, 1)
        love.graphics.circle('fill', eyeX, eyeY, 50)

        love.graphics.setColor(0, 0, .4)
        love.graphics.circle('fill', pupilX, pupilY, 15)
    end

    drawEye(200, 200)
    drawEye(330, 200)
end