Tech

Quick Start To Programming Particles

Posted by Mark Alexander on 9 May 2014

This tutorial is for those users that have progressed beyond the Drag'n'Drop interface and want to start using code to create their particle effects. As such, you should have a basic understanding of how to use GML (The GameMaker Language). If you want to use particles using Drag'n'Drop, there is a basic tutorial included with GameMaker: Studio which can be accessed from the Start Up splash screen Tutorials Tab. There is also an example GMZ available here to accompany this tutorial.

What is a particle?

A particle is a graphic resource that has certain properties which are defined by a particle system. These properties cannot be manipulated directly for individual particles, but are changed through the code that is used to define the system that it belongs to. They are very useful for creating beautiful and flashy effects (or subtle and discreet ones!) in a game without the cpu overhead that using objects has.

What is a particle system?

Think of a particle system like a container that we will use to hold our particles ready for use. We use code to define a series of visual aspects for our particle, and then we place it in the "container" so that we can take it out and use it whenever and wherever we need later.

How do I set one up?

Well, before setting up a system it´s important to know a few things... First off is that most of a particle systems code is only ever called ONCE in the game, usually in some type of controller object in the first room or level (this is not always the case, but for the sake of simplicity, we´ll keep it like this!). This is because a particle system, once created, stays in memory and is ready to be used at any time, so if you create it more than once it can quickly up the memory usage and cause serious lag, before eventually crashing the game. In this tutorial we will make a global particle system that can be used by any object at any time.

Part I - Creating A Particle System

To start with we need to define the particle system and give it a name so that we can use it. As this is going to be a global system that any object can use we will do it like this (in a controller object or an initialization script run at the start of the game):

global.P_System=part_system_create();

Easy, no? So that's the system created, but what about the particles? We have to define them too or the system is useless and does nothing! To create a particle you have to define it's general properties. These are like object properties, but they only apply in a general way to individual particles. What this means is that if you give the particles a minimum movement speed of 1 and a maximum movement speed of 2, any particle created by the system will have a random speed between 1 and 2 pixels per step, and that overall they will have an average speed of 1.5. Let's name and add our first particle to the system, then (the following code would go in the same object or script that we used to create the particle system):

global.Particle1=part_type_create();

Great, but we´re not ready yet to create our outstanding effects! We have still to define the general properties of our particle (ie: how it looks, its speed, rotation, alpha etc...). There are a lot of details that can be used to define a particle effect, so to show them I´ll post an overview of the manual and then a snippet of code that has them all too:

  • part_type_shape(ind, shape) - Sets the shape of the particle type to any of the constants above (default is pt_shape_pixel).
  • part_type_size(ind, size_min, size_max, size_incr, size_wiggle) - Sets the size parameters for the particle type. You specify the minimum starting size, the maximum starting size, the size increase in each step (use a negative number for a decrease in size).
  • part_type_scale(ind, xscale, yscale) - Sets the horizontal and vertical scale. This factor is multiplied with the size. It is in particular useful when you need to scale differently in x- and y-direction.
  • part_type_color1(ind, color1) - Indicates a single color to be used for the particle.
  • part_type_alpha1(ind, alpha1) - Sets a single alpha transparency parameter (0-1) for the particle type.
  • part_type_speed(ind, speed_min, speed_max, speed_incr, speed_wiggle) - Sets the speed properties for the particle type. You specify a minimal and maximal speed. A random value between the given bounds is chosen when the particle is created. You can indicate a speed increase in each step Use a negative number to slow the particle down (the speed will never become smaller than 0).
  • part_type_direction(ind, dir_min, dir_max, dir_incr, dir_wiggle) - Sets the direction properties for the particle type. Again you specify a range of directions (in counterclockwise degrees; 0 indicated a motion to the right). For example, to let the particle move in a random direction choose 0 and 360 as values. You can specify an increase in direction for each step.
  • part_type_orientation(ind, ang_min, ang_max, ang_incr, ang_wiggle, ang_relative) - Sets the orientation angle properties for the particle type. You specify the minimum angle, the maximum angle, the increase in each step and the amount of wiggling in angle. You can also indicate whether the given angle should be relative (1) to the current direction of motion or absolute (0). E.g. by setting all values to 0 but ang_relative to 1, the particle orientation will precisely follow the path of the particle.
  • part_type_blend(ind, additive) - Sets whether to use additive blending (1) or normal blending (0) for the particle type.
  • part_type_life(ind, life_min, life_max) - Sets the lifetime bounds for the particle type.

Before you look at the code, let's go over a couple of these properties in more detail...

