Log In  

Code for combining simple animations together to create more complex animations using + and * operators.

Cart #animation_operators-0 | 2023-09-09 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
3

The example uses four simple animations—each one just a different coloured circle starting in a different corner and moving to the diagonally opposite corner—and combines them in different ways to create the final animation.

For simple animations A and B:

  • The + operators first runs A and, once it's finished, runs B.
  • The * operator runs both A and B at the same time.

As with normal addition and multiplication you can string together as many animations as you want and use parentheses to indicate a particular ordering.

To create animations use new_animation() and then give the animation object an init method. The init method should return a table containing a draw and an update function; update should return true when the animation has finished.

  a = new_animation()
  a.init = function()
     local offset = 0
     return {
        update=function()
           offset += 5
           if offset > 128 then
              return true
           end
        end,
        draw=function()
           circfill(offset, offset, 2, 7)
        end
     }
  end

The animation object then needs to be instantiated to use it.

  anim = a() -- or a.init(), same thing

  function _update()
     anim.update()
  end

  function _draw()
     cls()
     anim.draw()
  end

Having the init function means you can use the same animation multiple times since any internal values, like offset, will be re-initialized each time. You don't need to initialize the animation each time when combining animations, that's handled internally, you only need to initialize the combined animation as a whole.

  -- creates a compound animation which will play the simple animation
  -- three times in a row.
  anim = (a + a + a)() -- or (a + a + a).init(). Again, same thing.

Lua Code (indented 3 spaces)

do
   local ani_meta = {
      __add=function(self, other)
         local an = new_animation()
         an.init = function()
            local children = {self(), other()}
            local i = 1
            return {
               update=function()
                  local a = children[i]
                  if a.update() then
                     i += 1
                     if i > 2 then
                        return true
                     end
                  end
               end,
               draw=function()
                  local a = children[i]
                  a.draw()
               end
            }
         end
         return an
      end,
      __mul=function(self, other)
         local an = new_animation()
         an.init = function()
            local children = {self(), other()}
            return {
               update=function()
                  local done = true
                  for a in all(children) do
                     local d = a.update()
                     done = done and d
                  end
                  return done
               end,
               draw=function()
                  for a in all(children) do
                     a.draw()
                  end
               end
            }
         end
         return an
      end,
      __call=function(self)
         return self.init()
      end,
   }
   function new_animation()
      return setmetatable({}, ani_meta)
   end
end

Lua Code (indented 1 space)

do
 local ani_meta = {
  __add=function(self, other)
   local an = new_animation()
   an.init = function()
    local children = {self(), other()}
    local i = 1
    return {
     update=function()
      local a = children[i]
      if a.update() then
       i += 1
       if i > 2 then
        return true
       end
      end
     end,
     draw=function()
      local a = children[i]
      a.draw()
     end
    }
   end
   return an
  end,
  __mul=function(self, other)
   local an = new_animation()
   an.init = function()
    local children = {self(), other()}
    return {
     update=function()
      local done = true
      for a in all(children) do
       local d = a.update()
       done = done and d
      end
      return done
     end,
     draw=function()
      for a in all(children) do
       a.draw()
      end
     end
    }
   end
   return an
  end,
  __call=function(self)
   return self.init()
  end,
 }
 function new_animation()
  return setmetatable({}, ani_meta)
 end
end

P#134087 2023-09-09 11:10


[Please log in to post a comment]