release used resources in createjs - html

I have a Container with multiple Sprite and MovieClip objects displayed on the Stage, where all the sprites use a 3MB png SpriteSheet.
At some point I load another SpriteSheet in order to display a different Containerwhich uses it.
Along the process of trial and error, I've seen that setting the visible property of the Container isn't enough, so i used removeChild(), and also cache(), both of which helped a proper framerate.
The problem is that as I load more containers and spritesheets, the framerate occasionally gets very low.
Are there any other steps I should take in order to release used resources?
What are the common pitfalls?

Yes, I had quite a bit of performance problems myself, when I first started creating applications in createJS.
If your frame rate is lower than it should be, then make sure to cache every object that isn't created from a Bitmap, since those are not refreshed constantly and don't consume performance. For example, Shape type objects are refreshed constantly and are very performance intensive.
You should use the following pattern for the objects that don't have animated content:
var bounds = displayObject.nominalBounds;
displayObject.cache(bounds.x, bounds.y, bounds.width, bounds.height);
This will cache the object and make it consume almost no performance.
Also, when it is time to get rid of it, make sure to displose of the assets using something like:
//if it was added as a child of a container
displayObject.parent.removeChild(displayObject);
//if it was cached prior
displayObject.uncache();
//when you don't need it anymore, for garbage collection
displayObject = null;

Related

Reuse Instance Names for Different Objects

