Constantly adding/deleting many many entities [solved]


(MinusIxi) #1

I’m trying to create a bullet hell and I’m getting frame drop issues (from 60->30ish) with as little as under 200 bullet entities. So I’m having some trouble. I’m currently using basic recycling with the code looking like:

public function PlayerShot() 
{
	_image = new Image(Assets.littleTriangle);
	_image.centerOO();
	graphic = _image;
	setHitbox(10, 10, 5, 5);
	type = "PlayerShot";
	layer = GC.LAYER_BULLETS;
}

And in the parent class Shot(), there’s a function

public function CreateShotA1(x:Number = 0, y:Number = 0, speed:Number = 0, angle:Number = 0, delay:Number = 0):void {
	this.x = x;
	this.y = y;
	_speed = speed;
	_angle = angle;
	_delay = delay;
}

And this is the code in the player class is:

if (shotDelay > 0) shotDelay -= FP.elapsed;
else if (Input.check("SHOT")) {
	shotDelay = 0.02;
	for (var i:int = 0; i < 32; i++) {
		var _shot:PlayerShot = FP.world.create(PlayerShot) as PlayerShot;
		_shot.CreateShotA1(x, y, 1600, i * 11.25);
		FP.world.add(_shot);
	}
}

So I’m quite envious of the mythical 1.5k or so entities that I hear about people achieving, and I’m wondering how to optimize or what to utilize to achieve it. I hear about object pooling with linked lists or whatever, but I figured recycling with the basic flashpunk stuff would be enough. Any ideas?


(Bora Kasap) #2
FP.world.add(_shot);

Firstly, you don’t need this stuff, because create function have a boolean parameter “addToWorld” and it’s default value is “true”, so, in your code, you are trying to add the bullet to the world twice.

var _shot:PlayerShot = FP.world.create(PlayerShot) as PlayerShot;
_shot.CreateShotA1(x, y, 1600, i * 11.25);

and, you don’t need to use two lines for creating function, you can use one line so you don’t need any variables, maybe it makes a micro performance addition

PlayerShot(FP.world.create(PlayerShot)).CreateShotA1(x, y, 1600, i * 11.25);

you can use this single line. (you can be sure about “CreateShotA1” function works before adding entity to the world)

and the last thing, i feel the problem in your bullet’s update function, so, can you share your update function?


(Ssnyder Coder) #3

Are you removing the bullets from the world by using the world.recycle() method? If no entities are being recycled, then every time you call world.create() you are getting a new entity instead of a pooled one.


(Ultima2876) #4

You could do some profiling with Adobe Scout to see which functions are eating up all your processing time. Or you could do it the old fashioned way and stop creating entities once you have around 200, to see if it’s actually your entity creation that’s causing the problem.


(MinusIxi) #5

Thanks for your replies. Didn’t know I was being redundant with code, egh. I’m using TheMiner (sociodox) for a profiler. The biggest memory eating functions are flash.display.Bitmap/draw and [render], both of which quickly increase from 3E6 up to 1E7 microseconds over 10 seconds or so, even when not pressing the shot button (though only [render] increases very quickly in this case). When the shot button is held down, the draw function quickly outpaces the [render] function, and takes up about 69% and 30% of the processing time, respectively. Actually, since I’m not sure what I’m looking at, I’ll just post up a picture of the screen:

And here is the update function for shot (the bullet)

override public function update():void {
		
	_image.angle = _angle*-1;
	x += _speed * Math.cos(_angle/180*Math.PI) * FP.elapsed;
	y += _speed * Math.sin(_angle/180*Math.PI) * FP.elapsed;
		
		
	if (x > FP.camera.x + FP.width + 50 || x <  FP.camera.x - 50 || y >  FP.camera.y + FP.height + 50 || y <  FP.camera.y - 50) {
		destroy();
	}
}
	
public function destroy():void
{
	FP.world.recycle(this);
}

The only other place at the moment which will also be calling the destroy() function of the bullet is in the enemy’s update function, which is simply:

var _shot:Shot = (collide("PlayerShot", x, y)) as Shot;
if (_shot) {
	_shot.destroy();
	killed = true;
	destroy();
}

