Bullet Collision Loop

I’m looping through an ArrayList to check if an enemy is colliding with one of the player’s bullets. It runs smoothly with only a few enemies on the screen but when there’s a bunch of them then the game starts to lag because every enemy is looping through every bullet.

Code:


	public void checkCollision(ArrayList<ShipBullet> bullets){
		for (int i = 0; i < bullets.size(); i++){
			ShipBullet bul = bullets.get(i);
			Rect rect1, rect2;
			rect1 = new Rect(bul.x,bul.y,bul.x+1,bul.y+4);
			rect2 = new Rect(x, y, x+graphic.getWidth(), y+graphic.getHeight());
			if (rect1.intersect(rect2)){
				destroyed = true;
				break;
			}
		}
	}

Is there any better way of doing this? I was thinking of pooling the bullets but I’m not familiar with pooling just yet (pretty much just found it on Google). Just wondering if there are other methods that I can try.

The method is checked every frame and there can be up to 10~ bullets on the screen from the player alone. And it starts lagging when 6 or so enemies are present. Not to mention I’m working on a cheap Android device but I’d still like to optimize it.

Thanks!

Have you tried profiling it? How many bullets are we talking about?

You could probably save a lot of time if you didn’t create two new Rect objects to test for each intersection. Either do the math manually or just create some Rects earlier and reuse them.

Is this collision method run for each entity? Because that seems wrong to me. Also just use an arraylist just like enemies.

But a short fix is to perform a distance check before collision (avoid sqrt)

A distance check isn’t going to be much more expensive than a rect-rect check, you’re just adding extra work. The ‘new’ overheard (especially on an Android VM) is going to dwarf that.

That was just some sloppy code on my behalf, I didn’t think it would have affected the performance that much though? (I’ll smooth it out a bit now)
And well bullets… uhm, can be around 20 maximum at any one time I think, by which time they leave the screen and get removed from the ArrayList. That’s just for the player bullets minus any additional ones from enemies (which I have yet to add).
Edit: Nope, no profiling - yet.

I run that method for every enemy ship in the enemy ArrayList.
Like this:


			//Enemies
			for (int i = 0; i < enemyList.size(); i++){
				Enemy enemy = enemyList.get(i);
				enemy.checkCollision(player.getBullets());
				
				if (enemy.getDestroyed()){
					propList.add(new GameExplosion(enemy.x,enemy.y));
					enemyList.remove(i);
					continue;
				}
				enemy.step(g);
			}

The bullets original ArrayList is held within the player object, and I just pass it to each enemy every step. If that’s a bad idea how otherwise would I get each enemy to check for collisions against bullets?

Edit 2:
Thanks for the suggestion about creating the Rects early on and reusing them. Got a noticeable performance boost. I don’t detect any lag unless I fill the screen up with about 40 enemies - the actual game won’t get that half as many enemies on the screen at once.

For optimized performance I wouldn’t use ArrayLists if items are removed frequently - just take a look into the source code to see what happens if its not the last item you remove.