When you see wiggle as an argument for a particle function, it means that if you place a number between 1 and 20 the particle will wiggle or fluctuate between the min and max values for the code (with 1 being a slow wiggle and 20 being very fast). So a particle speed min of 2 and max of 5 with a wiggle of 20 will oscillate very quickly between the min/max speeds for the lifetime of each particle.

Lifetime? That's the length of time in steps that a particle will exist for. So, a lifetime of 30 min and 30 max will have the particle existing for exactly 30 steps, but a lifetime of 20 min and 60 max will have each particle exists for a random number of steps between 20 and 60.

Finally, it's worth noting the blend option. With this you set the particle to have additive blending or normal blending. What's that you ask? Well having additive blending means that its brightness will be added to whatever is behind it on the screen, and so it gives a saturated glowing look - very useful for fire and magic effects (for example), but best left off for something like smoke. Experiment to see the differences!

NOTE: There are actually 3 different ways to define colour for a particle (you use only one, not all), but as this is for beginners they aren't covered here. Check the manual as they are easy to understand and offer more flexibility. There are also 3 different codes for setting alpha, and again, check the manual as they are very useful.

Now to define our global particle using the codes detailed above...

part_type_shape(global.Particle1,pt_shape_pixel);            //This defines the particles shape

part_type_size(global.Particle1,1,1,0,2);                    //This is for the size

part_type_scale(global.Particle1,1,1);                       //This is for scaling

part_type_color1(global.Particle1,c_white);                  //This sets its colour. There are three different codes for this

part_type_alpha1(global.Particle1,1);                        //This is its alpha. There are three different codes for this

part_type_speed(global.Particle1,0.50,2,-0.10,0);            //The particles speed

part_type_direction(global.Particle1,0,359,0,20);            //The direction

part_type_orientation(global.Particle1,0,0,0,0,1);           //This changes the rotation of the particle

part_type_blend(global.Particle1,1);                         //This is the blend mode, either additive or normal

part_type_life(global.Particle1,1,20);                       //this is its lifespan in steps

So that's it! We have now defined our particles and they are ready to be used? How do we do that? Read on...

Part II(a) - Creating Particles Directly

There are a couple of ways to create particles, and each has its pros and cons. You can use emitters to burst or stream particles, or you can create particles directly at a point. Which one you use really depends on what you are trying to achieve and the effect you are wanting to create, but we´ll start with the easiest of the two, which is creating particles directly with part_particles_create().

part_particles_create(global.P_System, x, y, global.Particle1, 50);

That short code above will create at the objects x/y coords 50 particles of Particle1 from our global system. Simple! The great thing about that line of code is that it can be used anywhere without any fuss. For example if you place it in the global left pressed event for the mouse in an object and change x/y for mouse_x/y, it will create particles at the mouse position every time you press the button. Or if you have a rocket, then you could place this in the step event and have smoke particles coming every step (although 1 or 2 would probably be better than 50!). You can even have it create particles over an area by changing the x/y coords randomly:

repeat(50)

    {

    var xx = x + 20 - random(40);

    var yy = y + 20 - random(40);

    part_particles_create(global.P_System, xx, yy, global.Particle1, 1);

    }

The above code will create 50 particles at a random position within a 40px square area.

Part II(b) - Creating Particles With Emitters

Since we've explained the easy way to create particles, let's now go the slightly more complex way, which is to use emitters. Emitters are another part of the particle system that has to be defined before being used, so we´ll make a global emitter the same as we did for the system and the particles. We also have to decide whether to have a static (non-moving) emitter or not and whether we are going to burst or stream the particles, as well as decide over what area and what kind of distributionwe are going to have the emitter use.

What does all that mean? Well, a static emitter is one that you can define once and forget about as it will not be moving anywhere for the duration of the game, ie: think of a log fire - it doesn't move, it just emits flames and so is static, but a fireball would require a non-static emitter and will move across the screen. As for bursting or streaming, a burst is a one off explosion of particles, whereas a stream is just that - a constant stream of particles every step. For area and distribution, with emitters you can define an area for emitting particles (which can be a rectangle, ellipse, diamond or line) as well as the distribution curve (gaussian, invgaussian, or linear). Oh, and please read the manual on emitters as it contains more info and codes that you may need or find useful.

The following images illustrate the different types of shape available:

    

And the distribution curves are illustrated here:

   

Here is a set of example codes that define two emitters. One will be static and stream particles over the area of the whole room, while the other will follow the mouse and burst every 30 steps from a small ellipse...

/

