Particle Systems¶
A particle system, much like the UI, is a Boo script. The script provides certain settings, and is run on each particle in a system.
There is a world-view particle limit, which defaults to 500.
Terminology¶
There are three different key terms in terms in the particle system:
- Domain: The entire world's set of particles
- System: A system of particles, contained in the world, driven by a script
- Particle: An individual particle
Creating in plugins¶
To create a system, you inject the IParticleDomain
as a Dependency
,
and use its methods. Primarily the CreateSystem
method with a script
file resolved.
The returned object is a ref, and if the ref is lost, the particle
system will be destroyed. If that is undesirable, you can set
Pinned = true
.
Scripting¶
Testing¶
Empeld has a built-in particle system display. Similar to how you test UI's, simply write
empeld.exe --dev-psys path/to/my/particlesystem.psys
You can then use F5 to refresh, and WSQA to move around the system.
Particle¶
The particle itself is a set of fields, all of which are modifiable by the script.
Variable | Type | Description |
---|---|---|
Pos | Vector3d | The real-world position of the particle |
Vel | Vector3d | The current velocity of the particle |
Acc | Vector3d | The current acceleration of the particle |
TexU | Vector2 | The U coordinate of the given texture. Defaults to (0,0) |
TexV | Vector2 | The V coordinate of the texture. Defaults to (1,1) |
Col | Rgba | The color of the particle. Defaults to white (1,1,1,1) |
Size | float | The size of the particle. Defaults to 1 |
Life | float | Current life of the particle. This is set automatically, but can be overriden. Ranges from 0 to 1 |
Lifespan | float | The life of a particle, in seconds |
Child | int | The index of this particle as a child. eg. if we were the result of an exploding particle, our child would be 1. Defaults to 0 |
BlendMode | ParticleBlendMode | The mode with which the particle is blended (See below) |
ParticleBlendMode¶
* Undefined=0,
* MaskAdd
* MaskAlpha
* Additive
* Screen
* Multiply
Script¶
Unlike the UI scripts, which are duck-typed, the particle scripts have to use explicit types. This is because they need to be high-performance. You can read about explicit typing on the wiki, which you can find a link to on Boo
Variables¶
The script has various variables that can be assigned to it, some of which are optional.
Name | Type | Required | Description |
---|---|---|---|
Texture | string | Yes | Relative path to an image of the particle |
ParticleLife | |||
AudioSpawn | SoundDescriptor | Sound played when a particle is spawned | |
AudioChildSpawn | SoundDescriptor | Sound that's played when a child spawns | |
AudioDie | SoundDescriptor | Audio that is played when a particle dies | |
ParticleLife | float | Life of a particle in seconds. Default: 5 | |
SystemLife | float | Life of a system in seconds. Default: Unlimited | |
SpawnRate | float | The delay, in seconds, until a new particle is spawned. Default 0.1 | |
PerParticleBillboard | bool | If false, system computes the billboard angle (fast); if true, billboard is computed for each particle (slow) | |
Collision | bool | Whether or not we check for particle collision | |
DieOnCollision | bool | If true, particles will die on collision, otherwise, it calls the collide method or defaults to bouncing. Default true | |
AutoGravity | bool | If true, gravity is automatically applied to Acc . Default false |
|
Wind | float | Coefficient of wind affect. Default 1.0 |
Methods¶
The script also has a set of methods. Each of them have a default implementation, but you can provide them explicitly to customize behavior.
Name | Arguments | Description |
---|---|---|
constructor | This is just the boo class constructor | |
Simulate | Particle, float | Simulate the particle, for an elapsed time of d |
Spawn | Particle | Called when a particle is spawned. Can initialize it here |
Die | Particle, ret: int | Called when a particle dies. Returns the number of children that get spawned as an int |
SpawnChild | Particle | Called when a particle child is spawned |
NextSpawn | ret: float | Return a float to override the delay to the next child spawn |
Collide | Particle | Called when a particle collides with something |
Examples¶
class ParticleController:
Texture = "hardsphere.png"
ParticleLife = 3f
SpawnRate = 0.05f
PerParticleBillboard = true
AutoGravity = true
Collision = true
DieOnCollide = false
static _rSeed = 1
r as Random = null
def constructor():
r = Random(_rSeed)
_rSeed += 1
def _random() as double:
return r.NextDouble() * 2.0 - 1.0
def simulate(p as Particle, d as single):
p.Vel += p.Acc * d
p.Pos += p.Vel * d
p.Col = Rgba(1f, 0.8f, 0.8f, 1f - p.Life)
def collide(p as Particle):
p.Vel = Vector3d(p.Vel.X, p.Vel.Y, p.Vel.Z * -0.8f)
def spawn(p as Particle):
p.Vel = Vector3d(_random()*2f, _random()*2f, 10f+_random()*2f )
p.Size = 0.05f
p.Pos = Vector3d(0f, 0f, 0.55f)
class ParticleController:
Texture = "hardsphere.png"
#Audio: filename, gain, pitch, variance, min_dist, max_dist
AudioSpawn = SoundDescriptor("firework_launch.wav", 0.5f, 1f, 0.3f, 2f, 30f)
AudioChildSpawn = SoundDescriptor("firework_exp.wav", 2f, 1f, 0.3f, 10f, 50f)
ParticleLife = 2f
PerParticleBillboard = true
static _rSeed = 1
r as Random = null
def constructor():
r = Random(_rSeed)
_rSeed += 1
def simulate(p as Particle, d as single):
p.Vel += p.Acc * d
p.Pos += p.Vel * d
if p.Child > 0:
p.Col = Rgba(p.Col.R, p.Col.G, p.Col.B, 1f - p.Life)
def _random() as double:
return r.NextDouble() * 2.0 - 1.0
def _getColor() as Rgba:
return Rgba(r.NextDouble()*0.6f+0.2f, r.NextDouble()*0.6f+0.2f, r.NextDouble()*0.6f+0.2f, 1f)
def spawn(p as Particle):
p.Vel = Vector3d(_random() * 0.4f, _random() * 0.4f, r.NextDouble() * 10f + 25f)
p.Acc = Vector3d(0f, 0f, -5f)
p.Col = _getColor()
p.Size = 0.5f
def die(p as Particle):
if p.Child == 0:
return 30
return 0
def spawnChild(p as Particle):
vInit = 5f
p.Vel = Vector3d(_random()*vInit, _random()*vInit, _random()*vInit)
p.Acc = Vector3d(0f, 0f, -2f)
p.Size = 0.3f
p.Lifespan = 2f
def nextSpawn() as single:
return r.NextDouble() * 3.5f