[LibGDX][solved] Removing game objects

I was wondering if there were any better ways of removing game objects in my game programmatically by hand. Essentially, once the player collides with the enemy, I want to dispose of the entity entirely.

Is there any better way to do this except for moving the enemy off screen and allowing Javas’s garbage collector to flush it’s memory usage when I dispose of the current screen/move to a different level?

Someone pointed out a while back about using double-buffered ArrayLists to store your entities:


// static update buffer list A
	protected static List<Entity> entityBufferA = new ArrayList<Entity>(200);
	// static update buffer list B
	protected static List<Entity> entityBufferB = new ArrayList<Entity>(200);
	// byte buffer switch
	protected static byte mainUpdateBuffer = (byte) 0;


public static void refresh(int delta, int screenWidth, int screenHeight) {

		for (Entity e : getMainBuffer()) {
			if(checkIfOnScreen(screenWidth, screenHeight, e)){
				e.render();
			}
			e.update(delta);
		}
		
		Systems.RendererSystem.render();

		for (Entity e : getMainBuffer()) {
			if (e.exists) {
				getOtherBuffer().add(e);
			}
		}
		getMainBuffer().clear();
		mainUpdateBuffer = (byte) (mainUpdateBuffer == 0 ? 1 : 0);
		System.out.println(delta);
	}

	public static List<Entity> getMainBuffer() {
		return (mainUpdateBuffer == 0 ? entityBufferA : entityBufferB);
	}

	public static List<Entity> getOtherBuffer() {
		return (mainUpdateBuffer == 1 ? entityBufferA : entityBufferB);
	}

Just store all your entities into the main buffer when they are created, and when you want to destroy them turn their “exists” boolean to false. This is how I do it, but I think you get the idea.

Have an ArrayList that is filled with enemy objects. Then have a render method like this:


public void render(Graphics g) {
     for(int i = 0; i < enemies.size(); i++) { //enemies is the arraylist
          TempEnemy = enemies.get(i); // TempEnemy is a temporary enemy set to an enemy in the list so you can do method calls

          TempEnemy.render(g);
     }
}

You would do the same thing with the update loop.

Now you have to be able to add and remove enemies from this list so you would make methods like this:


public void addEnemy(Enemy e) {
     enemies.add(e);
}

public void removeEnemy(Enemy e) {
     enemies.remove(e);
}

Now in your level class or your main game class you have to make this class: (The class that has all these methods about the enemy arraylist along with the arraylist itself)


EnemyController ec = new EnemyController();

Now, to add an enemy you would just have to type:


ec.addEnemy(new Enemy(x, y));

And to remove an enemy:


ec.removeEnemy(enemy instance goes here);

Now you want to be able to render the enemies in the list on screen. So in your render loop add this:


ec.render(g); //G being a graphics object

Now you have drawn all the enemies on the screen. They won’t move if you don’t call their update method. So in you level’s update method put something like this:


ec.update();

Now, you have it. In your collision event for your player you might want to put something like this:


if(collision with enemy) {
     ec.removeEnemy(enemy);
     score++;
}

You would want to pass the EnemyController to the player in a constructor argument BTW.

Fell free to drop a medal! Have fun!

Awesome! Thank you guys.

Just removing the entity from an arraylist should suffice. As long as there isn’t an instance left of that object them the garbage collector will remove it from memory.

Another option would be to have a Boolean in the entity isDead. When it collides with the player, you would set this to true. When you’re updating and rendering then you would just ignore the enemies that are dead. When you switch the level or dispose of the screen then they should all be deleted.

The two-ArrayList way is the best, although it is best and fastest to simply swap references instead of using a method call with a byte flag for every single add.

That’s my favorite strategy! Although I prefer to save the “dead” object’s index value
and then re-use it when requesting a new enemy rather than instantiate another 1! 8)

The other option is from this recent thread:

If the order doesn’t matter, remove the latest (tail) entry and insert it in the index of the “dead” object, replacing it! :stuck_out_tongue:
This way, we avoid left-shifting the List’s entries completely! :o

static final int BULLETS = 100;
final List<Bullet> bullets = new ArrayList<>(BULLETS);

public void displaySpritesOptimized() {
  stroke(Bullet.COLOUR);
  for (int b = bullets.size(), len = b; b-- != 0;)
    if (bullets.get(b).script()) { // returns true if requesting remove due to outta canvas!
      final Bullet u = bullets.remove(--len);
      if (b != len)  bullets.set(b, u);
      System.out.println("A bullet has strayed too far from view!");
    }
}