Skip to content

Particle System

Lucas Hicks edited this page Oct 16, 2023 · 1 revision

Particle System

To enhance the gameplay of the game and to add “Juice” to it, a system that renders particle effects has been added. This system uses the particle effects system provided in the LibGdx framework (see here); however, various components have wrapper and extended this functionality allowing to be implemented in our game. The addition of these effects alleviates the need for several ui components as game state information can be conveyed via visual effects instead.

ParticleService

In order to manage all of the games particle effects, the ParticleService class has been implemented.

Rendering

The ParticleService keeps track of all of the particle effects that need to be rendered. These effects are rendered using the same SpriteBatch as the other rendered components.

Pooling

In order to optimise the rendering of particle effects, the LibGdx framework has implemented particle effect pooling. Without this pooling, a new particle effect object needs to be created, then garbage-collected during an effect’s lifecycle. Although this approach is a lot simpler, it adds more work for the garbage collector and leads to memory fragmentation as effects are taking in and out of memory. With pooling, a pool of effects are initially created, and instead of creating new effect objects, an effect is then retrieved from this pool. When the effect is no longer needed, the effect is then returned to this pool, without being garbage collected. With this approach, effects loaded into memory are reused. As a result of this, the ParticleService also stores all of the effect pools needed.

ParticleEffectType

The ParticleEffectType is an enum within the ParticleService class which defines the different types of particle effects in the game. This enum has the following member variables:

  • effectPath - the path for the particle effect file that will be loaded by the ResourceService
  • category - category of the particle effect (eg: Weather event)
  • minCapacity - initial size of the pool for the particle effect
  • maxCapacity - maximum number of free objects stored in the pool

This enum also providers various getter methods, allowing for it to interact with methods in the ParticleService.

Member Variables

  • queuedEffects: An ArrayList containing instances of ParticleEffectWrapper. This stores all of the effects that are currently being rendered.

  • particleEffects: A HashMap mapping each ParticleEffectType to its associated ParticleEffect. This particle effect is needed in the creation of the ParticleEffectPool. In order to ensure that the pool functions correctly, a reference to the particle effect needs to be maintained ensuring that the garbage collector does not remove the effect from memory.

  • particleEffectPool: A HashMap containing ParticleEffectPools for each particle effect type. These are used to organise and reuse particle effects in an effective manner.

Methods:

  • Constructor The constructor initialises the data structures outlined before and loads all the ParticleEffects using the AssetManager. As these particle effects assets are needed during the creation of the pools, the constructor blocks until they are loaded in. After this, ParticleEffect and ParticleEffectPool instances are created.

  • render() The render method is responsible for updating and displaying all active particle effects on the screen. This is accomplished by first determining the player's current vector position. Then, the method goes through each ParticleEffectWrapper in the queuedEffects list and positions the PooledEffect accordingly. When a particle effect is complete, the render method ensures that it is reset and available for potential future use. This method is called in the main render loop after all other sprites are rendered, but before lighting. Additionally, the same SpriteBatch is used.

  • startEffect() The startEffect method is used to start a particle effect. It takes a ParticleEffectType enum and creates a ParticleEffectWrapper, putting this in the effect queue to be rendered.. The effect is then scaled and started.

  • stopEffect() The stopEffect method is called when a particle effect is complete and needs to be stopped. It takes a ParticleEffectType enum as its parameter. This method frees all of the PooledEffect instances, giving them back to the pool. It then removes the effect from list of effects that are queued, ensuring that it is not called upon in the render() method.

  • stopEffectCategory() This method is similar to the stopEffect() method but instead it stops all of the effects in a certain particle effect category.

ParticleEffectWrapper

In order to effectively manage the particle effects that need to be rendered in the game, they must have game-related identifiers. As the PooledEffect class doesn’t have this, the ParticleEffectWrapper class was created. This class adds type and category metadata to the PooledEffect allowing the ParticleService to easily control these effects in the startEffect() and stopEffect() methods. The category represents the broad classification of the particle effect. For instance, The category for WeatherEvent is represented by a String “WEATHER_EVENT” and the type is its implementation i.e. “ACID_RAIN”.

ParticleEffectComponent

In order to render particle effects on entities, the ParticleEffectComponent was created. This component can be added to an entity and effects can be staged to render using the startEffect() method which takes in an effect type. This particle effect is centred on the player when created and will not follow the player. From this, the particle effect will be added to the ParticleService and all rendering will be handled. This effect can also be stopped using the stopEffect() method and the stopAllEffects() method.

UML Diagram

Below is a UML overview of the core classes in the system (ignoring specific implementations).

particleSystemUML

Clone this wiki locally