Well the lag is introduced when I’m creating a ton of bullets when I hold the button down, so I would think it’s because of this. Although the time


(Ultima2876) #6

Quick question; have you tried running it as a ‘release’ configuration in a browser? (you can keep the debug overlay on)

You should always be profiling in a release configuration (from a browser) to get the most accurate ‘real world’ performance.

The most important part in that profiler’s output is the % of frame time measurement. The vast majority of your CPU time from the screenshot (about 86%) is spent rendering. I believe the [render] part is Flash’s internal rendering - to reduce this, remove any additional DisplayList rendering (the debug console, your profiler most likely). The BitmapData/draw call is somewhat more difficult to avoid. Judging by this your issue isn’t actually object creation but rather object drawing.

My recommendation is to avoid calling ‘Draw’; Bitmaps can be drawn in two ways. These are copyPixels and draw. copyPixels is lightning fast but cannot do transformations (scaling or rotation). Draw is slow but handles transformations and a number of other useful features. If it can, FlashPunk will use ‘copyPixels’; if not (ie your Image has transformations), it will have to use Draw. To allow your game to use copyPixels you want to try and avoid transformations; obviously you want rotated bullets, but you might consider using PreRotation graphics instead of Image; these will pre-cache your rotations so that you can avoid the slow draw calls. PreRotation is used like an Image, but instead of setting the angle property, you set the frameAngle property (this is very important; if you set the angle property it will use draw just like the Image does!).

I can’t see anything obviously wrong with the way you are recycling entities or any of your other code.


(David Williams) #7

If your angle for the bullet never changes, I wouldn’t calculate the movement x and y in every update cycle, since it’d be constant.

What I’m talking about:

_image.angle = _angle*-1;
x += _speed * Math.cos(_angle/180*Math.PI) * FP.elapsed; //Store these two when you
y += _speed * Math.sin(_angle/180*Math.PI) * FP.elapsed; //actually get '_angle'

(MinusIxi) #8

After applying the suggests (except for prerotations, I’ll experiment with it when I have more free time later on), I’m finally getting from about low~mid 50’s with a few jumps into high 40’s and high 50’s. I’ll continue to fiddle with stuff, and post if I have any problems, until I get a pretty stable result. Thanks a lot guys!

Also, the angle in the update function was there in case I needed to dynamically change the angle of the bullet mid-flight. I suppose I could cache it somewhere so I don’t have to constantly calculate it, thanks for pointing that out.

Kind of off topic, but if I were to switch to, say, Axel which supports stage3d, I would be able to handle more bullets and objects because they get pushed to the GPU, but how would that affect trying to submit games to sites in the future when finding sponsorships or licenses in the future? I’ve read some posts about compatibility issues regarding stage3d and some game portals, most of which date 1 to 3 years back, but is this issue resolved?


(Ultima2876) #9

That issue with Stage3D isn’t entirely fixed, but it’s better than it was before. The main issue is that a lot of sponsors still believe most of the users are using netbooks that don’t support Stage3D (though if you use baseline-constrained that shouldn’t be an issue any more, but I don’t know how many libraries bother to implement it… I know Starling does.) Another issue is that a lot of their widgets and ads on their sites break if they enable renderMode = direct for their pages, so they don’t get as much ad revenue as they would with a non-stage3D game.

We have a Stage3D-enabled version of FlashPunk called Stage3DPunk that will be available very soon (if you PM me you can try it early as part of our testing program). It will be completely free to use on desktop and web, and we license it for your use on mobiles if you publish your game with us on at least one platform (typically though we like to publish on Barnes and Noble’s Nook Store, Amazon’s App Store and Google Play, leaving iOS and Ouya to the developer - and our publishing deal comes with some nice perks of its own quite apart from Stage3DPunk as well). Most relevantly, it has an automatic fallback to regular FlashPunk rendering if a sponsorship portal doesn’t support Stage3D – so you can get the best of both worlds; Stage3D on any site that supports it, FlashPunk on any site that doesn’t. PM me if you’d like more info (we’re preparing to release all the nitty gritty details when we release the library publically).