The external movieclip.lua library allows you to create animated sprites (sometimes called “movieclips”) from sequences of images, which can then be moved around the screen using the same techniques as any other Corona display object.

Functions are available to play these animation frames, or partial sequences of these frames, in either the forward or reverse direction; to jump to specified frames; to skip to the next or previous frame; to automatically delete the animation on completion of a sequence; and to make the animation draggable, complete with press, drag, and release events. Drag boundaries have also been added in this revision. For further documentation, see the latest version of the 2.0 Beta Guide, although this library should be compatible with any version of Corona since 1.1.

This framework provides an quick and lightweight way to create animations, and also helps when porting existing Flash content to Corona. You can download a new sample project that demonstrates most of the features discussed here.

Thanks to all those who contributed code, ideas and/or testing to this library, especially Darren Osadchuk and Scott Janousek.

As always, you should feel free to extend this library for your own projects; the current version includes many features we saw Corona developers implementing repeatedly, and so we hope it will be convenient for everyone. Note that while this is based on the older “sprite” library, the name has been changed to “movieclip”, because “sprite” is now reserved for the upcoming sprite sheet feature in Corona Game Edition. The differences between movieclips and sprite sheets are discussed at the end of this post.

Using the Movieclip Library

This line makes all movieclip features available under the “movieclip” namespace:

[cc lang=”lua”] local movieclip = require “movieclip” [/cc]

movieclip.newAnim( frames )
Creates an animated sprite using an array of image filenames provided in the frames table:

[cc lang=”lua”] myAnim = movieclip.newAnim{ “img1.png”, “img2.png”, “img3.png”, “img4.png” } [/cc]

myAnim:play()
Starts the animated sprite playing in the forward direction. When the end of the image set is reached, it will cycle back to the first image and continue playing. If a specific frame sequence has already been constructed, calling play() with no parameters will simply resume playing within that sequence.

myAnim:play{ startFrame=a, endFrame=b, loop=c, remove=shouldRemove }
Starts the animated sprite playing in the forward direction. When the frame of number given by “endFrame” is reached, it will cycle back to the frame number given by “startFrame” and continue playing.

[cc lang=”lua”]myAnim:play{ startFrame=1, endFrame=6, loop=3, remove=true }[/cc]

The “loop” parameter accepts a number of times to loop the sequence, with zero (the default) indicating that it should loop forever.

The “remove” parameter is a boolean flag, and if set to “true”, the movieclip will automatically delete itself when the given sequence is complete. This is useful for things like animated explosions and other single-use cases. Note that the object will only be garbage-collected if there are no other remaining references to it in your Lua code. The default value is “false”.

All parameters are optional, but startFrame and endFrame will default to the first and last images provided in newAnim(), so it is a good practice to provide both values explicitly to avoid unexpected behavior.

Passing any parameters to play() indicates that a new sequence should be constructed, and any current sequence information will be reset. Call play() with no parameters if you simply want to resume the current sequence.

myAnim:reverse()
Starts the animated sprite playing in the reverse direction. When the beginning of the image set is reached, it will cycle back to the last image and continue playing backwards. If a specific frame sequence has already been constructed, calling reverse() with no parameters will simply resume playing backwards within that sequence.

myAnim:reverse{ startFrame=a, endFrame=b, loop=c, remove=shouldRemove }
Starts the animated sprite playing in the reverse direction. When the frame of number given by “endFrame” is reached, it will cycle back to the frame number given by “startFrame” and continue playing.

The “loop” parameter accepts a number of times to loop the sequence, with zero (the default) indicating that it should loop forever.

The “remove” parameter is a boolean flag, and if set to “true”, the movieclip will automatically delete itself when the given sequence is complete. This is useful for things like animated explosions and other single-use cases. Note that the object will only be garbage-collected if there are no other remaining references to it in your Lua code. The default value is “false”.

All parameters are optional, but startFrame and endFrame will default to the last and first images provided in newAnim(), so it is a good practice to always provide both values explicitly to avoid unexpected behavior.

Passing any parameters to reverse() indicates that a new sequence should be constructed, and any current sequence information will be reset. Call reverse() with no parameters if you simply want to resume the current sequence.

myAnim:nextFrame()
Resets any animation sequence in progress, moves the animation to the next image in the total sequence, and stops. This can be used with a two-frame movieclip to make an image toggle between two states

myAnim:previousFrame()
Resets any animation sequence in progress, moves the animation to the previous image in the total sequence, and stops.

myAnim:currentFrame()
Returns the numerical index of the current frame.

myAnim:totalFrames()
Returns the total number of frames in the animated sprite.

myAnim:stop()
Stops the animation of the sprite at its current frame.

myAnim:stopAtFrame( frame )
Jumps the animation to the specified frame, given either as a frame number or by an optional frame label (see setLabels function below).

Note: to perform the equivalent of a “go to and play” from a specified frame, simply issue a stopAtFrame command followed by a play or reverse command. Both commands will execute before the display updates again, and so the transition will be immediate:

