as3 what is the most efficient way to use enterframes

16 posts

Flag Post

i need advice from developers, i noticed that my game runs too much addeventlisteners and enterframes and it lags about 5% of the game. and each class runs about 3 to 5 addeventlisteners. my question is what is the most efficient way to use addeventlisteners and enterframes.

 
Flag Post

//sumgato:Try to avoid repeating event listeners that can use only one handler (such as enterFrame or keyboard listeners) and always remember to remove them with removeEventListener once you don’t need them (you can also use weak references by passing true as the last parameter (addEventListener(event, listener, false, 0, true);) and then the event listener should be garbage collected along with the object, but I have read that they aren’t very reliable so I’d rather be safe and remove the listeners with removeEventListener)
//

thanks sumgato.

 
Flag Post

Kind of like this:

	public class GameContainer 
	{
		// vector (or array, if you must) that you will populate with objects that need to execute something every frame
		private var aBunchOfGameObjects:Vector.<GameObject>;
		
		public function GameContainer() 
		{
		}
		
		// this is a single enter frame function
		private function FrameHandler(e:Event):void
		{
			var i:int;
			var iLength:int = aBunchOfGameObjects.length;
			
			// cycle through all of your game objects, or whatever, and do stuff with them
			for (i = 0; i < iLength; i++)
			{
				aBunchOfGameObjects[i].StuffToDoEveryFrame();
			}
		}
		
	}

Also don’t forget to remove any event listeners for objects you no longer have references to. Excessive enter frame events will lag you, not removing event listeners will lag you too, because they (annoyingly enough) don’t clean up on their own.

Also, about weak references: It’s my understanding that weak references are NOT self cleaning either. What they do is allow an object to be collected if no other references to it remain. The listener itself still remains though.

 
Flag Post
Originally posted by Aesica:

Kind of like this:

	public class GameContainer 
	{
		// vector (or array, if you must) that you will populate with objects that need to execute something every frame
		private var aBunchOfGameObjects:Vector.&lt;GameObject&gt;;
		
		public function GameContainer() 
		{
		}
		
		// this is a single enter frame function
		private function FrameHandler(e:Event):void
		{
			var i:int;
			var iLength:int = aBunchOfGameObjects.length;
			
			// cycle through all of your game objects, or whatever, and do stuff with them
			for (i = 0; i &lt; iLength; i++)
			{
				aBunchOfGameObjects[i].StuffToDoEveryFrame();
			}
		}
		
	}

Also don’t forget to remove any event listeners for objects you no longer have references to. Excessive enter frame events will lag you, not removing event listeners will lag you too, because they (annoyingly enough) don’t clean up on their own.

Also, about weak references: It’s my understanding that weak references are NOT self cleaning either. What they do is allow an object to be collected if no other references to it remain. The listener itself still remains though.

That’s awesome, I never thought of just running all of those functions with 1 enter frame, I assumed it would lag just as bad as all the other enter frames.

 
Flag Post

Nope, because you have 1 event listener rather than thousands. Sending an event has a small amount of overhead that a basic loop doesn’t have.

 
Flag Post

with your permission, Aesica & Therus16, I´ll put the very useful code of Aesica in Spanish, for help to more people ;)

package 
{

	public class ContenidoJuego
	{
		/*vector o Array que se llenará con los objetos que necesitan ejecutarse 
		cada frame*/
		private var unMontonDeObjetosDelJuego:Vector.<ObjetoJuego>;


		public function ContenidoJuego()
		{
		}
		//Esto es una simple función enterframe
		public function ControladorDeFrames(e:Event):void
		{
			var i:int;
			var iLongitud:int = unMontonDeObjetosDelJuego.length;
			/*ciclo a través de todos tus objetos del juego, o lo que sea, y hacer 
			cosas con ellos*/
			for (i = 0; iLongitud; i++)
			{
				unMontonDeObjetosDelJuego[i].CosasQueHacerCadaFrame();
			}
		}
	}
}

 
Flag Post

Did anyone create a game which uses frame enter events in the way Aesica do? I wonder if how big is the performance difference. Also, does switch from pseudo parallel(multiple enter frame events) to linear(loop) affect anything?

 
Flag Post

@chachon2: Go for it. :D

@a3lex33: My entry in the most recent gitd thread uses this method, as does the first game I made. If you have the patience to reach the final boss, you’ll find there’s a LOT of things flying around on the screen and a surprisingly small amount of lag despite that. While neither of these games are all that great overall, they do perform exceptionally compared to games that use multiple enterframe events. There’s also this thing I made when I first explored the concept of blitting over using standard displayobjects. As you can see, even with normal displayobjects, using a single enter frame function over several hundred allows thousands of things to fly around the screen before performance hits start to kick in.

 
Flag Post

Aesica can you put a small example so that noobs can use it and learn with it, and we can use that trick in our games??

 
Flag Post

Well I kind of did give an example. Let’s say you have a coin class, an enemy turtle class, and a player class. With several coins, turtles, and the player on the screen, that could either be a bunch of different enter-frame events (one for each object) or you could have just one class with one enter-frame function that loops through an array of coins, turtles, and players and calls what would’ve been their enter-frame function, all without the excess overhead of a dozen+ different enterframes firing off 30-60 times a second.

 
Flag Post
Originally posted by Aesica:

