i'm curious about something. Let say we have 30 object in the code, and every object should be animated trough enter frame event. Which will be faster(in terms of memory execution) : to have just one event listener in the main object (for example) and to call object methods, or, to have separate event listener for every object?
Thanks :) .
UPDATE: Well, actually, i need to monitor each object to find out when that object is on current frame, e.g. on end of animation, and than remove it from display list. What is the best way to that?
For 30 objects, this doesn't really matter. Actually, in general it matters only little, since the bottleneck will always be rendering.
But to answer your question: Listeners are slow. For one notification to happen, an Event object needs to be created (allocation is generally quite expensive), and an untyped call of an anonymous function or a method closure needs to be done (which is signifficantly slower than calling a method on a strictly typed value).
You should try to use tweens instead of animating via ENTER FRAME event.
Animating on ENTER FRAME will cause tremendous lag, especially if you have lots of objects.
Checkout TweenLite: http://www.greensock.com/tweenlite/
Definitely to have just one event listener. The less listeners, the faster.
As a rule of thumb, one listener is better, and will induce a more predictible behaviour.
That being said, it depends pretty heavily on what you're trying to do. You might not have to animate every object on every enter frame event, thus gaining performance further.
Related
I have a question how can I clear/free memory in flash? For example I am finishing game and I want to start from beginning and if I will just jump to the first frame all the objects there are still in this memory, is any possibility to force cleaning memory?
Can I free memory for an object? for example I removeChild(something) - and I want to free memory for an object as I will reuse it?
Can anybody explain me how the engine works?
Thanks
I would encourage you to read Chapter 14, Garbage Collection in the "Moock Book" (Essential ActionScript 3.0 by O'Reilly Publishing).
The short answer to your question is that you're not in control of de-allocation, the garbage collector is. In a garbage-collected language like AS3 or Java, you don't have manual control over allocation and de-allocation of memory like you do in lower level languages; there are no AS3 equivalents to things like delete in C++ or free in C. Your goal should not be controlling when you destroy things, but rather not forgetting to remove references to things you no longer need around and making sure you disable things that you intend for garbage collection.
Memory leaks in AS3 typically come from a mixture of newbie misunderstanding (like thinking removeChild or setting a reference to null destroys objects), and from not keeping good track of references to objects--especially where strong listeners are involved.
A previous respondent posted this:
myObject = null;
What this does is remove a reference to the object that the variable myObject was holding. Nothing more. You need to know a lot more about the situation in order to be able to say whether this assignment even makes the object in question eligible for garbage collection, especially how many other variable are holding references to the object. And the object might already be eligible for garbage collection even if you didn't set the reference to null (i.e. if myObject has no connection to a GC root).
Suffice to say, the entire GC mechanism is more complex than can be satisfactorily explained in a StackOverflow post. That's why it has a whole chapter in the Moock Book, and even that book does not go into implemenation detail or great detail about when exactly the Flash Player does its ref counting deletions or mark and sweep passes.
The most important things to remember are, IMHO:
When you intend to "kill" an object, give it a cleanUp() or destroy() function where you do things like stop all its timers, sounds, remove listeners, etc. An object will continue to exist and execute code until it gets GC'd. And the Flash Player defers GC as long as it can--it's usually triggered when the Player needs to allocate more RAM from your system, because allocating memory is about the only thing that's more time consuming than doing the mark and sweep GC pass.
Read about weak vs strong listeners. Basically, when you have a weak listener, the listener reference is one that is ignored by mark-and-sweep GC, so it alone will not prevent an object from getting collected. But don't listen to anyone who tells you "always use weak" or "always use strong listeners and manually remove them" because there are times where each is appropriate, and that's why the choice is yours.
removeChild() will remove object from stage, but will still keep it in memory. You will have to null the object like this myObject = null if you wish to get rid of it entirely. You might not need to do that thought. Just removing it from stage and removing all associated events will be sufficient in most cases.
Clearing memory is a tricky thing with Flash, the proper way ow implementing it setting up objects properly in the first play for easy clearing, rather than forcing deletion. When you want to remove an object from memory, you do it by removing any reference to it, and then flash marks it for garbage collection. Then Flash at a later point removes the object from memory.
In order for the object to be ready for data collection it cannot have any connection to another object.
so if you have an object that has a single connection to a MovieClip and the movie clip has no other relation, then if you set it to null, you will remove it.
if you, however, have two objects that point to it, if you remove one link by setting it to null, the MovieClip will not be removed.
furhtermore, if you have a 2 or more movie clips that have a network of connections, removing those objects requires these connections be broken as-well. For example if you have a level with many characters and listeners set up, removing the lavel movieClip will not clear it.
one way of breaking these connections is adding onRemovedFromStage Events, that remove further children, listeners and objects. I've started using the casaLib extension of movieclip - CasaMovieClip, that has a function called removeChildrenAndDestroy. this makes it a bit easier, but would take a while to implement on an older project.
Anyhow, you'll find there are many sites discussing this, a good place to start is grant skinner's blog
recently, i ran into a problem where i needed to access the List object from the List's custom cell renderer class.
there were 2 options:
listen for and dispatch a custom event to communicate between the 2 classes.
reference the List from the cell renderer class with the parent property: List(parent.parent.parent)
while it's much easier to choose the second option, i feel that dispatching and listening for a custom event would result in code that's more inline with the design of AVM2, offers greater control for communication and, as it's expected AS3, should be less difficult to debug or maintain within new hands.
however, i also feel that using an event is more expensive, requires attention to resource management perhaps making it more difficult to debug and maintain and could be generally overkill.
is this simply a matter of needs or taste? should dispatching/listening for custom events be avoided if they can be?
Don't forget that you can't see the control flow of event listeners from single glances at the code.
While I'm not against event listeners completely, if you use them, you should try to use them in the most self-documenting and simple way possible. If you have clever stuff, like adding/removing event listeners, and it goes wrong, then it can be a nightmare to debug because you cannot see what dispatchEvent is going to do.
If owner gets you the right object, then I would just go with that, myself.
I would look at it from another angle. If the other option ends up creating more dependency between the two classes, I would definitely opt for event dispatching.
In that regard , I'm not sure why you think that an event driven application would be harder to debug & maintain. It would seem to be the opposite, but it would of course depends on how one implements the event dispatching in the application. But saying this and re-reading your question I realize you seem to contradict yourself! Of course , I tend to agree with the first statement.
...offers greater control for communication and, as it's expected AS3,
should be less difficult to debug or maintain...
...perhaps making it more difficult to debug and maintain and
could be generally overkill.
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
So, I've been toying around with Flash, browsing through the documentation, and all that, and noticed that the ENTER_FRAME event seems to defy my expectation of a deterministic universe.
Take the following example:
(new MovieClip()).addEventListener(Event.ENTER_FRAME,
function(ev) {trace("Test");});
Notice this anonymous MovieClip is not added to the display hierarchy, and any reference to it is immediately lost.
It will actually print "Test" once a frame until it is garbage collected. How insane is that? The behavior of this is actually determined by when the garbage collector feels like coming around in all its unpredictable insanity! Is there a better way to create intermittent failures? Seriously.
My two theories are that either the DisplayObject class stores weak references to all its instances for the purpose of dispatching ENTER_FRAME events, or, and much wilder, the Flash player actually scans the heap each frame looking for ENTER_FRAME listeners to pull on.
Can any hardened Actionscript developer clue me in on how this works? (And maybe a why - the - f**k they thought this was a good idea?)
Short answer: you get what you ask for.
The fact that your MovieClip is "anonymous", as you call it, doesn't change how garbage collection works.
Both of your theories are wrong. It's simpler. You asked your MovieClip instance to notify you whenever a frame is entered. Quote from the docs:
Dispatched when the playhead is
entering a new frame. If the playhead
is not moving, or if there is only one
frame, this event is dispatched
continuously in conjunction with the
frame rate. This event is dispatched
simultaneously to all display objects
listenting for this event.
And this is what is happening.
Objects such as MovieClips are heap allocated. If you store a reference to it in a local variable, the reference lives in the stack and will get out of scope when you return from your function. You'll have no way to refer to the object, but the object will still be alive, in the heap. So, whether you store a reference to the mc instance or not, that doesn't change this basic fact of how heap and garbage collection works.
Now, since the are no strong refs to this object, this object is elligible for collection. This does not mean it will be collected when the function returns.
Since the object is still alive, it will continue to dispatch the event, because you asked for it. Once it's collected, naturally, your code in the handler will no longer be executed.
Edit
I said that both of your theories are wrong. I think that's the case from an Actionscript perspective. However, at the player level, it seems evident that the player has to keep track of objects on which it must fire certain events, so yes, it must be storing an internal reference to said objects. This is no different to how it works for other objects that are globally handled by the player, though, such as for instance, loaders. There's one exception to this that I'm aware of: running Timers. As long as a Timer is running, it won't be collected, even though you don't have any Actionscript reference to it.
I am writing a game in AS3 and have, as an example, around 40 objects on screen. Let's say they are clouds. I'm wondering which of the two paths would be less a strain on system resources:
a) Put an eventListener on each object and have it update itself, or
b) Loop through the array and manually update each object
Or is the performance difference negligable? Does either solution scale better than the others?
I would expect the performance to be fairly negligable either way. Once you get a lot of objects you might see a difference (with the loop being the winner). From my experience Adobe put a lot of work into optimizing the actionscript event listener path.
This is a tricky one, purists would say to to go with the array looping method, as with this method it would be possible to cut out the 'view' out of the MVC and still have the system working (which is a good test of any system). However, if you are working with the events you can cut some corners with event bubbling and strict typing.
For example if we assume you make a custom event called CloudEvent that has a property called cloud that contains a reference to the dispatching CloudSprite, then as long as the event bubbles by default, you don't need to add an event listener to each one, just to the DisplayObjectContainer which holds them (which I am imaginatively calling CloudContainer). This way the event bubbles up and you only have to add one listener, and don't have to worry about managing listeners on child items.
public function CloudContainer()
{
super();
addEventListener(CloudEvent.CHANGE, cloudChangeHandler);
}
private function cloudChangeHandler(evt:CloudEvent):void
{
var cloud:CloudSprite = evt.cloud;
cloud.update();
}
Hope this helps
I am under the impression that event listeners require more resources so it is better to use an array when performance is required. It would also scale better for that reason. If you are using Flash 10 then use a Vector, I believe it offers better performance than an array (and type saftey).
Use EventListeners! Just make sure you manage them properly ie. remove them when you done, use weak references.
You wont really find much performance from doing things like this. Usually better performance comes from the bigger ticked items, like not using filters, lowering the frame-rate etc. So punishing your code clarity and OO for the sake of a half a millisecond is not worth it in my book.
There are a few really great guides out there that will teach you all about optimizing in AS3. The best one I have found is Grant Skinner's; AS3 Resource Management. And I just found a quicker seven step version. I would definitely recommend everyone doing AS3 should read the Grant Skinner slides though.
Of course don't just take my word (or anyone else answering your question), you can do you own tests and actually see whats up using a profiler. See Lee Brimlow's latest video tutorial for how to do this. It is worth the watch! Check it out here: GotoAndLearn - ActionScript 3 Performance Testing.