Infinite Loops (Action Script 3) - actionscript-3

I'm new to Flash Actionscript because my programming class uses it. I normally use C++ (or a variant of it) and have dabbled in Java, so Actionscript was mostly familiar to me.
However, whenever I use a while loop, AS3 crashes after 15 seconds. I need to use a while loop otherwise the scope of the entire code will end and the game will stop running on code I presume. In my normal programming language, while (true) will hang the game unless I have Waitframe(); somewhere in the code to let it progress a frame. But I search, and Actionscript has no such thing, and all I've found are "Infinite loops are the devil aaaaaaaa".
Soooo, how am I supposed to be able to make a game with this? I want my game to last more than 15 seconds, yet AS3 "helpfully" terminates the script should it "hang", despite me doing stuff (although that stuff doesn't really show up at all, presumably because the script hangs). Did I miss a wait function that allows for prolonged while loop usage, or am I doing it wrong?

Unlike C/C++ environment, Flash Player (which initially was much less into the script and much more into animation) is not a real-time environment and works in phases, often referred to as frames (a basic Flash Player cycle consists of advancing the playhead to the next frame of any present timeline/MovieClip).
So, each phase goes in two steps:
Script execution.
Rendering the stage.
So, if you want to control something so that user sees as smoothly animated, you need to run a script every frame. Lets say, you have a box you want to move smoothly to the right.
var Box:DisplayObject;
addEventListener(Event.ENTER_FRAME, onFrame);
function onFrame(e:Event):void
{
Box.x++;
}
Normally, Flash Players tries to keep the FPS as close to the settings as it is possible. However, if your scripts (which is a handlers for various events, not only ENTER_FRAME, but also keyboard events, mouse/touch input, network events, etc.) run for too long and/or rendering is too heavy, Flash Player will not be able to keep FPS right.
That's also why there's a limit on script execution phase, set to 15 seconds by default. Flash Player suggests to abort the script running for too long as possibly malfunctional.
Then, the solution to your problem depends on what you are trying to do there, but in any case you must finish things and let Flash Player to proceed in order for your app to function normally.

Flash works on a "Frame" system, essentially a timer by frame rate.
Put all your game code in a new function and call that function using an event listener.
stage.addEventListener(Event.ENTER_FRAME, function(e:Event):void {
// Your code here
// Called every frame
});

Another point, is that you don't want a truly infinite loop. In general, you want a conditional situation, so that the user can exit. In C, you'd do:
extern quit;
void init()
{
quit = 0;
}
//inside main()
while(!quit)
{
//game functions
//advance_frame();
}
You would break that loop if the player tries to exit, dies, or wins the game, with each having a unique value, such as quit == 1 for normal exit, == 2 for death, and == 3 for winnig; then a different loop (inside main) for each of those.
Infinite loops are in general, rare, and should be used with extreme care. Usually you would want a statement that causes them to exit, in any case.
Even in C, you need to advance the frame manually. Only game-based scripting languages tend to 'automate' this somehow, and Macromedia Flash was never designed with the intent of powering a game engine.
Is game design in Flash truly being taught at University now?! If so, that's horrible.

Related

AS3 Tween Freezes

I started using AS3's Tween function but noticed some strange behavior every once in awhile. Basically, it freezes before it finishes the tween.
This website seems to offer the solution:
http://www.rgbeffects.com/blog/actionscript/tween-freeze-frustrations-avoid-actionscript-tweens-stalling-out/
My program requires that the rotation tween works precisely every time. I like to use the functions adobe put in place but this makes me nervous since it has such a big issue.
Should I be using AS3's tween or some external tween like greensock.com's TweenLite?
Which would be more reliable?
Most likely your tween instance is being prematurely garbage-collected, because you don't store a reference to it somewhere. This is a common mistake which you can easily Google for.
Solution: store a reference to Tween instance while it is performing animation to save it from GC.
Follow the link for detailed explanation: AS3 Garbage Collection, the reason your tweens are ending early.
Official article on adobe.com also mention this problem (see note at the bottom of article):
Note: Consider variable scope when using the Tween class. If a tween is created in a function, it is important that the variable's scope exists beyond the function itself. If a tween is stored to a variable of local scope, ActionScript garbage collection removes the tween as the function completes, which will likely be before the tween has even begun.
And here are some links on garbage collecting if you would like to learn more on GC logics.

How should I substitute an image in a larger animation using AS3?

We're making a Flash browser game with a few reasonably complex animations. Our designer is making the animations in Flash Professional while I'm wiring everything up and adding some logic through AS3 (using FlashDevelop).
In one of our more complex animations a "bonus item" moves around the screen. It tweens hither and tither, there special effects and as such, it disappears for a few frames and then reappears later.
From AS3 we want to be able to dynamically decide which bonus item (say a mushroom or a star) to include in the animation. We don't want to have to ask our designer to replicate the entire animation for each of our bonus items.
This is what we've tried:
Created a two frame (1 mushroom frame, 1 star frame) "BonusItem" movieclip in FlashPro and Exported for ActionScript.
Created the complex animation movieclip in FlashPro and added the BonusItem movieclip to the relevant frames. Gave the BonusItem instance an instance name on all necessary KeyFrames. Exported entire movieclip for ActionScript (exported as "ComplexAnimation").
Intention:
The intention was to be able to do this:
var complexAnimation:ComplexAnimation = new ComplexAnimation();
complexAnimation.bonusItem.gotoAndStop("star"); // Frame labels have been added in FlashPRo.
this.addChild(complexAnimation);
This would play the complex animation with the star and we could easily call gotoAndStop("mushroom") to play the same animation with the mushroom.
Problems:
The first problem was that complexAnimation.bonusItem was null on line 02 above. I solved this by handling ADDED_TO_STAGE for complexAnimation and putting line 02 above in the handler.
The next problem was that each time the bonusItem movieclip started tweening, or if it was not present in some frames and was subsequently re-added the complexAnimation.bonusItem attribute/reference was reassigned to a new bonusItem instance. I then had to find a way to know when this was happening and call gotoAndStop("star") on the new instance.
I've found two ways to do this:
1) Listen for ADDED events on complexAnimation with a target.name of "bonusItem". It's a bit crap in a strongly typed language to have to resort to matching strings, but this works. Btw, when the ADDED event is fired new frame object references are still null.
2) Listen for FRAME_CREATED events. This happens later than ADDED at a point where new frame references have been initialized. As such I can check if complexAnimation.bonusItem is non-null at then call gotoAndStop("star") on it. One problem with this is that calling gotoAndStop actually triggers another FRAME_CREATED event to fire, so I need to guard against infinite looping. Again, it works but I don't have a great feeling about it.
Conclusion:
Well I don't really have a conclusion other than I feel like I'm working really hard to do something relatively simple. I'm hoping there's an easier & more robust approach. I have a strong feeling that I'm going crazy. Anyone know a better way to do this?
If you have an object that exists on a timeline and it has an instance name, and you need to be able to maintain a reference to it through the duration of the timeline, then it must exist on every frame (and in the same layer!) of the movieclip. I grant you, your workarounds get the job done but you have already experienced the pain involved in doing so.
The path of least resistance is to just have the object exist at all times. If the user shouldn't "see" it, just hide it offscreen somewhere. Just make sure it always exists, contiguously, on that timeline layer from frame 1 all the way to the final frame.
The other thing I'd suggest is to stop deeply nesting movieclips in the hopes of using those nested clips as state representations. This is one of the things that sadly was very easy to do in the AS2 days, but has been rendered impractical to the point of madness in AS3. Anything deeper than 1 layer is getting into some dicey territory. 3 layers deep and you need to rethink your strategy. Perhaps instantiating different movieclip instances from the library and adding/removing dynamically instead of relying on frames.
I thought I'd update this post with our current (and hopefully long-term) solution.
First of all, I made an error in the above post:
The next problem was that each time the bonusItem movieclip started tweening ... the complexAnimation.bonusItem attribute/reference was reassigned to a new bonusItem instance.
This was incorrect. Flash was indeed assigning a new instance of BonusItem, but it was caused by a Mask layer keyframe rather than the tween.
I had been keen to try to avoid having any logic which relied on string comparisons, but in the end I swallowed my pride to make life easier.
Our designer gives all relevant objects (stuff that we'll need to access from AS3) instance names on each keyframe in the timeline. If the object is nested within other objects our designer must assign those parent objects instance names too. We must coordinate those instance names so that dev know what the accessors are called - we would've had to do all this anyway. Our designer also still has to "Export For Actionscript" a class for each relevant movieclip (e.g. BonusItem).
In AS3 we're using Robotlegs for dependency injection and as the basis of our MVC framework. Robotlegs suggests that application-specific logic should be separated from view-specific logic. It allows us to specify a logic class (called a Mediator) to be associated with each and any of our views. As such we can do the following mapping:
BonusItem -> BonusItemMediator
This means that every time Flash creates a BonusItem on the timeline Robotlegs somehow knows about it and creates a new instance of BonusItemMediator (which we write ourselves and have full control over). In addition, Robotlegs can easily give us a reference from our BonusItemMediator to its associated view instance (the BonusItem instance). So inside my BonusItemMediator I can ask the view reference what its instance name is. I also walk up its parents to the stage and record each of their names to generate a resultant string of instance names that uniquely specified this instance of the BonusItem.
e.g.
"game.complexAnimation.bonusItem"
Once I know this I can ensure that the bonusItem is showing the correct image (star or mushroom) with the following code:
var frameLabelName:String myGameModel.whatTheHellShouldThisBeShowing("game.complexAnimation.bonusItem");
this.view.gotoAndStop(frameLabelName); // where view is the BonusItem instance
So now regardless of how or when Flash seemingly randomly decides to destroy and recreate my bonusItem I'll hear about it and can ensure that that new BonusItem instance is displaying on the correct frame.
The main weakness with this solution is that we're relying on string comparisons. Our designer could easily mistype an instance name and we wouldn't hear about it until that code was hit at runtime. Of course tests mitigate that risk, but I still feel that it's a shame that I'm using a strongly typed language, but then not making use of the compile time type checking.

Game programming without a main loop

My professor gave my class an assignment today based on object oriented programming in Pygame. Basically he has said that the game that we are to create will be void of a main game loop. While I believe that it is possible to do this (and this question has stated that it is possible) I don't believe that this is required for adherence to the Object Oriented paradigm.
In a diagram that the professor gave, he showed the game initializing and as the objects were instantiated the control flow of the program would be distributed among the objects.
Basically I believe it would be possible to implement a game this way, but it would not be an ideal way nor is it required for Object Oriented adherence. Any thoughts?
EDIT: We are creating an asteroids clone, which I believe further complicates things due to the fact that it is a real time action game.
Turn based games or anything event driven would be the route to go. In other words, take desktop GUI apps. They'll just tick (wait) over until an event is fired. The same could be done for a simple game. Take Checkers for example. Looping each game cycle would be overkill. 90% of the time the game will be static. Using some form of events (the observer design pattern would be nice here) would provide a much better solution. You're using Pygame, so there may be support for this built in, through due to my limited use I cannot comment fully. Either way, the general principles are the same.
All in all it's a pretty rubbish assignment if you ask me. If it's to teach you event driven programming, a simple GUI application would be better. Even the simplest of games us a basic game loop, which can adhere to OO principles.
Hmm. In the general case, I think this idea is probably hokum. SDL (upon which PyGame is implemented), provides information to the program via an event queue, and consuming that queue requires some sort of repeatedly checking the queue for events, processing them, and waiting until the next event arrives.
There are some particular exceptions to this, though. You can poll the mouse and keyboard for their state without accessing the event queue. The problem with that is it still requires something like a loop, so that it happens over and over again until the game exits.
You could use pygame.time to wait on a timer instead of waiting on the event queue, and then pass control to the game objects which poll the mouse and keyboard as per above, but you are still 'looping', but bound by a timer instead of the event queue.
Instead of focusing on eliminating a main loop, how about instead think about using it in an object oriented way.
For instance, you could require a 'root' object, which actually has its own event loop, but instead of performing any action based on the incoming events, it calls a handler on several child objects. For instance when the root object recieves a pygame.event.MOUSEBUTTONDOWN event, it could search through it's children for a 'rect' attribute and determine if the event.pos attribute is inside that rect. if it is it can call a hypothetical onClick method on that child object.
I think it might qualify as event driven programming? Which can still be object oriented. You see this in Flash a lot.
There's a difference between a main loop in a main class. You can still have a game class initialize all of your objects, and then rely on inputs to move the game onward.
Kinda hard to say exactly without knowing the exact parameters of your assignment, the devil is in the details.
You might look at how python utilizes signals. A decent example I found is at: http://docs.python.org/library/signal.html

Garbage collection - manually wiping EVERYTHING!

I have been building a game for a while (nearly done) - But the game needs a replay button and its a big task.
I know the GC is dreadful in flash, but I wanted to know if there is a way to wipe EVERYTHING as if the flash app has just begun. Clearing memory, game data - I haven't to worry about game loading as its not really heavy on data.
Everything pretty much lives in a DataModel - but I fear if I just clear the all variables, I'll have pockets of orphaned memory.
Any forwarding idea would be great.
cheers guys.
I would do this:
make a class that encapsulates your entire game, called GameContainer or whatever.
Do a search on all your source code, and make sure that in every call to addEventListener, you are passing true for the "use weak references" argument.
In your document class (or frame script), make a single instance of GameContainer and add it to the stage, and do nothing else.
Now when you want to entirely clear your game from memory, remove GameContainer from the stage and null the reference. Memory will not immediately be released, but everything in your game will now be eligible for release. If Flash thinks it needs more memory it will trigger a GC, and the large orphaned GameContainer will be nuked. (Step 2 above will keep your event listeners from counting as references to your objects, and make sure that all self-contained objects are eligible for disposal.
Not sure what you mean about Flash's GC being dreadful though. I can't recall having heard of any bugs in it. It won't nuke your objects unless you are careful with your references, but that's true of all garbage collection.
Not short of refreshing the page. There might be some hack you could do by loading a separate swf and then unloading it, but that would be just as error prone as doing it the proper way.
My advice would be to just buckle down and write your reset function then get something to monitor memory and make sure it works by reiniting/resetting a bunch of times.
The problem with Flash's garbage collector is that as far as I know you cannot FORCE it to "collect". I had this issue with a program in which I would load in various external SWF's, and occasionally Flash would simply not load them. What you may need to do is make a function to set every major variable in your code to null at the end of a game, if you want a true reset.
There is still no guarantee, but unfortunately I'm fairly certain there is no shortcut to force a memory release.
(For me this meant also making sure my event handlers were cleared properly, and my loaders would "unload()" after passing their content off, in the case of my external SWF loader.)

FLVPlayback component memory issues

My website is entirely flash based, it moves around a 3D model which was given to me as chunks of video that I've converted to FLV files. I'm using the FLVPlayback component to control the video inside of my program. While running memory checks using System.totalMemory I've noticed that whenever a video is loaded, it will eat up a chunk of memory and even when I remove all the event listeners from it(they are all weakly referenced), remove the component from its parent, stop the video and null the component instance, it still will not give that memory back.
This has been bothering me since I started working on this project because of the huge amount of video a user can potentially instantiate and load. Currently every video is loaded into a new FLVPlayback instance whenever it is required, but I have read that perhaps the best way to go about this problem is to simply have a global FLVPlayback instance and just reload the new video into the old instance, that way there would only be one FLVPlayback component in the application's memory.
Has anyone else run into this problem as well? Have you found a better solution than using a global instance that you just re-use for every new video?
I've never really liked the components, they're a bit dodgy. This particular problem seems to be common, and the somewhat annoying solution is, as you're suggesting, to only have one FLVPlayback and reuse that.
Here's a blog post about it
You can't help the memory problems much until Flash adds destructors and explicit object deletion, unfortunately. See this thread:
Unloading a ByteArray in Actionscript 3
There's a limit to how much memory Flash applets can use; the GC seems to fire upon reaching that limit. I've seen my memory-easy applets use as much as ~200MB, just because they run for hours on end and the GC doesn't want to kick in.
Oh, and I don't think using a single instance is an elegant solution, either. Currently I just write a dispose() function for my custom classes, waiting for some day when it can be turned into a proper destructor.
From what I gather after a lot of testing is that flash dynamically loads in libraries and components as needed but never garbage collects that data. For instance, if I have a website or an Air app that uses the FLVPlayback component, the actual component and libraries associated with it aren't loaded until a new FLVPlayback() instance is created. It will then load in the library and component into memory but you will never get that space back until the program / website is closed. That specific instance with the video inside of it will get garbage collected and release some memory as long as you remove listeners from it, take it off the stage, and set it to null.
Also, if you are doing individual videos, the VideoPlayer is much lighter weight, and cleans up nicer.
Thanks for the responses, the links to the other blog questions were helpful as well, I had read all of Grant Skinner's info on garbage collection too, but searching through those links and going back and re-reading what he had originally said about GC helped refresh the old noggin. In addition to nulling and re-instantiating that single FLVPlayback component, I also realized that I wasn't correctly unloading and destroying my Loader instances either, so I got them cleaned up and now the program is running much more efficiently. I would say the memory usage has improved by around 90% for the site.
#aib I will admit the single instance solution isn't elegant, but because flash just won't let go of those FLV files, I'm kind of stuck with it.
#grapefrukt I detest the flash components, they typically cause more grief than time saved, however in this case I had a lot of cue points and navigation stuff going on with the video files and the FLVPlayback component was the best solution I found. Of course I'm still fairly new to the ActionScript world so perhaps I over-looked something.
Unfortuantely, thats just the way flash handles it. Not particularly smart, but it works for most people.