Skip to content

Pooling

Pooling means creating a small group of reusable objects ahead of time instead of creating a new object every time it is needed.

Think of a pool as a rack of spare equipment. When the game needs one, it takes an available item from the rack, uses it, and makes it available again when it is finished. This is especially useful for things that are created or played often, such as particles, bullets, enemies, and sound effects.

One Audio element can only play one copy of a sound at a time. In Breakout, the ball can hit several bricks in quick succession. If every hit used the same audio element, a new brick-hit sound would have to wait for the previous one to finish.

SoundPool solves this by creating several Audio elements that all use the same sound file:

this.pool = [];
for (let i = 0; i < this.size; i++) {
const audio = new Audio(this.source);
audio.volume = this.volume;
audio.loop = this.loop;
this.pool.push(audio);
}

For example, new SoundPool("./sounds/paddle_hit.wav", 5, 0.5) creates five audio elements for the paddle-hit sound. They can overlap, so rapid hits still make a sound.

The pool keeps track of which audio element to try next with currentSound:

play() {
const sound = this.pool[this.currentSound];
if (sound.currentTime === 0 || sound.ended) {
sound.play();
}
this.currentSound = (this.currentSound + 1) % this.size;
}

After each call to play(), the index moves to the next item. The % this.size keeps the index within the array: after the last sound, it returns to the first one. This is called cycling through the pool.

If the selected sound is still playing, this version leaves it alone rather than restarting it. A larger pool gives more sounds a chance to overlap, but also uses more resources. Choose a size that fits how often that effect can happen; five is a reasonable starting point for a frequent effect such as the brick hit.

The same idea works for short-lived game objects. Rather than repeatedly creating and discarding particles, create a fixed number once. Mark a particle as active when it is needed, update and render active particles, then mark it inactive when its effect ends. The next effect can reuse that inactive particle.

Pooling can reduce repeated setup work and garbage collection in busy parts of a game. However, always start with simple, readable code and add a pool when an object is used frequently enough to need one.