Well I kind of did give an example. Let’s say you have a coin class, an enemy turtle class, and a player class. With several coins, turtles, and the player on the screen, that could either be a bunch of different enter-frame events (one for each object) or you could have just one class with one enter-frame function that loops through an array of coins, turtles, and players and calls what would’ve been their enter-frame function, all without the excess overhead of a dozen+ different enterframes firing off 30-60 times a second.

aesica your code is great, so your saying that i should make a separate class only for an enterframe function and collect them in one array for the enemies and the players functions. so what if i remove an object for example enemy then the enemy dies then how should i removed there functions individually if the loop is still running and the object would be null.

 
Flag Post

What I did for the game of mine that used displayobjects (sprites in particular) instead of blitting was that the container class (I called it “GameContainer”) I added all the sprites to also held the arrays. So, when I needed to add something to the stage, I’d also add it to the array. When it was time to remove something from the stage, it would get removed from the array in the line right after. Basically, whenever you intend to remove something from the stage, remove it from the array at the same time.

// any time you might do this:
removeChild(arrayOrVectorOfStuff[i]);
// do this right afterward:
arrayOrVecorOfStuff.splice(i, 1); // edit:  I can't remember the last time I used splice, so I hope this is correct

Once you get that down, note that there’s an even faster way to remove things from an array:

arrayOrVectorOfStuff[i] = arrayOrVectorOfStuff[arrayOrVectorOfStuff.length - 1];
arrayOrVectorOfStuff.length--;
i--;

In both cases, the variable “i” is of course implying a for loop. I’m just too lazy to open FD and deal with proper tabbing this time. :)

 
Flag Post

removing it from the array. thanks aesica.

 
Flag Post
Originally posted by theruss16:

always remember to remove them with removeEventListener once you don’t need them (you can also use weak references by passing true as the last parameter (addEventListener(event, listener, false, 0, true);) and then the event listener should be garbage collected along with the object, but I have read that they aren’t very reliable so I’d rather be safe and remove the listeners with removeEventListener)
//

Well, there’s no such thing as an event listener being collected.
This is mixing two things up in a way that it sounds confusing.
Let’s have a look:

Adding a listener to an EventDispatcher means nothing else but adding a reference to a function to that dispatcher.
“Hey you, when that event happens, call that function”

Then you add the garbage collector to the whole thing.
This is a process that wipes all objects that are not referenced and aren’t referencing anything from memory. (that’s super simplified)
“If you don’t have any connections to it and it has no connections to you, consider it dead”

With that in mind, we can take a look at that first statement again:
Adding a listener to a dispatcher means adding a reference (to a function).
That’s why you should remove listeners from unwanted objects, because only objects without references can be collected.

So far so good.

But how is adding a weak listener different?
After all, this would add a weak reference that’s not counted as a “strong” reference.
Therefore, the object should still be collected even though this reference still exists, right?

Yes. That’s all correct.
But guess what?
Nothing guaranties it actually happens. Just because some object could possibly be collected doesn’t mean the collector actually runs.
Collecting garbage is serious work and you don’t want to run after every small piece of junk.
That’s why the garbage collector runs at some arbitrary point that you cannot determine.
After all that’s the beauty of managed memory. (pun intended)

So if you null the last reference to an object with a weak referenced ENTER_FRAME listener added to it, you have no guarantee when this function you added as a listener will be called for the last time.
Maybe the flash runtime that executes your application can never be bothered to collect that one object, because it wouldn’t make much sense from a memory management / performance point of view.

But sure enough your logic goes haywire if that “deal one damage to the player every frame” object persist in memory and keeps on doing its thing.

 
Flag Post
Originally posted by NineFiveThree:

But sure enough your logic goes haywire if that “deal one damage to the player every frame” object persist in memory and keeps on doing its thing.

This won’t happen with enter frame events (assuming you remove the object from the stage), but it could certainly happen with timers. Yet another reason to use ENTER_FRAME.

Edit: Ok, you’re right. Yet another reason to use only a single ENTER_FRAME listener that calls an update() function on everything else.

 
Flag Post
Originally posted by player_03:
Originally posted by NineFiveThree:

But sure enough your logic goes haywire if that “deal one damage to the player every frame” object persist in memory and keeps on doing its thing.

This won’t happen with enter frame events (assuming you remove the object from the stage), but it could certainly happen with timers. Yet another reason to use ENTER_FRAME.

In this example, the Event keeps firing (at least for me).

package 
{
    import flash.display.Sprite;
    
    import flash.events.Event;
    
    public class FlashTest extends Sprite 
    {
        private var _count:uint = 0;
        
        public function FlashTest() 
        {
            var s:Sprite = new Sprite();
            
            s.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);  
            
            s = null;          
            
        }
        
        private function onEnterFrame (e:Event):void
        {
            trace(_count++);
        }

    }
}

The variable is local, but I set it to null anyway.