Rain Effect in GameMaker: Studio

For my LD33 entry Hue and Cry I wanted a rain effect to add atmosphere. I tried various things with particles and objects. This is what I came up with in the end:

Rain effect in Hue and Cry

It really does look a lot better in-game, promise!

I’ve followed all the steps to make an example project:
RainExample.gmx

Here’s how to recreate it.

1. Raindrops
First, create a sprite for the raindrop. To some extent, its appearance should depend on the style of your game. You should also decide the angle at which you want your rain to fall, and set the raindrop to match that. As a general rule, the drop will probably need to be longer than you expect.
Here is the sprite I used for Hue and Cry, a semi-transparent line on a transparent background:

Raindrop

It seems small here but in the final game, everything was 3x as large.

Now, import this as a sprite into GameMaker, and call it sprite_raindrop or whatever your naming convention is. Use precise collision checking, and set the origin to the leading edge of the drop (so in my case, X: 0 Y:32, as it is 32×32 going down and left).

Now we must create our raindrop object. Call this object_raindrop and set the sprite to sprite_raindrop.

You will probably want to set the depth of this so it draws above other objects.

Add a Create event and add two actions:

  • Start moving in a direction from ‘move’ tab. Applies to self, and I used the bottom left arrow with speed 20.
  • Set alarm 0 to 1000 or longer if your screen is very large and your raindrops moving slowly.

When the alarm goes off we will destroy the raindrop, as it has left the screen by now. We don’t want old raindrops existing as it could cause slowdown.

So, add event Alarm -> Alarm 0 and add to that the action Destroy the instance (the recycle bin icon from main1 tab).

2. Rain Controller

So far we have raindrops which move correctly if added to the scene. We need to do two things: create a load at the start, and then continuously add them while the game is running.

To do this, create an object object_rain with no sprite. We will need to add some code to this object.

First, create a Step event. Add this code:

repeat(5) // repeat for however many new raindrops we want to add
{
  // choose a random x position inside or to the right of the view (since raindrops move left)
  rainx = random_range(view_xview[0], view_xview[0]+2*view_wview[0]);
  // choose a random y position above the view
  rainy = random_range(view_yview[0]-view_wview[0],view_yview[0]);

  instance_create(rainx,rainy,object_raindrop); // create our new raindrop
}

This creates 5 new raindrops at random positions above the view every frame. Tweak the number 5, and if your raindrops are moving in a different direction you will need to change the x coordinates of where they spawn.

You can now add object_rain to a room to give a rain effect. But there is a problem: there are a few frames at the start before rain has fallen down. To fix this, add event Create with the following code:

repeat(10) // repeat for however many raindrops we want initially
{
  // choose a random x position inside the view
  rainx = random_range(view_xview[0], view_xview[0]+view_wview[0]);
  // choose a random y position inside the view
  rainy = random_range(view_yview[0],view_yview[0]+view_hview[0]);

  instance_create(rainx,rainy,object_raindrop); // create the raindrop
}

This should now work properly if object_rain is added to a room.

3. Splashes
All well and good so far but want looks really cool is if some raindrops hit objects and create splashes. For this add object_splash with no sprite.

Add a Create event, with Set Alarm 0 to 20, and also add this code:

splash = part_system_create();
part_system_depth(splash,-100);

droplet = part_type_create();
part_type_shape(droplet, pt_shape_square);
part_type_scale(droplet,0.01,0.01);
part_type_colour1(droplet,c_white);
part_type_alpha1(droplet,1);
part_type_speed(droplet, 1,2,0,0);
part_type_life(droplet,10,10);
part_type_gravity(droplet,0.2,270);
part_type_direction(droplet,45,135,0,0);

splash_emitter = part_emitter_create(splash);
part_emitter_region(splash,splash_emitter,x-3,x+3,y-3,y+3,ps_shape_ellipse,ps_distr_gaussian);
part_emitter_burst(splash,splash_emitter,droplet,10);

I shan’t go through it in detail, but this sets up the particle system splash, particle type droplet and particle emitter splash_emitter we will use for each splash.

This is essentially all that is needed to get it to work.

Next we add two events that contain only Destroy the instance: Alarm 0 and Room End. The reason for these is to make sure the particle effects are cleaned up when we no longer need them.

Finally we add a Destroy event, which will handle all the cleanup. Add the following code:

part_emitter_destroy(splash_emitter);
part_type_destroy(droplet);
part_system_destroy(splash);

That’s all for the splash.

4. Creating the Splashes
Lastly, we need to generate the splashes when raindrops hit things. There is a certain amount of customization required for this part.

What I did was to create an object called parent_block and set this as the parent for everything I wanted to interact with raindrops.

Then add a Step event to object_raindrop with the following code:

if(place_meeting(x,y,parent_block)) {
  if(!collidedBefore && random_range(0,1)>0.5) {
    instance_create(x,y,object_splash);
    instance_destroy();
  }
  collidedBefore=true;
} else {
  collidedBefore=false;
}

and this code to the Create:
collidedBefore=false;

Let’s go through the code line by line:
If the raindrop collides with any object which has parent_block as a parent:
Check whether the raindrop collided with anything the previous frame, and if not then randomly choose half of all collisions, to create a splash and destroy the raindrop.
Then we simply set whether the raindrop collided that frame.

That’s it! Let me know whether this effect worked for you.

2 thoughts on “Rain Effect in GameMaker: Studio

  1. I’m getting an error in the RainExample.gmx in object_splash:
    “wrong number of arguments for function part_emitter_destroy”

    Any ideas?

    ryan lore Reply

Leave a Reply

Your email address will not be published. Required fields are marked *