Repeat loop blues
April 27, 1998
by Pat McClellan
Dear Multimedia Handyman,
I keep reading on the ShockeR listserv that I should never use repeat loops in Shockwave movies. Why not? They seem to work ok. And if I can do repeat loops, then how else can I do repetitive things?
Pete
Dear Pete,
The reason that repeat loops are a problem in Shockwave is in the way that the processor handles them. They are extremely powerful because the computer devotes 100% of it's focus to executing the repeat loop until it is finished. This is the case whether we're talking about a projector or a shockwave movie. In the case of a projector, that's not generally a problem, but in a Shockwave movie, the computer may need to devote some of its attention to other things which might be going on at the same time.
For example, let's say that you've got a dcr in which you are accessing linked files or you have other net functions going on in the background. Those things will function well, until the movie encounters the repeat loop. At that point, all netLingo functions will be put on hold while you're repeat loop commands all of the processor's attention.
"Okay," you say, "my movie doesn't use any netLingo, nor linked members. So does that mean I can use a repeat loop?" Well, you've also got to consider the fact that during a repeat loop, the processor not only ignores events going on in the movie, but also outside the movie. For example, your browser's scroll functions won't work. And the browser's back button. And you can't enter a URL in the browser's location window. Generally, it's not a good thing to "trap" your user this way.
Now, I'm not an unreasonable purist. In fact, I do use repeat loops on occasion - a fact that I will freely admit as long as I'm writing under a pseudonym. I use repeats for fast, discreet operations such as cycling through a short list of items. But, I know there are other ways to accomplish this task, so let's examine some options.
The Iterative Approach
Let's imagine an example in which we need to cycle through 100 items in a list. We'll use a variable, i, to be the index moving through the list.The "old way" (using a repeat loop)
on cycleList global gOurList repeat with i = 1 to 100 set theItem = getAt(gOurList, i) do whatever with theItem endIn our "no repeats" option, we'll replace our index, i - a local variable - with a global variable, gIndex. This will allow us to "remember" where we are in the list so that we don't have to execute it all in one sweep. We'll also need a global "flag" to tell us whether to continue cycling through the list.
on cycleList2 global gOurList, gIndex, gCycleFlag if gCycleFlag = 1 then if gIndex <= 100 then set theItem = getAt(gOurList, gIndex) do whatever with theItem set gIndex = gIndex + 1 else set gCycleFlag = 0 end if end if endNow, the handler will only access one item in the list at a time. The global variable that serves as the index will allow us to know which item is next the next time we go through the handler. Our problem is that we need a way to repeatedly call this handler - whenever the processor is free to deal with it.
If you're not familiar with the *on idle* event, take a moment to read up on it in the Lingo Dictionary. Basically, an on idle handler executes every time that the processor has a "free" moment. This will be very helpful to us because the *on idle* event can happen many times per frame. Since the *on idle* event happens throughout our program, we need a switch so that it will only call the handler when it is supposed to. That's why I put in that gCycleFlag global variable. When gCycleFlag is 1, then the *on idle* handler will call the cycleList2 handler. When the cycleList2 handler has gone through all 100 items, then gCycleFlag gets set to 0 and the handler ceases being called.
on idle global gCycleFlag if gCycleFlag = 1 then cycleList2 endTo begin the process, all you need to do is set gCycleFlag to 1 and gIndex to 1.
Zav pointed out that using the idle handler has the drawback that it's not predictable. Specifically, the on idle event happens whenever other processing tasks have been completed and the computer is waiting. Therefore, faster computers will have many more opportunities to idle. An alternative to calling cycleList2 in an idle handler is to call it *on exitFrame*. Simply put the same code from our idle handler into your exitFrame scripts. This way, you know that the handler will be called at least once for each frame. This approach is good for doing things that need to be more predictable in timing, but it would be very slow for cycling through a list of 100 items.
The Escape Hatch
Jim Collins posted an approach on the listserv which allows for repeats, but puts in an "escape hatch" that allows user input to interrupt the repeat. Note that this would not prevent the repeat loop from stopping netLingo operations. However, if you're not doing any netLingo, then this approach WILL allow user input -- such as a click on the scroll bar - to get through.Jim's approach is to use *repeat while NOT the mouseDown*. This means that a mouseDown event would interrupt the repeat loop. You could also include the keyDown as an event which would interrupt the repeat.
on cycleList3 global gOurList set myIndex = 1 repeat while not the mouseDown set theItem = getAt(gOurList, myIndex) do whatever with theItem set myIndex = myIndex + 1 if myIndex > 100 then exit repeat end repeat endI hope those 2 options will help you avoid the pitfalls of repeat loops. If you're writing behaviors or objects, you can use properties to hold the indexes for your iterations. Good luck with your program.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.