Hi,
I'm trying to create a set of "cartoon" blocks in BYOB to help students manage animations. The idea is to hide the logic for interrupting animations, so that students only have to invoke a new animation in order to kill the existing one.
The code below is invoked from a script that controls the movement of a car by polling the keyboard. Triggering a new "loop" animation automatically terminates any other animation(s) that may be running.
(Just discovered I can't post images as a new member, so here is the URL:
http://www.newlifeinteractive.com/images/Usage.jpg
This works... but most of the time a good second or two elapses before the animations switch, and sometimes two animations get stuck playing at once.
I'm using "atomic" blocks to do the flag-setting necessary to signal a switch in cartoons, to avoid race conditions; however, the behavior I'm seeing indicates that this code sequence is running in parallel with other invocations of itself, leading to what appear to be race conditions when keys are pressed and released quickly.
I've tried the "thread safe" and "turbo" settings in BYOB without any effect.
I'll show the relevant code for the looping cartoon block. Many thanks in advance to anyone who has a suggestion on how to make this work. My next approach will be to have a single cartoon framelist per sprite, which gets swapped out directly, and a single frame-switching loop per sprite, so that there will be no possibility of a conflict. However, this starts to expose the internals of the logic, which defeats my original purpose for creating these blocks.
In any case, here is the "loop cartoon" block. The first thing it does is call an "atomic" block (GB INTERNAL CARTOON LAUNCH) to switch off any currently running animatons. You can see by the way this block terminates its own loop how the interrupt signal is communicated between scripts.
http://www.newlifeinteractive.com/images/LoopBlock.jpg
And here is the implementation of the cryptic "internal launch" block:
http://www.newlifeinteractive.com/images/InternalLaunchBlock.jpg
(The insertion of the new "thread" record at the *beginning* of the list was just an odd experiment.)
And finally the (also atomic) "stop cartoons" block, which does the actual update to the data structure.
http://www.newlifeinteractive.com/images/StopCartoonsBlock.jpg
Any idea why the latter two blocks don't execute in one "call"? Are there any workarounds? Am I misunderstanding something?
Thanks,
alloplastic
Offline
I think you need the launch block:
when flag clicked
launch [thread - a]
launch [thread - b]
Offline
Thanks for the reply. I had forgotten about Run and Launch. I think I might be looking for the exact opposite, though, i.e. "Run this set of commands and don't let anyone else run them until they are done." Does something like that exist?
Run is similar to what I want, because it causes the current script to wait, but I don't think it prevents a second invocation from calling the same run command an instant later.
Offline
alloplastic wrote:
I think I might be looking for the exact opposite, though, i.e. "Run this set of commands and don't let anyone else run them until they are done." Does something like that exist?
You could perhaps use closures to create a sort of wrapper object for a script. (Check out the BYOB Manual for an idea of how to start using OOP in BYOB). The wrapper object would take the desired script (my_script, below) as input and would return a new script, one that only invokes my_script if it's not already running:
If you run this script, the second invocation should be ignored because there's one already in progress:
Last edited by fullmoon (2012-08-31 19:59:13)

Offline
Hi, all.
Thanks again for the responses. They took me down some interesting paths, and I've ended up with a workable solution.
The idea of using "Launch" let me push the details of the cartoon loop into the background, such that users only have to use the "play cartoon" block, and a "loop" gets spun up on a separate thread if one doesn't yet exist.
To solve the race condition, I simply relegated a sprite's cartoon state to a single record (a list) being run by a single animation loop per sprite. There is now no possibility for race conditions or double animations on a single sprite.
I have to admit to not fully exploring fullmoon's suggestion. However, the example prompted me to try using a *global" variable for the "running" state, and that still had the same problem. Very quick keypresses fell through the logic.
That might have just been my code, but I think even in the closure example there might be a race condition. At least, I'm walking away from this exercise thinking that BYOB scripts fundamentally should be thought of as independent threads, wherein context switches can occur between any two commands -- including between "if x == false" and "set x to true."
Offline