Flash to Cinder – Timed Event Loops

This is the first tutorial in a series designed to help Flash developers transfer their skills to the C++ creative coding framework Cinder. I’ll provide links to sample code at the end of the post. There’s a lot to learn, so lets get started.

Timing events to happen in a repeating loop is a common technique used in games and applications. It’s commonly used in games when for instance, you want a missile to attack you’re hero every 2 seconds or in an application when you want to remind the user where to click if they haven’t touched anything in a few minutes. I recently used a timed event loop for an installation that required an image transition every 30 seconds.

Event Loops in AS3

In AS3, this is a pretty simple task. First set up your timer for 1 second (or 1000 milliseconds) and add the Timer event listener:

var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, onTimerTick);

Create your function, onTimerTick, which gets called each time an iteration of the loop completes:

function onTimerTick(event:TimerEvent){
	// Insert Magic here
}

Then just tell your timer it to start:

timer.start();

If you need to stop the loop, you simply just tell it to stop:

timer.stop();

That’s all there is to it.

Event Loops in Cinder

In Cinder, it’s not insanely more involved, but you have to know to use the TimeLine API that comes with Cinder release 0.8.4+. Instead of a Timer object, you store your timer as a CueRef object. CueRef is a reference to a Cue object which is part of the TimeLine API that’s specifically meant to stored events (or cues) that you want to call at a specific time.

To use, first declare an instance of your CueRef object (mCue) in the header and define it in Cinder’s default setup function:

mCue = timeline().add( bind(&CinderEventLoopApp::timerCalled, this), timeline().getCurrentTime() + 1 );

Translated into English, this would read as “Hey TimeLine, call the function timerCalled, but not just yet. Call it 1 second after the current time.” You may notice that the Timeline is expecting seconds unlike flash which expects milliseconds. This one line is essentially the same as when you initialize, add the event listener, and tell the timer to start in AS3, but without the looping.

By default, a CueRef object is set up to run once and then dispose of itself. So before you’re done, you have to make a few adjustments to mCue to get the loop going:

mCue->setDuration( 1 );
mCue->setAutoRemove( false );
mCue->setLoop();

setDuration() sets the gap between loop iterations to be 1 second, setAutoRemove() prevents the cue from being removed after it completes, and setLoop() makes it so that the mCue‘s function gets called repeatedly after however many seconds you pass in setDuration.

To stop your loop, toggle the looping setting to false:

mCue->setLoop( false );

To start it up again, toggle the looping setting to true again:

mCue->setLoop();

True is the default argument when nothing is passed.

You can see both the AS3 and Cinder code put to use in this gist example. Both versions do the exact same thing, moving a red box to random positions on the stage every 1 second. Thrilling, I know.

To use the AS3 version of the code, create a new AS3 project in Flash Pro (CS3+), copy the code from gist and paste into the actions panel on the first frame. For the Cinder code, create a new project using Cinder’s TinderBox, call the project “CinderEventLoop” and paste the gist code right into the default cpp file. Both should run immediately as is.

As you can see, this is a simple task with a simple solution in Cinder. Of course not all tasks translate this easily from AS3, though there are instances where the translation is even less convoluted in Cinder. There will be examples of both I’m sure as this series continues.

If you have any suggestions of things you want to learn to do in Cinder that you were accustomed to doing in Flash/AS3, let me know. Let’s makes this an easy transition and get all you flash guys and gals doing the amazing stuff that you do, doing that amazing stuff in Cinder.

Greg Kepler is an interactive developer at the Barbarian Group. He started as a design student graduating from RIT with a degree in New Media Design and Imaging in 2004 and fell in love with Flash. He worked for 4 years as a designer, developer, and interactive studio manager at Iomedia and moved on to the Barbarian Group in 2010 as an interactive developer where he tries to get his hands dirty with whatever technologies he can.

  • Vincent Houzé

    Hi, thanks for this tutorial, but I have an issue with Visual Studio 2010, the line
    mCue = timeline().add( bind(&CinderEventLoopApp::timerCalled, this), timeline().getCurrentTime() + 1 );compiles fine in debug mode, but crashes the compiler in release mode… Any idea ? Thanks a lot

  • GregKepler

    Hi Vincent, try replacing that line with these 2:

    std::function<void()> a = std::bind(&CinderEventLoopApp::timerCalled, this);mCue = timeline().add(a, timeline().getCurrentTime() + 1);

    This problem is discussed further in this post in the cinder forums http://forum.libcinder.org/topic/timeline-cue-with-bound-function-crashes-the-vc10-linker-in-release-mode-anyone-else-seen-this