-
Notifications
You must be signed in to change notification settings - Fork 7
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.
In order to manage all of the games particle effects, the ParticleService
class has been implemented.
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.
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.
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 theResourceService
-
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
.
-
queuedEffects
: AnArrayList
containing instances ofParticleEffectWrapper
. This stores all of the effects that are currently being rendered. -
particleEffects
: AHashMap
mapping eachParticleEffectType
to its associatedParticleEffect
. This particle effect is needed in the creation of theParticleEffectPool
. 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
: AHashMap
containingParticleEffectPool
s for each particle effect type. These are used to organise and reuse particle effects in an effective manner.
-
Constructor The constructor initialises the data structures outlined before and loads all the
ParticleEffect
s using theAssetManager
. As these particle effects assets are needed during the creation of the pools, the constructor blocks until they are loaded in. After this,ParticleEffect
andParticleEffectPool
instances are created. -
render()
Therender
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 eachParticleEffectWrapper
in thequeuedEffects
list and positions thePooledEffect
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 sameSpriteBatch
is used. -
startEffect()
The startEffect method is used to start a particle effect. It takes aParticleEffectType
enum and creates aParticleEffectWrapper
, putting this in the effect queue to be rendered.. The effect is then scaled and started. -
stopEffect()
ThestopEffect
method is called when a particle effect is complete and needs to be stopped. It takes aParticleEffectType
enum as its parameter. This method frees all of thePooledEffect
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 therender()
method. -
stopEffectCategory()
This method is similar to thestopEffect()
method but instead it stops all of the effects in a certain particle effect category.
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”.
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.
Below is a UML overview of the core classes in the system (ignoring specific implementations).