Particle effects

WME provides generic particle generators for creating real-time particle effects, such as snow, rain or smoke. For creating particle effects, WME provides so-called "particle emitters". By setting a number of various parameters of the emitters, you can achieve many very different effects.

WME particles demo

Since the number of parameters the particle emitters are providing can be quite overwhelming at first, there is a demo project prepared for you. This demo project contains several predefined particle effects (snow, rain, smoke...) ready to be copied&pasted to your own game. You can use those effects as a starting point for your own particle generators.

You will find the demo project in your WME DevKit installation folder, in the "projects\wme_particles" subfolder.


Creating particle emitters

In WME, every particle emitter is attached to a game object, either an entity or an actor. This allows you to precisely specify the depth-position of the particles within a scene. Entities and actors provide a CreateParticleEmitter() method. This method initializes a particle emitter attached to a given entity/actor. Once initialized, you can query the particle emitter object using the ParticleEmitter property.

// get the scene entity we will use to attach the emitter to
var SomeEntity = Scene.GetNode("some_entity");

// initialize entity's particle emitter
SomeEntity.CreateParticleEmitter();

// query the emitter object
var Emit = SomeEntity.ParticleEmitter;

The example above initializes and queries the particle emitter. Once queried, you can use the emitter object just like any other game object. You can call its methods and set its properties. For a complete list of available methods and properties see the particle emitter scripting reference.

Destroying particle emitters

If the particle emitter is no longer needed, you call the DeleteParticleEmitter() of an actor or an entity which owns the emitter to destroy it.

Particle emitter parameters

The particle emitter object provides numerous parameters. These parameters affect the initial state of the particles being generated by the emitter. Once the particle is "shot" out of the emitter, it lives its own life. Typically it moves across the screen in a certain direction with a certain velocity. For example, a snow emitter will generate snowflakes, and the snowflakes will slowly fall from the top to the bottom of the screen.

Emitter shape and position

First, we need to specify the shape of the emitter. Emitters in WME are always rectangles positioned somewhere on screen. You specify the position of the emitter rectangle and its width and height:

Emit.X = 100;
Emit.Y = 100;
Emit.Width = 200;
Emit.Height = 200;

Note that by specifying zero as the emitter width or height you reduce the rectangle to a line. For example, a snow emitter will be shaped as a horizontal line positioned at the top edge of the screen.

If you set both width and height to zero, you will reduce the emitter to a point. For example a smoke emitter will emit all particles from a single point.

Borders

Sometimes you need to limit the area the particles can live in. For example, you want the snowflakes to disappear when they hit the ground. WME allows you to specify the area by setting particle borders. The borders once again shape a rectangular area on screen. Use the SetBorder() method to define the border rectangle's position and dimensions. Typically this border rectangle covers the entire scene area.

Emit.SetBorder(0, 0, Scene.Width, Scene.Height);

Sometimes it's useful to set the thickness of the border. For example, you want the ground to have some height. You can set the thickness of the border edges using the SetBorderThickness() method. For example, to set the ground edge's height to 100 pixels, you'd call:

Emit.SetBorderThickness(0, 0, 0, 100);

Particles appearance

The particles are represented by WME sprites. You can assign one or more sprites to the particle emitter using the AddSprite() method. When the emitter creates a new particle, it assigns it one of the defined sprites by random. There must be always at least one sprite assigned. To remove sprites from the list, use the RemoveSprite() method.

Particles scale, velocity and direction

When a new particle is generated by the emitter, it's assigned an initial direction, velocity and scale. These parameters are assigned by random from a specified range. You specify the range by setting emitter's properties.

Emit.Velocity1 = 20;
Emit.Velocity2 = 50;

Emit.Scale1 = 10;
Emit.Scale2 = 100;

Emit.Angle1 = 175;
Emit.Angle2 = 185;

For example, if you set the above parameters to the emitter, whenever it generates a new particle it's assigned a random velocity from the range 20 to 50, scale from 10 to 100 (percent) and direction angle from 175 to 185 (degrees). The direction angle is specified as follows: 0 degrees - up, 90 degrees - right, 180 degrees - down, 270 degrees - left. And of course any angle in between.

Particles lifetime and transparency

Similarly to the other random parameters, you can specify the lifetime of the particles. The lifetime specifies for how long the particle exists on screen until it "dies" and disappears. If you specify lifetime lesser or equal to zero, the particle's lifetime isn't limited. The particle only dies when it hits the border.

