Link Search Menu Expand Document

Particles

Particles are everywhere, rain, smoke, dust, clouds, and more! Adding them to your game will make it look more natural and polished.

Let’s learn about particles!

Particle Basics

What is a particle?: These are little dots (or other shapes), that fly around on the screen. They don’t interact with anything on the screen, they’re mostly just used for adding visual flare

There are 3 components that go into particles

  • Particle System: This has properties for a group of particles (for example depth)
  • Particle Type: Before you make particles you need to define a particle type. This will have all the information about how the particles look and behave
  • Particle Emitter: These emit the particles. Everything about how are where the particles spawn is determined by the emitter

TODO: do I need to talk more about depth / layers at some point?

Sweet, next let’s see how this translates to code

Turret Explosion

We already added camera shake to make the turret death pop more, let’s ad particles for even more pop 💥

// oTurret Create
//// PARTCILES
{
	p_sys = part_system_create();

	p_type = part_type_create();
	part_type_shape(p_type, pt_shape_smoke);
	part_type_color1(p_type, c_gray);

	p_emit = part_emitter_create(p_sys);
	part_emitter_region(p_sys, p_emit, x-10, x+10, y-10, y+10, ps_shape_ellipse, ps_distr_linear);
}

p_sys = part_system_create();: This creates a new particle system

p_type = part_type_create();: This creates a new particle type

part_type_shape(p_type, pt_shape_smoke); / part_type_color1(p_type, c_gray);: These define the shape and color properties for the particle. There are a LOT of particle properties, it’s not uncommon to have to call 10-15 property functions after creating your particle type. They all start with p_type to indicate which particle type is being updated, and then they follow up with the property specific parameters. ctrl + space and F1 are your friends. Type part_type_ and ctrl + space to see the full list of particle type functions. Also you can hit F1 on any of them to see the documentation. Try clicking pt_shape_smoke and hitting F1, this will show you all your other particle shape options

p_emit = part_emitter_create(p_sys);: Creates a new particle emitter. Be sure to include the system here as one of the input parameters

part_emitter_region(p_sys, p_emit, x-10, x+10, y-10, y+10, ps_shape_ellipse, ps_distr_linear);: This defines where the particles will spawn. You start with 2 points to form a rectangle, and then you specify the shape an distribution. In this case I’m putting ps_shape_ellipse so that it’ll limit to the circle within the defined rectangle, and ps_distr_linear to indicate that I want them to spawn evenly across the area (as opposed to ps_distr_gaussian where most particles will spawn toward the center of the emitter region)

That’s all for the setup, but it won’t spawn any particles unless we call either the part_emitter_burst function, or the part_emitter_stream functions. Let’s do that next

// oTurret Step
{
	if(visible){
		if(hp < 0){ // add visible afterward
			visible = false;
			part_emitter_burst(p_sys, p_emit, p_type, 10);
			alarm[1] = -1;
			with(oControl){
				shake_cx = 0;
			}
		}
	}else{
		if(part_particles_count(p_sys) == 0){
			instance_destroy();
		}
	}
}

// oTurret Destroy
delete this event, we don't need it anymore

if(visible): I’m updating the turret to handle it’s death in 2 phases. First it’ll go invisible, where it spawns a bunch of particles, and triggers the camera shake. Then once the particles are all gone, we’ll actually destroy the turret. I use the visible variable to figure out which phase we’re one. If hp < 0 then we’re ready to start the first phase, and visible will be set to false. Then while visible is false, we’ll be checking to see if the particles are complete

Why are we using visible to store state? Didn’t you spend a lot of time talking about flags and state machines for this kind of thing?: Yep you got me, in this case visible is the easy/hacky way, but using flags or a state machine is probably better. I guess I can get a way with it since the turret object is a little simpler than the player, but I’m also just being kind of lazy