/CREATE EVENT //Define and name the emitters global.Particle1_Emitter1=part_emitter_create(global.P_System); global.Particle1_Emitter2=part_emitter_create(global.P_System); //Set up the area that will emit particles part_emitter_region(global.P_System, global.Particle1_Emitter1, 0, room_width, 0, room_height, ps_shape_rectangle, ps_distr_linear); part_emitter_region(global.P_System, global.Particle1_Emitter2, mouse_x-10, mouse_x+10, mouse_y-10, mouse_y+10, ps_shape_ellipse, ps_distr_gaussian); //Set the first to stream 10 particles every step part_emitter_stream(global.P_System, global.Particle1_Emitter1, global.Particle1, 10); //This can now be forgotten as it will function until told to stop... //Set the alarm[0] event to burst the emitter2 particles... alarm[0]=30;

 

/CREATE EVENT

//Define and name the emitters

global.Particle1_Emitter1=part_emitter_create(global.P_System);

global.Particle1_Emitter2=part_emitter_create(global.P_System);

//Set up the area that will emit particles

part_emitter_region(global.P_System, global.Particle1_Emitter1, 0, room_width, 0, room_height, ps_shape_rectangle, ps_distr_linear);

part_emitter_region(global.P_System, global.Particle1_Emitter2, mouse_x-10, mouse_x+10, mouse_y-10, mouse_y+10, ps_shape_ellipse, ps_distr_gaussian);

//Set the first to stream 10 particles every step

part_emitter_stream(global.P_System, global.Particle1_Emitter1, global.Particle1, 10);

//This can now be forgotten as it will function until told to stop...

//Set the alarm[0] event to burst the emitter2 particles...

alarm[0]=30;

But what if you want several objects to emit particles? A global emitter can only be in one place at a time, so you would need to create local emitters in each object. These emitters will still use the global particle system and any particles that are within it, but they can be different shapes and sizes and move with the object, making them ideal for rockets or bullets or things. The code you would use is exactly the same as above, but without the global. before the emitter names (Check out room 2 in the example file for examples of this (the link is at the top of the page).

That's the creation of particles dealt with but there is one more thing that´s very important... Cleaning up when you are finished with them.

Part III - Cleaning Up

As mentioned at the start, once created, a particle system (and its particles, emitters etc...) are stored in memory for instant use. Great, but what happens when you restart the game? Or if your player dies and starts the room again? Well, if you don´t manage the game right you get a memory leak. This is when something is eating up memory and will cause lag or even block the computer causing your game to crash, and it is a pretty common problem with first time users of particle systems.

How do you avoid this? Well, GameMaker: Studio has a couple of functions to delete particle systems and their emitters and particles from memory when not in use and with a little bit of planning when using the following codes, you can remove this potential problem.

The first thing you have to do is decide where you are going to create the system and how you will use it. You could create it in the Game Start event of an object that is in your first room (like a menu or title screen), but this means that if you restart the game code using the game_restart() function, it will be recreated and cause a memory leak. To avoid that you would need to have something like this in the Game End event of your object

part_type_destroy(global.Particle1);

part_emitter_destroy(global.P_System, global.Particle1_Emitter);

part_system_destroy(global.P_System);

game_restart();

This will remove the defined particle, emitter and then the system from memory before restarting the game again. If you have it in a controller object that is placed in every game room, then you could have the create event that defines the particle system and other parts, then place the destroy codes in the room end event. Just remember that after thinking about where would be the most suitable place to create the system, think about where would be the most suitable place to destroy the system too! If you check out the file that goes with this tutorial you can see what I mean by looking at the room end and destroy events of the objects used.

Summary

Now you know the basics about particles, particle systems and emitters, so you can now add them into your game! But before rushing off please note that as I said at the start, particles are less cpu hungry than objects, but they are not the solution to everything as they will cause lag if you have thousands of them at a time. The best thing to do is experiment and use them carefully to "flesh out" visually a game and give it a bit more eye-candy without over doing it.

Another thing to take into account is that a particle system can be a chore to set up and test, so I can't recommend enough that you use one of the many particle designing tools that are available. Two excellent ones are:

Particle Designer 2.3 by Alert Games - Very powerful and permits you to export the file as a gml script that can then be imported into any game.

Sparks by Nocturne Games - A particle animation tool that will create sprites from particle effects. Very useful for HTML5 and other occasions where particles cannot be used.

For further reading and an in-depth study of all the particle functions RhysMeyers has a far more extensive pdf file with just about everything particle related here.

•  Particles_For_Beginners.gmz

(Download will require you to log in)

 

Back to Top