Let's talk about 'while' loops. First, let me say that they are pretty awesome. For serious. A while loop basically says 'while condition A is true, do statement B...as fast as freakin' possible.' However, due to the single minded nature of an LSL script (and several other types as well), while a while loop is being executed, there's not a whole lot that particular script can do...so they can be a bit hard to stop arbitrarily. Other events that would be triggered wait until after the while loop is done doing its thing. Meaning, you can't just stop them on a timer, or a listen event, or whatever...you likely have to involve child scripts at this point. But, due to what I just said, you can start a while loop off on a link message (the popular method for communicating between scripts in the same prim) but you can't stop it with them. So, what do you do if you want your while loop to run until receiving an outside signal rather than a preset condition evaluating as false on its own (that's basically what 'for' loops are for...lame). Well, its pretty simple, you just have to use a somewhat unconventional 'choke' parameter. For instance, say I have a pusher script. In case you didn't know, push is pretty nasty when set on a while loop, it happens so rapidly it will send targets flying. Well, I want to start and stop pushing on a chat command, for perhaps a force field effect (works great for this btw). My listen event can trigger it easily enough but it is utterly unable to stop once it has begun pushing. So, I take my 'pushing' part of the script, and move it to a child script, dedicated to the purpose. The main script listens for the 'go' command, and sends a link message to the pusher script when it hears it. The while loop starts up, and looks something like this:
while(llGetColor(0) != <1,0,0>)
llPushObject(gTarget,gDirection,ZERO_VECTOR,FALSE);
As you can see, the condition for the while loop to keep executing depends on face 0 of the prim the script is in being not-red. Therefore, if my main script hears me give the cutoff command, all it has to do is change ol' face 0 to red and...voila, the pusher stops pushing. Probably immediately afterward in the pusher script I will have the face turned back to not-red. Using this method, we don't have to raise any events which wouldn't get triggered anyways, we simply rely on an arbitrary parameter that can be easily manipulated by the main script. You can use prim color, size, description, anything you want really...its terribly simple; it just takes a little thinking outside the box. Doing so puts the full power of the awesome while loop in your hands (timer-based events can't even come close to the speed of repetition here). Before we conclude, let's take a look at another while-based effect:
integer info = llGetAgentInfo(llGetOwner);
while(info & AGENT_IN_AIR)
info = llGetAgentInfo(llGetOwner);//remember that only this line will execute if unless a scope is declared with { and }
llOwnerSay("landed");
In this example we have a bit of code that presumably would be triggered while the owner is in the air (jumping, falling, etc). The loop will execute as long as the avatar is detected as being IN_AIR, and immediately stop when this ceases to be...continuing on with the code in a nice fashion that doesn't require timers or anything like that. I use logic like this in a double-jump effect where I like to restrict the times you can double-jump to once per in-air session. Another similar application I use this for is spouting off particles when the avatar is detected as typing, and idling until immediately stopping when finished (for chat poofers and the like). Timers can only check conditions so fast and splitting your code into more and unnecessary events might not always be desirable; this is a good way to keep things simple and accurate. So, if you aren't already using while loops to your advantage, I strongly suggest you do so. I hope this article has enlightened you to the power available to those who can harness it. Enjoy!
~Ark
No comments:
Post a Comment