part_emitter_burst(p_sys, p_emit, p_type, 10);: Here we send out a burst of 10 particles (with the system, emitter, and particle type that we defined). This emits all 10 particles at the same time, if we had used part_emitter_stream then it would have continued to send out 10 particles every step until we changed it. Since we want this to be a single explosion, part_emitter_burst is the way to go

Particle Independence: One important note is that particles systems/types/emitters all exist completely independently from the object. We create the particles from the object, but they aren’t affected by the objects properties. This is why we can make the object invisible without affecting the particles. Changing visible just disable’s the objects draw event, but the particles are drawn separately. We’ll find later that the particles don’t even care if the object exists or not, we can destroy the object, or even restart the game and the particles will just continue to exist. I’ll cover how to handle this a bit later

alarm[1] = -1;: Since the turret is now in the dying phase, we want to disable the shooting alarm

if(part_particles_count(p_sys) == 0){: This checks how many particles are left in the system. Once you create particles, they move around for a bit, and then eventually die. You can change how long particles last using part_type_life but by default they only last for a few seconds

Nice work! Now we should see an explosion when we kill turrets

Well it still needs some work. Maybe you could try browsing through the particle properties, and try making it look better?

<data-summary=”How to improve the particles?” markdown=”1”>

Here’s what I came up with, but there are many right ways to do this, so don’t take this as gospel

p_type = part_type_create();
part_type_shape(p_type, pt_shape_smoke);
part_type_color1(p_type, c_gray);
part_type_alpha2(p_type, 1, 0);
part_type_life(p_type, room_speed, 2*room_speed);
part_type_speed(p_type, 1, 2, -.1, 0);
part_type_direction(p_type, 0, 360, 0, 10);
part_type_size(p_type, .5, .7, .05, 0);

Here’s what I came up with after play with it a bit. When working with particles it’s pretty common to do a lot of iterations of testing the game and then going back to tweak the values. Don’t feel like you need to know the numbers right away, it always takes some tweaking

part_type_alpha2(p_type, 1, 0);: This sets the alpha/transparency of the particle type. We use alpha2 to indicate that we want to specify 2 alpha values (one for the beginning, and one for the end). In this case I’m having the particles start at 1, and then fade to 0 by the end of the particle’s life

part_type_life(p_type, room_speed, 2*room_speed);: I want to prolonge the fading effect, so I’m changing the particle life. Here I give it a minimum and a maximum range so they could die anywhere from 1 to 2 seconds. Now in addition to fading, we’ll also see the particles thining out since most of them will already be gone by the time we hit 1.8 seconds

part_type_speed(p_type, 1, 2, -.1, 0);: At the moment the particles just sit there, but with an explosion you’d expect them to move away so I’m adding a bit of speed. The first to properties are the minimum and maximum starting speed, so their speeds will range from 1 px/step to 2 px/step. This will give them a spread as some will end up traveling further than others. I also wanted to particles to slow down as they move away from the start (this looks more naturaly since real smoke would be slowed down by air resistence), so I specify -.1 to be the increment. This indicates that the speed should decrease by .1 every step. The last parameter is the wiggle, this will randomly change the speed over time. I didn’t feel like I needed that one

part_type_direction(p_type, 0, 360, 0, 10);: In addition to speed I also wanted to clarify which direction it should move. The parameters are very similar to the part_type_speed parameters, with min, max, increment, and wiggle. I wanted to initial direction to be completely random between 0 and 360. I didn’t want an increment (although adding increments to direction creates a cool spiral effect, definitely worth trying at some point). And then I used 10 for the wiggle to hopefully make it look a little more natural. So it’s essentially adding random_range(-10, 10) to the direction on every step

part_type_size(p_type, .5, .7, .05, 0);: Size also follows the min, max, increment wiggle pattern. By default the particles were a tad big, so I changed the sizes to range between .5 and .7. I’m actually having it grow over time, combining this with the decreasing transparency makes it look like the smoke is dissapating

</data-summary>

Now we’ve got an awesome explosion for our turret 😎

Flames

Next let’s use particles to make the spark bullets actually look like flames

We’ll start by unchecking the visible box for oSpark

This is a common approach for simulating fire, water, and other effects. Just make actual bullets to handle the collisions and then use particles to make them look pretty

Here’s what I came up with 😜

//// oFlame Create
// particles
{
	p_sys = part_system_create();

	p_type = part_type_create();
	part_type_shape(p_type, pt_shape_explosion);
	part_type_color_mix(p_type, c_red, c_yellow);
	part_type_life(p_type, 5, 15);
	part_type_alpha3(p_type, 0, 1, 0);
	part_type_size(p_type, .75, 1, -.01, 0);

	p_emit = part_emitter_create(p_sys);
	part_emitter_region(p_sys, p_emit, x-8, x+8, y-8, y+8, ps_shape_ellipse, ps_distr_linear);
	part_emitter_stream(p_sys, p_emit, p_type, 2);
}

//// oFlame Step
// particles
{
	part_emitter_region(p_sys, p_emit, x-8, x+8, y-8, y+8, ps_shape_ellipse, ps_distr_linear);
}

part_type_color_mix(p_type, c_red, c_yellow);: This set the particle color to be a random mix between 2 colors. So the particles can be red, yellow, orange or any other color in between

part_emitter_region(p_sys, p_emit, x-8, x+8, y-8, y+8, ps_shape_ellipse, ps_distr_linear);: The region roughly matches the shape of the bullet. I’ve also added it to the step event, that way the particles will continue to spawn from the correct location as the spark moves

part_emitter_stream(p_sys, p_emit, p_type, 2);: I’m using stream here because I want the particles to keep spawning as the bullet moves

Particle Clean Up

Particles can be a little stubborn about going away sometimes. Let’s add a debug key for restarting the game, and I’ll show you what I mean

// oPlayer Step Event
switch(state){
	...
}

//// RESTART DEBUG KEY
if(keyboard_check_pressed(ord("R"))){
	game_restart();
}

Now trigger the flame turret, and then restart the game

What!?! 😲 Why are the particles still there!!! 😭

So as I mentioned earlier, particles are independent of objects, and not just that, they’re independent to the point where it’s kind of extreme. Doesn’t matter if destroy the object, go to a different room, or even restart the game. The particles will hang around in memory until you explicitly delete them

Early on, you had to think of all these scenarios when handling particle clean up, so we’d have the same clean up code in the destroy event, room restart event, game restart event, etc. Now, luckily, Game Maker added a clean up event to help with this

// oTurret Clean Up Event
part_type_destroy(p_type);
part_emitter_destroy(p_sys, p_emit);
part_system_destroy(p_sys);

// oSpark Clean Up Event
part_type_destroy(p_type);
part_emitter_destroy(p_sys, p_emit);
part_system_destroy(p_sys);

Now when you try the same trick, the particles should clean up properly

This bug is very easy to miss, I think I’ve hit it in every game I’ve made, and it’s often pretty late in development

More Particles?

I’ll chill w/ the particles for now, but you can keep going as long as you like 😉, here are some other options if you’re interested

  • Smoke on the missile
  • Bullet Collision
  • Rain

Can you have too many particles? Technically yes, with enough particles you’ll eventually hit performance issues, but designwise not really. If you have a lot of big effects your player will get really overwhelmed, but if you look for it, you’ll find that modern games have tiny particles effects EVERYWHERE. It’s just a great tool to make your world seem more real and alive

Particle Tools

As mentioned earlier, whenever I make particles there tends to be a lot of back and forth rerunning the game to make sure the effect looks the way I want it

There are tools out there which let you preview particles in real time. In theory I think they’d save a lot of time, and are probably worth using

I haven’t gotten around to using them myself yet (old dog, new tricks y’know), but don’t let me hold you back! Here are some optoins to consider

  • Particle Forge by DragoniteSpam: This is a free tool from the Game Maker community (but please donate if you can)
  • GeonFx: This seems like a really professional one, but it also comes with a price tag

This site uses Just the Docs, a documentation theme for Jekyll.