The ParticleEmitter Object - Grisgram/gml-raptor GitHub Wiki

There is also an object available in raptor, which you can put directly on a layer in your room, the ParticleEmitter.
It can be found in the _gml_raptor_/Objects folder of the project template.

This object is also used by the ParticleManager when you create or clone additional emitters in your scene. Read more about this in Multiple Emitters.

Variables of the ParticleEmitter

The object offers a range of variables to set at design time in the room editor or at runtime.
When you create or clone an emitter, the methods of the ParticleManager take care about the details here.

image

Variable Type Description
partsys_index integer If you read the documentation to this point, you very likely already know, that this is either undefined if you have only one layer to render particles, or that this is the index for the PARTSYS macro and the index you set in the Particle Editor when you created your particle effect
follow_instance object instance Set this pointer to any instance in your room, to make the emitter follow that instance
follow_offset Coord2 Set the offset (x and y) the emitter shall keep to the instance it follows
scale_with_instance bool More often than not your instances might change their size/scaling during their lifetime. Set this to true to have the emitter also scale with the instance in the scene
emitter_name string The unique name of the emitter
stream_on_create bool True, if this emitter shall start streaming particles immediately when created. Default = false
stream_start_delay real The number of frames to wait, before actually streaming
stream_particle_name string In the Particle Editor you set a default particle for an emitter, however, when you add an emitter manually to the scene, the emitter doesn't know about that default, so you have to set the name of the particle type to spread here
stream_particle_count integer The particles per frame to emit in streaming mode
burst_particle_name string Same as with stream_particle_name, the manually added object has no information about the default particle name
burst_particle_count integer The number of particles to burst in one go

Follow offset

When you try to attach your emitter to an instance for the very first time, you will recognize, that the emitter is placed exactly at the x/y coordinates of its parent (the instance it follows).
Even if this is a natural default, in most cases, you will not want the emitter to spread exactly at this coordinates. You will want an offset to the parent. Imagine the thrust beam of a space ship. If the ship is flying to the right, you will likely want the beam to appear in the middle of the ship (vertically) and on its left edge (behind the ship, horizontally).
A toch flame will likely not spread in the top left corner of the torch, but more in the center of the object.

These offsets are very specific, spezialized for each single object.

Follow instance works as a delta mechanism, means, that, if the parent moved 5 pixels to left, the emitter will also move 5 pixels to the left.
Knowing this, makes defining the offset very easy:

After attaching an emitter to an instance, just set the emitter position!
Here's an example (The example uses the raptor macros for edges of instances, so you also see a good usage scenario for them here):


Note

This example shows the very basic "all-manually" way of attaching an emitter. There are much better ways to do this as you will see in the examples below this one!
Also, this example does not use object pools. To be honest, this example shows kind of a way "how to not do it". Keep that in mind, as negative examples also help you understanding, how to do it right.


var ship = instance_create_layer(VIEW_CENTER_X, VIEW_CENTER_Y, "ShipLayer", SpaceShip);
var ship_left, ship_middle;
with(ship) {
    ship_left = SELF_VIEW_LEFT_EDGE;
    ship_middle = SELF_VIEW_CENTER_Y;
}
var emitter = instance_create_layer(VIEW_CENTER_X, VIEW_CENTER_Y, "BeamLayer", ParticleEmitter);
with(emitter) {
    follow_instance = ship;
    x = ship_left;
    y = ship_middle;
    scale_with_instance = true;
    stream_particle_name = "ptThrustBeam";
    stream_on_create = true;
    stream_particle_count = 2;
    stream_start_delay = 0;
}

Now, that's quite some code needed to make a beam follow the ship... This can't be a good way, right? If raptor only had this option, I'd not use it.

Let's take a look at how to do it right:

Back to the Particle Editor, the object pools and the available methods in the ParticleManager class. What do we know?

  • We know, that we created a particle emitter in the Particle Editor when we exported our code
  • We also created a particle type when we exported
  • We already set the partsys_index at export time
  • We have a ParticleManager ready to use through the PARTSYS macro
  • Now we just want the predefined emitter to follow our space ship
  • AND we want to use the object pools for performance

Note

Adding all this up, it is clear, that the first example above does everything wrong!


How to do it right

In the Create and Clean Up events of your spaceship, write this:

// Create
beam_emitter = PARTSYS.emitter_attach_clone("emThrustBeam", self);
beam_emitter.set_offset(SELF_LEFT_EDGE, SELF_CENTER_Y);

// Clean Up
pool_return_instance(beam_emitter);

How to do it right with a subclassed (derived) Emitter object

For this example, we assume, that your derived emitter object is named ThrustEmitter.
The set_emitter_object and reset_emitter_object pair of calls is something you should be used to, as it is a common GameMaker pattern, which can also be found as method pairs of shader_set and shader_reset, same for surfaces, fonts (draw_set_font) and so on.
You only have to add such a pair of calls around the creation of your emitter, and you are done:

// Create
PARTSYS.set_emitter_object(ThrustEmitter);
beam_emitter = PARTSYS.emitter_attach_clone("emThrustBeam", self);
beam_emitter.set_offset(SELF_LEFT_EDGE, SELF_CENTER_Y);
PARTSYS.reset_emitter_object();

// Clean Up
pool_return_instance(beam_emitter);

Note

Now, THAT looks way better, right?
This is the way how to do it! The beam will follow the ship at a set offset for as long as it is in the scene.


Other functions in the ParticleEmitter

In the example above you have seen the very handy set_offset function of the ParticleEmitter.
It also offers functions for streaming, bursting and stop of streaming.
Once you have an emitter, you always have two ways to start/stop an emitter. Both are equally valid and exist to support your personal taste of coding. Either do it all through the global PARTSYS or do it right on the instance of your emitter, whatever you prefer.

Here are the functions offered by the ParticleEmitter

set_offset

/// @function		set_offset(xoff, yoff)
/// @description	sets a static offset distance to apply when following an instance
set_offset = function(xoff, yoff) {

stream

/// @function		stream(particles_per_frame = undefined, particle_name = undefined)
/// @description	Starts streaming particles as defined for the emitter.
///			If you don't supply any parameters, the values from the variable definitions
///			(which hold the defaults from Particle Editor) are used.
stream = function(particles_per_frame = undefined, particle_name = undefined) {

stop

/// @function		stop()
/// @description	Stops streaming
stop = function() {

burst

/// @function		burst(particle_count = undefined, particle_name = undefined, stop_streaming = true)
/// @description	Immediately bursts out n particles
///			If you don't supply any parameters, the values from the variable definitions
///			(which hold the defaults from Particle Editor) are used.
///			If no burst_particle_name is set in the variable definitions, the
///			stream_particle_name is used.
burst = function(particle_count = undefined, particle_name = undefined, stop_streaming = true) {
⚠️ **GitHub.com Fallback** ⚠️