Like2D Logo Like2D
← Back to Docs

Animation NEW

Like2D includes a built-in sprite-sheet animation system. Create animations from horizontal sprite strips and control playback with a rich object-oriented API. Animations use loadImage and renderImageRegion under the hood.

loadAnimation

loadAnimation(filename, frameWidth, frameHeight, frameCount, frameDuration)

Creates an animation object from a horizontal sprite sheet. The image is automatically loaded via loadImage.

Parameters:

Returns:

-- 4-frame walk animation, 64x64 per frame, 0.1s per frame
local walkAnim = loadAnimation("assets/player_walk.png", 64, 64, 4, 0.1)

-- 2-frame idle animation, 0.5s per frame
local idleAnim = loadAnimation("assets/player_idle.png", 64, 64, 2, 0.5)

Animation Methods

Once you have an animation object, use these methods to control playback and rendering.

MethodDescription
anim:update(dt)Advances the animation timer. Call in onUpdate(dt).
anim:draw(x, y, w, h)Renders the current frame. w/h default to frame size.
anim:drawEx(x, y, w, h, angle, flipH, flipV, alpha, ox, oy)Renders with full transform (rotation, flip, alpha, origin).
anim:play()Starts or resumes playback.
anim:pause()Pauses at the current frame.
anim:resume()Resumes after pausing.
anim:stop()Stops and resets to frame 0.
anim:reset()Same as stop().
anim:setFrame(n)Jumps to frame n (0-indexed).
anim:isPlaying()Returns true if currently playing.
anim:isFinished()Returns true if a non-looping animation has ended.
anim:getCurrentFrame()Returns the current frame index (0-indexed).
anim:getFrameCount()Returns the total number of frames.
anim:setLooping(bool)Sets whether animation loops (default: true).
anim:setSpeed(multiplier)Sets playback speed (1 = normal, 2 = double).
anim:setPingPong(bool)Enables ping-pong mode (forward → backward → forward).
anim:setReverse(bool)Plays animation in reverse.
anim:setAlpha(alpha)Sets default opacity for drawing (0–1).
anim:setDuration(seconds)Changes per-frame duration at runtime.

Quick Example

local walkAnim, idleAnim, currentAnim

function onInit()
    walkAnim = loadAnimation("assets/player_walk.png", 64, 64, 4, 0.1)
    idleAnim = loadAnimation("assets/player_idle.png", 64, 64, 2, 0.5)
    currentAnim = idleAnim
    player = { x = 400, y = 300, speed = 200 }
end

function onUpdate(dt)
    -- Switch animation based on input
    if isKeyDown("Left") or isKeyDown("Right") then
        currentAnim = walkAnim
        if not walkAnim:isPlaying() then walkAnim:play() end
    else
        if currentAnim == walkAnim then
            currentAnim = idleAnim
            idleAnim:play()
        end
    end

    -- Move player
    if isKeyDown("Left") then player.x = player.x - player.speed * dt end
    if isKeyDown("Right") then player.x = player.x + player.speed * dt end

    -- Update current animation
    currentAnim:update(dt)
end

function onDraw()
    clearScreen(30, 30, 50)
    currentAnim:draw(player.x, player.y, 64, 64)
    drawTextDirect("Frame: " .. currentAnim:getCurrentFrame(), 10, 10, 20, 255, 255, 255, 255)
end

Multi-Animation Example

-- Manage multiple animations for different states
local anims = {}
local currentState = "idle"

function onInit()
    anims.idle = loadAnimation("assets/player_idle.png", 64, 64, 2, 0.5)
    anims.walk = loadAnimation("assets/player_walk.png", 64, 64, 4, 0.1)
    anims.jump = loadAnimation("assets/player_jump.png", 64, 64, 3, 0.15)
    anims.jump:setLooping(false)
    
    player = { x = 400, y = 300, vy = 0, grounded = true }
end

function onUpdate(dt)
    -- Determine state from input/physics
    if not player.grounded then
        currentState = "jump"
    elseif isKeyDown("Left") or isKeyDown("Right") then
        currentState = "walk"
    else
        currentState = "idle"
    end
    
    -- Update only the current animation
    anims[currentState]:update(dt)
end

function onDraw()
    clearScreen(30, 30, 50)
    anims[currentState]:draw(player.x, player.y, 64, 64)
end

See also: Rendering for the underlying renderImageRegion() function.