[cc lang=”lua”]myAnim:stopAtFrame(4)

myAnim:play()

myAnim:stopAtFrame(“foo”)
myAnim:reverse()[/cc]

myAnim:setLabels( labels )
Adds optional labels to an Anim object previously created, using a table to assign label names to selected frame numbers:

[cc lang=”lua”]myAnim:setLabels{ foo=1, bar=3 }[/cc]

myAnim:setDrag
Turns any movieclip into a draggable object when “drag” is set as true. The “limitX” and “limitY” parameters limit the dragging to either the x or y axis, and the “bounds” parameter can be used to specify drag boundaries for the object.

The “onPress”, “onDrag” and “onRelease” parameters take the names of functions to be called when those events occur. All parameters are optional.

[cc lang=”lua”]myAnim:setDrag{
drag=true,
limitX=false,
limitY=false,
onPress=myPressFunction,
onDrag=myDragFunction,
onRelease=myReleaseFunction,
bounds={ 10, 10, 200, 50 }
}[/cc]

To turn off the draggable property again, set “drag” to false:

[cc lang=”lua”]myAnim:setDrag{ drag=false }[/cc]

About Bracket Notation

Note that the examples above, in which functions accept values within curly brackets, are using the Lua “shorthand” notation for passing a table of values to a function.

In other words, the function is technically receiving a single value that happens to be a Lua table, which could also be written like this: function( { values } ). The shorthand allows the outer set of parentheses to be eliminated, making the code more readable.

Differences Between Movieclips and Sprite Sheets

The upcoming Corona Game Edition will include a “sprite sheet” feature for constructing animated sprites by copying rectangular areas from a single large texture in memory.

Sprite sheets are a much more efficient use of texture memory than a series of individual image files, since OpenGL-ES allocates all textures in dimensions equal to the next power-of-two, no matter what the size of the source image actually is. For example, a single image with dimensions of 80×300 will require a texture memory allocation of 128×512 pixels. Therefore, sprite sheets are recommended for complex character animation, or any case in which there are a large number of animation states.

However, sprite sheets will require more coding and are more complex to set up; for example, you must first construct a large sheet of animation frames using a tool like Zwoptex. Therefore, the movieclip library is easier to get started with, and can be more rapidly used to port Flash content, since movieclip frames can be exported directly from Flash as PNG sequences.

  1. Thanks for the updated library.

    I think there is a small error in your example. You have
    local movieclip = require “movieclip”
    myAnim = sprite.newAnim{ “img1.png”, “img2.png”, “img3.png”, “img4.png” }

    I think the second line should be:
    myAnim = movieclip.newAnim{ “img1.png”, “img2.png”, “img3.png”, “img4.png” }

  2. What is the best way to control the speed of the animation?

    Would it be a case of using a timer and calling something like

    myAnim:nextFrame()

  3. @Paul – your suggestion would probably work well in some cases, although if you had more than a few clips onscreen, you’d want to test it on target devices to see the performance. I don’t think timers are necessarily that expensive, but they might add up if you had a lot of functions constantly polling the system time.

    The movieclip library is primarily designed for a Flash-like model, in which there’s a global framerate for everything. For greater timing control, or for complex animation cases, we’d recommend using Game Edition and the sprite-sheet feature.

    In addition to using texture memory much more efficiently (one big image rather than lots of little ones), that feature includes an animated-sprite API that lets you set different animation speeds for different sprites, or even for different sequences within the same sprite. Also, it’s a time-based API rather than frame-based, so the total animation time will remain the same even on slower devices that need to drop frames — the engine automatically handles all this under the hood.

  4. is there anyway we can know it finished it’s animation ? just like the “remove=true “, but i want it to call function when the given sequence is complete.

  5. @Chan, You should use the Sprite library instead of the Movieclip library because it gives you better control over the animations. You do have a onComplete listener with Sprites.

  6. Hello. Thanks for the example. Works great in the simulator for me but not on my Nexus One. No errors either. Is there a limit to how many images can be used for the movie clip? I currently have 36. Boggled on this one.

  7. @tareq – I got confused with LIME, as well. Ive been using the public code from corona forum area. focus on one step at a time. set a goal of what you want to accomplish and break it down into its simplest parts. display image1, move image1, display image2, test if image1 collides with image2, etc… build your program in increments. start small.

  8. Sorry, unless I mis-understood with the animation techniques, how would I “change” the speed of the animation, from going to one frame to the next? Like some of us on here, it is jumping to the next frame very rapidly! :( ..

    Hope someone can help me on this, I would be appieciated :) x

    SJC

    • Brent Sorrentino says:

      Hi Stephen,
      I think this “movieclip.lua” library has fallen out of use, for the most part… although you’re still free to use it, if you can make it work. Since it appears to just be animating “frames” of a movie, then yes, you could position the “movie” between other display objects or layers.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>