Simple question: how can I reuse instance names for different objects (obviously on different frames)? I really want to be able to use the same instance name for all my scenes, "ground", even though these ground instances are of different classes. I really don't want to have to go about naming them "ground0", "ground1", etc.I realize that there are ways around this, but I would hate to fool around with all that extra work. So that being said, how do I reuse the instance name "ground" without having this warning thrown at me?:
Menu, Layer 'ground', Frame 1 Warning: The instance name 'ground' is declared on an object of type Ground but there is a conflicting use of the instance name 'ground' on an object of type Ground2.
And by the way, I realize that an instance is supposed to be an occurrence of a specific object, but to be honest I don't quite see the point in not being allowed to reuse instance names when appropriate. Any help would be much appreciated.
If I recall how finicky Flash was, it may have something to do with how you created the "ground" instance on those frames.
By that, I mean:
Did you create one instance first, and then created new keyframes afterwards (meaning: the same instance would be used in all keyframes), or...
Did you begin by creating your empty keyframes first, and then drag-dropping / pasting one "ground" instance in each frames? (meaning: in this case, it would likely be treated as 3 separate instances).
I'm not sure if this assumption is correct, but Flash doesn't necessarily tie instances to layers, as in "Oh, ground is on Layer 1, therefore every frames should reuse the same instance...". In a perfect world, I agree this would make sense. But from the early versions of Flash when it was mostly targeted to animators, where anything goes (from having multiple shapes and instances on the same frame, from re-arranging the depth of groups / instances on one frame/layer), it's still making the assumption that if you drag / copy an item from the library to the stage, it doesn't necessarily mean they are the same instance. Instead, you have to babysit Flash by creating more keyframes (or tween keyframes depending on your need) after the frame with the existing asset instance you want to reuse.
Again, the above is an assumption based on my experience - but if you did enter the "ground" instance-name manually for each instances found on each frames, chances are you previously copy/pasted or dragged new instances to those frames.
Does it sound like something you may have done?
EDIT:
If you have "ground" assets across a few frames, which are instances of different Symbols, then that definitely would trigger those Warnings you've been getting. I'm not sure where you can turn those off (Preferences? Project Publish settings? Advanced AS3 settings maybe?).. but regardless, here's a way that may work for you, programmatically.
Since each frames have a unique instance, with each instances named "ground", you could create a helper function to work like the .getChildByName("ground") method (and to be honest, I'm not sure if that method would work right-off the bat, you could try). You would need to for-loop through the given MovieClip's children (In your Menu's children, in your case I believe?), and check if(child.name==theNameInQuestion) return child;.
That being said, I can't guarantee this is THE proper solution (didn't test), as I don't know how you're navigating the frames at runtime (play/stop/gotoAndPlay/gotoAndStop/etc), and that may affect which "ground" instance is available at a given time. Internally, Flash does addChild/removeChild to swap out those various "ground" instances as it cycles through the frames, it's not a simple visible=true/false toggle (AFAIK).
EDIT 2:
This could be what you need?
If any programming language if you want to reuse instance name variables you simply type them with the top most superclass type. In your case that would be:
var ground:DisplayObject;
ground = new Ground!();
ground = new Ground2();
//etc ....
Edit: If using property panel you can't use the same name for 2 objects as there will be no way to differentiate between them. So an error will be correctly thrown.
Now if you want to use in code only one name same principle as shown above applies:
var ground:DisplayObject;
ground = ground0;
ground = ground1;
//etc ....
Then you can safely use in code the variable ground.

Loader method unloadAndStop() behaviour

Had some issues using the loader and I feel I need to totally understand how the unloadAndStop() method works. I'm working on a project that loads in multiple swfs when required at runtime. For this I've been using a single loader and pulling out its contents to a cache when it's complete.
The single loader is implemented via an extended class that I haven't written, and it seems to implement the "unloadAndStop(true) method when loading in a new URLRequest.
Now, I've had some strange issues using this system, and I've traced it back to the unloadAndStop(true) call, which according to the Adobe documentation stops audio, playback, and flags for removal by the garbage collector. Obviously this isn't what I want; I still have references to this object on the stage and in my cache! It seems strange to me that there's a way to flag something directly for garbage collection in this manner, where, as far as I know, there's no other way to do that.
So that causes me to assume that in order to properly remove something loaded with a loader you have to unload it in the manner. Is this the case? If I load something in, pull out its contents to movieClip1, load in a new movieClip, and then remove all references to movieClip1 (the original Loader contents) will that be garbage collected, or does it have to be removed via the unloadAndStop method?
TL;DR:
Is it necessary to call unloadAndStop(true) from a loader to guarentee anything it has loaded gets removed from memory, or can the loader load another URLRequest without fear of a memory leak?
It's well described in the docs:
gc:Boolean (default = true) — Provides a hint to the garbage collector to run on the child SWF objects (true) or not (false). If you are unloading many objects asynchronously, setting the gc paramter to false might improve application performance. However, if the parameter is set to false, media and display objects of the child SWF file might persist in memory after running the unloadAndStop() command.
It's because you can have some SWF, get some specific child, and remove the SWF. But you keep reference to it's child, which means that the child won't be garbage collected. But if you force GC to check children, it will try to mark all of them for collection, and leave the ones that are used.
So basically, there is no need to force GC in order to clean things out. The best and most important practice is to remove everything from Stage, and clean all references to it. It will sooner or later going to be checked by GC. unloadAndStop is a shortcut for someone that doesn't keep track on what he's doing and just a safety measure to be sure that you've cleaned as much as you can.
I personally don't use it.

Invalid BitmapData

So, I'm porting a game, build for web flash in AIR Mobile (using FlashDevelop). Now, I have one class that runs first, which make vector graphic in bitmaps and re-size them as needed. Than, all this bitmaps (actually, BitmapData) are stored in Vectors. This class is a object of a Singelton class, which allows me easy access to the stored BimapData.
Also, I'm using FlashPunk as the game engine.
Now, I already created around 16 BitmapData and stored them in that class and everything is fine. But, the next BitmapData I add, in new Vector object, is not working as it should. Everything is fine while in RenderScreen, but as soon the game starts, e.g. click start game, it should return the BitmapData to create the menu, but it reports "ArgumentError: Error #2015: Invalid BitmapData"
What might be the problem? The BitmapData in question is created from vector graphic using draw(), scaled as needed, with initial width 1024px and height 120px. Also, the game run with around 40Mb memory, so the size is not the problem ...
Any idea why this error shows?
EDIT: I founded the problem and resolve it. How to close this question?
I'd bet my hat that it's a memory problem... error 2015 is either because one of the dimensions are invalid (width or height < 1 ), or because there is not enough memory to create the BitmapData.
The System class has a few properties that might help you debug the state of the memory before you try to create the conflicted BitmapData ;)
And if you find that it is actually a memory problem, besides wearing a new hat, you will have to rethink the way you cache those sprites... try to cache only the necessary pieces for each stage of the application, dispose them before you need to create more, etc. Good luck!

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.