Page 1 of 2

Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 1:12 pm
by AlexanDDOS
I made a simple sprite animation library writen in Lua for LÖVE. It works with LÖVE drawable objects, supports looping animations, animation pausing, automatic loading frames from image files by strings with their names, frame transforms and creating sprites from spritesheets (by a special sub-module).

The source code, issue section and full manual are on the library's GitHub page:
https://github.com/AlexanDDOS/love-imation

UPD: It's my first published project, so it doesn't seem to be perfect. I often get advises, how to make its code cleaner and faster, so it changes often too. I have already solved some problems stated below, so they aren't actual now.

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 2:16 pm
by grump
Nice.

You might want to consider using ImageData:paste in place of mapPixel for cropping. It'll be faster, shorter and cleaner.

Documentation has lots of typos:
repectively
an new
initialzation
love.grpahics
...

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 2:36 pm
by ivan
I see where you are going with this lib, but the code needs a lot of work.
You are creating tables left and right, some of which are not used at all (for example: letters={'x','y'}).

Code: Select all

  local frame = self:getCurrentFrame()
  local args = {frame[1], ...}
  local letters = {'x', 'y'}
  
  for i = 2, 10 do
    if i < 5 or i > 6 then
      args[i] = args[i] or frame_defaults[i] + frame[i]
    else
      args[i] = args[i] or frame_defaults[i] * frame[i]
    end
  end

  love.graphics.draw(unpack(args))
end
The use metatables/rawset in your case is not very appropriate IMO.
Minus points for not using quads.
No offence, but the code is all of the place. :)
Consider the following tutorial on how to clean up/simplify your lib:
https://2dengine.com/?p=animation
(I know this is not a perfect example, but note how much less code is involved during update/draw)

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 4:08 pm
by AlexanDDOS
Thanks, the upper commenters!
I've already optimized the code and fixed some bugs.

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 4:31 pm
by ivan
Looks better. Your use of metatables is not very good, in fact I highly recommend avoiding metatables in this case.
If you insist on using metatables (which is pointless in your case) then how about:

Code: Select all

local alias = {drawable=1, x=2, y=3, r=4, sx=5, sy=6, ox=7, oy=8, kx=9, ky=10}
-- untested but much cleaner IMO
local frame_mt = {
  __index = function(t, k)
    return rawget(t, alias[k] or k)
  end,
  __newindex = function(t, k, v)
    rawset(t, alias[k] or k, v)
  end
}
I think the code would be much cleaner if removed this "key to index" business altogether.
It doesn't add anything useful to an animation library.

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 7:41 pm
by AlexanDDOS
ivan wrote:
Tue May 01, 2018 4:31 pm
Looks better. Your use of metatables is not very good, in fact I highly recommend avoiding metatables in this case.
If you insist on using metatables (which is pointless in your case) then how about:

Code: Select all

local alias = {drawable=1, x=2, y=3, r=4, sx=5, sy=6, ox=7, oy=8, kx=9, ky=10}
-- untested but much cleaner IMO
local frame_mt = {
  __index = function(t, k)
    return rawget(t, alias[k] or k)
  end,
  __newindex = function(t, k, v)
    rawset(t, alias[k] or k, v)
  end
}
I think the code would be much cleaner if removed this "key to index" business altogether.
It doesn't add anything useful to an animation library.
What do you think about such code?

Code: Select all

local frame_alias = {drawable = 1, x = 2, y = 3, r = 4, sx = 5, sy = 6, ox = 7, oy = 8, kx = 9, ky = 10}

local frame_mt = {
  __index = function(t, k)
    local r = rawget(t, k)
    if r == nil then
      k = frame_alias[k] or tonumber(k)
      r = rawget(t, k)
      if k == 6 then
        r = r or rawget(t, 5) or 1
      elseif k == 5 then
        r = r or 1
      elseif k then
        r = r or 0
      end
    end
    return r
  end,
  __newindex = function(t, k, v)
    rawset(t, frame_alias[k] or k, v)
  end
}

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 8:01 pm
by grump
What are you doing with this frame_alias/frame_mt code? Like, what problem does it solve? I honestly don't get it.

li:draw is a complete mystery to me

Code: Select all

for i = 2, 10 do
    if i < 5 or i > 6 then
      args[i] = args[i] or 0 + frame[i]
    else
      args[i] = args[i] or 1 * frame[i]
    end
end
Both 0 + <number> and 1 * <number> always equal <number>, right?

Re: Love-Imation - a sprite animation library

Posted: Tue May 01, 2018 8:28 pm
by ivan
Yes, what Grump said. Just focus your code on doing 1 thing really well, namely animation. No need for sneaky metatables trying to fill in the default values.

Re: Love-Imation - a sprite animation library

Posted: Wed May 02, 2018 4:31 am
by AlexanDDOS
ivan wrote:
Tue May 01, 2018 8:28 pm
Yes, what Grump said. Just focus your code on doing 1 thing really well, namely animation. No need for sneaky metatables trying to fill in the default values.
I tried to make avoiding li:draw(), if it was needed, easier, because I thought it would be better. But now, I think you're right about fallback values in metatable. People, who really want to avoid it, don't need returning them by the library, so it will be really better to move it from matatables to the drawing function.

Re: Love-Imation - a sprite animation library

Posted: Wed May 02, 2018 4:42 am
by AlexanDDOS
grump wrote:
Tue May 01, 2018 8:01 pm
What are you doing with this frame_alias/frame_mt code? Like, what problem does it solve? I honestly don't get it.

li:draw is a complete mystery to me

Code: Select all

for i = 2, 10 do
    if i < 5 or i > 6 then
      args[i] = args[i] or 0 + frame[i]
    else
      args[i] = args[i] or 1 * frame[i]
    end
end
Both 0 + <number> and 1 * <number> always equal <number>, right?
I just forgot about the operator order, when I was writing this code. I've already fixed it.