Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
MovieClip or Roll Your Own? (with Editor and example project) — Gideros Forum

MovieClip or Roll Your Own? (with Editor and example project)

antixantix Member
edited March 2016 in General questions
Hey all. I am trying to decide if I should use MovieClip for animations, or if I should just create my own animation system. I have looked at some MovieClip examples and tutorials but I'm slightly confused and wonder if somebody can answer a question. Is every frame in a MovieClip a separate Bitmap and each of those bitmaps a separate image file?

EDIT:
Well here is my Animation Editor. It's purpose is to create animation data for sprites arranged in a grid, inside a TextureAtlas.

HOWTO - EDITOR:
To get started quickly, load an atlas (player.png in the images folder should do), load an animation file (player.aaf in the images folder will suffice), and start messing about. Otherwise...

1. Click the "Load" toolbar button in the :TextureAtlas" pane to load an atlas. By default your atlas will be sliced vertically into 64x64 sized regions, which you will see populating the "TextureRegions" pane, ready to be added as frames in your animations. You can change the slice settings at any time and click the "Vertical" or Horizontal" buttons to reslice the atlas.

2. Select an animation from the list in the "Animations" pane. You can rename it and set it's other properties with the controls in the Animation pane.
2a. Click the "Loops" checkbox if you want the animation to loop when complete.
2b. Use the "Speed" slider to adjust playback speed. The formula for animation playback speed is as follows... (1 / number of frames) * playback speed.
2c. Use the "offsetX" and "offsetY" sliders to adjust the frames position. NOTE: This information is saved but the Animator class currently ignores these values.

3. To add frames to an animation just "DoubleClick" any region in the "TextureRegion" pane and it will be added to the currently selected animations list of frames (in the "Frames" pane).

4. You can use the controls in the "Frames" pane to move the currently selected frame up and down in the list, as well as delete it.

5. In the Playback pane you can test your animations and see if they play how you want. You can use the toolbar buttons to advance/reverse frame by frame, goto first/last frames, and play/stop playback. NOTE: Currently all animations loop in the editor.

6. Click the "Save" toolbar button in the "Animations" pane to save your animations. The file will be saved as "yourfilename.aaf" which is just a plain text file containing the region and animation information.

7. Click the "Export" toolbar button in the "Animations" pane to export the animations for use in your game. The file will be exported as "yourfilename.json" which you might guess, is a JSON file containing the region and animation data.

HOWTO - GIDEROS:
The included example project has a bunch of buttons that you can click to play different animations, and a bunch of extra code. The most basic example I can come up with is as follows...
require("json") -- FOR OPERATIONS ON JSON DATA
local File = File.new() -- FOR FILE OPERATIONS
local Animator = Animator.new() -- THE ANIMATOR CLASS
 
local playerAtlas = Texture.new("images/player.png")-- LOAD ATLAS
local player = Actor.new(TextureRegion.new(playerAtlas, 0, 0, 0, 0)) --CREATE PLAYER ACTOR
stage:addChild(player)
 
local playerAnimations = File:loadJSON("images/player.json") -- LOAD ANIMATIONS
Animator:attach(player, playerAnimations) -- ASSIGN ANIMATIONS TO PLAYER
 
Animator:set(player, "run") - START ANIMATION
 
local function onEnterFrame(event) -- MAIN PROGRAM LOOP
  local timer = os.timer()
  local dt = timer - currentTimer
  currentTimer = timer
  Animator:update(player, dt) -- UPDATE PLAYER ANIMATION
end
 
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
LIMITATIONS:
Windows only (tested on Win8.1 64-bit), requires .net Framework 3.5
An animation file can contain only 128 animations.
Each animation can contain 64 animation frames.

I'm sure there are other things I forgot, just ask :)

UPDATES:
14/3/16 - Updated Animator class to skip unnecessary calls to setRegion(). Thanks @keszegh
15/3/16 - Updated Editor and screenshot to fix Sc rollbar in "TextureAtlas" pane that was too short.
Antix Animation Editor V1.0.0.png
1351 x 707 - 219K
Example.png
657 x 1020 - 16K
zip
zip
Antix Animation System.zip
314K

Likes: talis, hgy29, pie

+1 -1 (+3 / -0 )Share on Facebook

