Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

spritesheets (animation) in Codea

edited March 2014 in Code Sharing Posts: 499

A more advanced spritesheet animator. Will load spritesheets and let you define animations from a given set of frames.



--# Main
function setup()
    local spritesheet = readImage("Dropbox:runningcat_512x256")
    cat = {
        idle = animation(spritesheet, 512, 256, {vec2(2,2)}), -- freeze on frame[i]
        run  = animation(spritesheet, 512, 256),
    }
end

function draw()
    noSmooth()
    spriteMode(CORNER)

    background(28, 245, 156, 255)
    sprite("Dropbox:retrojungle", 0, 0, WIDTH, HEIGHT)

    translate(WIDTH/4, 100)
    scale(.75)

    cat.run:play()
end

--# animation
animation = class()

function animation:init(spritesheet, width, height, ...)
    self.img    = type(spritesheet) == "string" and readImage(spritesheet) or spritesheet
    self.width  = width
    self.height = height
    self.cols   = math.ceil(self.img.width / self.width)
    self.rows   = math.ceil(self.img.height / self.height)
    self.fps    = type(arg[1]) == "number" and arg[1] or 24
    self.frames = type(arg[1]) == "table" and arg[1] or (type(arg[2]) == "table" and arg[2] or {})

    if #self.frames == 0 then
        for r = 1, self.rows do
            for c = 1, self.cols do
                table.insert(self.frames, vec2(c, r))
            end
        end
    end

    self.mode = { -- spriteMode(...)
        [0] = { -- CORNER
            pos  = vec2(self.width/2, self.height/2),
            size = vec2(self.width, self.height)
        },
        [1] = { -- CORNERS
            pos  = vec2(self.width/2, self.height/2),
            size = vec2(self.width, self.height)
        },
        [2] = { -- CENTER
            pos  = vec2(0, 0),
            size = vec2(self.width, self.height)
        },
        [3] = { -- RADIUS
            pos  = vec2(0, 0),
            size = vec2(self.width*2, self.height*2)
        }
    }

    self.atlas = mesh()
    self.mask  = self.atlas:addRect(0, 0, 0, 0)
    self.atlas.texture = self.img
end

function animation:play()
    self.timer = self.timer or ElapsedTime
    local n = spriteMode()
    i = i or 1

    if (ElapsedTime-self.timer) > (1/self.fps) then
        self.timer = nil
        i = self.frames[i+1] and (i+1) or 1
    end

    self.atlas:setRect(self.mask, self.mode[n].pos.x, self.mode[n].pos.y, self.mode[n].size.x, self.mode[n].size.y)
    self.atlas:setRectTex(self.mask, 1/self.cols*(self.frames[i].x-1), (1/self.rows*(self.rows-self.frames[i].y)), 1/self.cols, 1/self.rows)
    self.atlas:draw()
end

image image

Comments

  • BriarfoxBriarfox Mod
    Posts: 1,542

    @se24vad Looking good! So much smaller then my animation class that I wrote when I first learned Codea. Thanks!

Sign In or Register to comment.