Emit.LifeTime1 = 4000;
Emit.LifeTime2 = 5000;

In the above example, each new particle is given a random lifetime ranging from 4 to 5 seconds (the value is specified in milliseconds).

You can specify that the particle transparency should change in the course of particle's lifetime. For example, smoke particles will slowly fade out as they move away from the emitter. Once again, you specify the range of transparency values like this:

Emit.Alpha1 = 255; 
Emit.Alpha2 = 0;
Emit.AlphaTimeBased = true;

If you use these settings, the particles will smoothly change their transparency from 255 (completely opaque) to 0 (completely transparent).

If you don't set the AlphaTimeBased attribute to true, the particles will use a randomly selected alpha transparency from the Alpha1 - Alpha2 range instead.

Particles depth

Each particle is assigned a random depth value. The depth can be used to fake a perspective when displaying the particles. For example, you want the snowflakes the smaller and slower the farther from the viewer they are. WME allows you to bind particle's scale, velocity and lifetime using the following attributes:

Emit.LifeTimeZBased = true;
Emit.VelocityZBased = true;
Emit.ScaleZBased = true;

Particles rotation

You can specify an initial particle rotation in degrees, as well as angular velocity to animate particles rotation. Once again, the actual rotation and angular velocity value is picked randomly from the given range.

Emit.Rotation1 = 0;
Emit.Rotation2 = 360;
Emit.AngVelocity1 = 1000;
Emit.AngVelocity2 = 2000;

Particles growth/shrinking

Particles can grow or shrink in course of their lifetime. Additionally you can specify whether the growth/shrinking is linear or exponential. Exponential growth means the particles grow the faster the bigger they are:

Emit.GrowthRate1 = 20;
Emit.GrowthRate2 = 50;
Emit.ExponentialGrowth = true;

Particles generation

Particles are generated in batches. You can specify the time interval and size of the batches using the following attributes:

Emit.GenerationInterval = 200;
Emit.GenerationAmount = 40;

These parameters specify that the emitter will generate 40 new particles every 200 milliseconds. The emitter will recycle dead particles and it will generate new ones when there are no free particles available. You can limit the maximum number of particles on screen by setting the MaxParticles property:

Emit.MaxParticles = 300;

You should always set the maximum number of particles to some reasonable amount. Remember that large number of particles on screen can negatively affect the overall game performance!

You can query the current number of active particles using the NumLiveParticles property.

Fade in, fade out

You can order the particles to smoothly fade in when they are created or to fade out when they are disappearing. For example, you would use the fade-out effect to simulate the snowflakes melting away when they land on the ground.

Emit.FadeOutTime = 1000;

Masking particles by a region

Sometimes it's useful to display particles only if they are inside a specific screen region. You can achieve this by setting the UseRegion attribute to true. This attribute has effect only if the particle emitter is owned by a region entity. In that case, the entity's region is used for controlling whether the particles are visible or not.

Emit.UseRegion = true;

Attaching script code to the particle emitter

It can be useful to be able to run a piece of code whenever the particle emitter emits a new batch of particles (typically this can be used to attach some sound effect to particle bursts). For this purpose the emitter provides a property called EmitEvent. If you set this property, whenever the emitter emits new particles, it triggers an event with that name in its owner object. Set this property to null to disable event trigerring.

Emit.EmitEvent = "burst";

...

on "burst"
{
  this.PlaySound("sounds\burst.ogg");
}

Controlling the emitter

Once the parameters are set, we execute the particles generation by calling the Start() method of the emitter. This method accepts one optional parameter, which specifies the "initial time". This time is used to populate  the particle emitter with particles before it's first displayed on screen. For example, you don't want the snowflakes to start falling only after you enter the scene, it wouldn't look good. So you specify the initial time when calling the Start() method, and the emitter will simulate the particle generation and position the particles appropriately.

You can farther control the emitter's behavior using the self-describing methods Stop(), Pause() and Resume().

Forces

In addition to the particles' own velocity and direction, you can also affect their movement by placing additional "forces" to the scene. For example, you can simulate wind blowing using a force. There are two types of force: global force and point force. Global forces affect all the particles the same way, while point forces affect the particle the more the closer the particle is to the force origin. You define each force by its name, direction, strength and position in case of point forces. To add a new force or to replace force with the same name, use either the AddGlobalForce() or AddPointForce() methods. To remove a force use the RemoveForce() method.