Comments

  • not necessarily, you can tween motions (rotation, translation, scale) within a movieclip.
    so it's a combination of frames and tweens that you can use movieclip for.
  • I never change the bitmap in a MovieClip - just tween the bitmap between various positions, sizes, rotations, etc...
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • totebototebo Member
    edited March 2016
    I like MovieClip and use it a lot. For custom properties, such as setAltitude() in an isometric game, I use a custom Tween class because MovieClip only accepts Sprite.

    MovieClip is a bit limited, and could do with a few extra features such as getFrame(), reverse() and a way to step it instead of relying on its internal timers. The latter would prevent it from going out of sync, and allowing you to pause many MovieClips easily.

    Overall, though, MovieClip is faster, and therefore lovelier, than GTween.
    My Gideros games: www.totebo.com
  • antixantix Member
    Let me rephrase my question.. Is each graphic in a MovieClip a separate Bitmap object?
  • @antix yes it is, you can even modify each of them.
    I even apply shader on each of them

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • antixantix Member
    edited March 2016
    @tkhnoman - Thanks. What I would ideally like is to have a 1 frame (Bitmap) MovieClip and then modify the Bitmap using my own animation system that uses TextureRegion swapping. I think this would be faster and more efficient than creating hundreds of Bitmap objects which are then used as frames. That's the theory anyway ~:>

    Likes: totebo

    +1 -1 (+1 / -0 )Share on Facebook
  • Like that idea @antix. Share the class if you make one! :)

    Likes: antix

    My Gideros games: www.totebo.com
    +1 -1 (+1 / -0 )Share on Facebook
  • antixantix Member
    Will do, I'm just working on the editor right now :)

    Likes: totebo

    +1 -1 (+1 / -0 )Share on Facebook
  • i guess textureregion swap is pretty fast, so that's a good idea. good luck with it and please share your class later.

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    Did you try TNT animator studio by gregBUG?
    I think it does the same thing, and it already has its editor. :) I use it and I am very happy about it.
    http://www.tntparticlesengine.com/?page_id=405

    The free version is compiled, but if you donate something you get the lua source

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • antixantix Member
    @pie, thanks. Yep I looked at that and it is pretty cool but unfortunately it uses Texture Packs, with no option to just use a big Texture and TextureRegions.

    I have already created an editor for my system, and now need to get the animator class working in Gideros.
  • antixantix Member
    *shameless bump*

    Edited top post which includes my Animation Editor and a Gideros example project. Enjoy @};-

    Likes: keszegh, totebo

    +1 -1 (+2 / -0 )Share on Facebook
  • Thanks for sharing your tool, really appreciated the effort. =D>

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • one could combine this with movieclips or extend this so that it can do all that movieclips can (while still working with textureregions) - i.e. tweening.
    in any case your class is already great for frame by frame animation and mc is good for tween animation.

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • i don't know how much it matters but perhaps when the frame did not change then you could avoid refreshing the textureregion. for very slowly animated sprites this could save a lot of settextureregion calls.

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
  • antixantix Member
    @keszegh, yep I suppose I could do that. I suppose storing oldFrame and checking that vs newFrame would do the trick.

    I will have to test which is faster, checking and not setting regions, or just setting regions every time :)

    With regards to mirroring MovieClips, I should find out more about how they work and what they do. I gave up on them when I discovered they create too many Bitmaps.

    So with MovieClip and GTween.. What is the difference?
  • antixantix Member
    Okay adding frame skipping was straight forward. I've re-uploaded the whole thing (in the first post) with the updated file. Here it is for those who don't want to download the entire thing again..
    --[[
     
    name:   Antix Animator
    vers:   1.0.1
    desc:   A simple frame based animation system
    auth:   by Cliff Earl
    date:   March 2016
    legal:  (c) 2016 Antix Software
     
    hist:   v1.0.1 - Added frameskipping to avoid wasteful calls to setRegion(). Thanks to keszegh
     
    --]]
     
    Animator = Core.class()
     
    -- NOTHING MUCH HAPPENS ON STARTUP
    function Animator:init()
    end
     
    -- ASSIGN ANIMATIONS TO ACTOR
    function Animator:attach(actor, a)
      actor.anim_regions    = a.regions
      actor.animations      = a.animations
      actor.anim_paused     = true
      actor.anim_complete   = false
      actor.anim_speed      = 0
      actor.anim_loops      = false
      actor.anim_timer      = 0
      actor.anim_frames     = nil
      actor.anim_length     = 0
      actor.anim_prevFrame  = 0
    end
     
    -- DETACH ANIMATIONS FROM ACTOR
    function Animator:detach(actor)
      actor.anim_regions    = nil
      actor.animations      = nil
      actor.anim_paused     = nil
      actor.anim_complete   = nil
      actor.anim_speed      = nil
      actor.anim_loops      = nil
      actor.anim_timer      = nil
      actor.anim_frames     = nil
      actor.anim_length     = nil
      actor.anim_prevFrame  = nil
    end
     
    -- UTILITY FUNCTION - DESTROY ANIMATION
    function Animator:dispose(table)
      for k in next,table do
        local t = type(k)
        if k == "table" then -- IF NEXT IS A TABLE THEN EMPTY THAT FIRST
          self:dispose(k)
        end
        table[k] = nil
      end
    end
     
    -- SET WHICH ANIMATION TO PLAY
    function Animator:set(actor, animation)
      local a = actor.animations[animation]
      actor.anim_frames     = a.frames
      actor.anim_speed      = a.speed
      actor.anim_length     = a.length
      actor.anim_complete   = false
      actor.anim_paused     = false
      actor.anim_loops      = a.loops
      actor.anim_timer      = 0
      actor.anim_prevFrame  = -1
    end
     
    -- SET ACTORS ANIMATION PLAYING OR PAUSED
    function Animator:pause(actor, state)
      actor.anim_paused = state
    end
     
    -- ANIMATE ACTOR
    function Animator:update(actor, dt)
      if actor.anim_paused then return end -- DON'T BOTHER IF IT'S PAUSED
     
      local floor = math.floor
      local function clamp(n, min, max) return n < min and min or (n > max and max or n) end
     
      if actor.anim_loops then -- PLAY LOOPING ANIMATION
        local timer = actor.anim_timer + (dt * actor.anim_speed)
     
        local nextFrame = clamp(floor(actor.anim_length * timer + 1), 1, actor.anim_length)
          if nextFrame ~= actor.anim_prevFrame then
            local region = actor.region
            local r = actor.anim_regions[actor.anim_frames[nextFrame]]
            region:setRegion(r[1], r[2], r[3], r[4]) -- SET NEW TEXTURE REGION
            actor:setTextureRegion(region)
            actor.anim_prevFrame = nextFrame
          end
        if timer >= 1 then timer = timer - 1 end
        actor.anim_timer = timer
      else
        if not actor.anim_complete then -- PLAY NON LOOPING ANIMATION
          local timer = actor.anim_timer + (dt * actor.anim_speed)
          local nextFrame = clamp(floor(actor.anim_length * timer + 1), 1, actor.anim_length)
          if nextFrame ~= actor.anim_prevFrame then
            local region = actor.region
            local r = actor.anim_regions[actor.anim_frames[nextFrame]]
            region:setRegion(r[1], r[2], r[3], r[4])
            actor:setTextureRegion(region) -- SET NEW TEXTURE REGION
            actor.anim_prevFrame = nextFrame
          end
          if timer >= 1 then actor.anim_complete = true end
          actor.anim_timer = timer
        end
      end
    end
  • thanks.

    one movieclip can combine many tweens and frame based animation into one anim that you can simply 'play'. this could be done with making the many tweens of course but would be much more complicated.
  • keszeghkeszegh Member
    edited March 2016
    btw movieclip has the advantage that it's native (not lua), so perhaps movieclip should be modified to work as antix's class.

    like a MovieClipTextureBased (or the same name MovieClip with some flag when created, to mark that it's defined differently) in which the constructor timeline is not containing elements of type
    {1, 100, sprite, {x = {0, 200, "linear"}}}
    but rather
    {1, 100, textureregion, {x = {0, 200, "linear"}}}
    and when playing such an mctb, when the texture is the same and only the region changed, it would work internally as antix's solution, that is, only set the new region.
    this way only as many sprites would be created by the movieclip as necessary. in most cases only one, if all the frames fit in one texture.

    of course antix can modify his code to work like this but i guess changing mc to work like this might be less work and useful enough to put it into the core code.
  • or even better only in the timeline elements would one decide the type and for texturebased ones perhaps some self-defined scaling etc can be useful (which for a sprite exists already):
    {1, 100, textureregion, {x = {0, 200, "linear"}},{texturebased=true,startScaleX=2}}
  • antixantix Member
    @keszegh, thanks, that's a lot to think about. For now I'm happy with the Animator class. I might add tweening to it, or possibly make my own tweening class which would do most things that GTween could do but with a couple of differences.
Sign In or Register to comment.