GMS 2 [Solved]Large Particle Systems - Most Efficient / Best Practices

Large particle systems can use a lot of system resources, and easily course memory leaks.

I'm trying to build a rain particle system, trying to build something efficient. My idea is to use part_emitter_region to update the position of the instance creating the rain, with coordinates based on the camera. This seems to be possible as the documentation eludes to it. However, I can't get this approach to work.

Here's the code
Code:
Create event

xmin = 0;
xmax = 0;
ymin = 0;
ymax = 0;

//Rain System
partRain_sys = part_system_create();

//Rain Particle
partRain = part_type_create();
part_type_shape(partRain,pt_shape_line);
part_type_size(partRain, 0.1, 0.1, 0, 0);
part_type_color2(partRain, c_blue, c_white);
part_type_alpha2(partRain, 0.25, 0.75);
part_type_gravity(partRain, 0.1, 290);
part_type_speed(partRain, 0.5, 0.5, 0, 0);
part_type_direction(partRain, 250, 330,0,1);
part_type_orientation(partRain,290, 290, 0, 0, 0);
part_type_life(partRain,room_speed,room_speed*2.2);
gpu_set_blendmode(bm_add);

//Create Emitter

partRain_emit = part_emitter_create(partRain_sys);
part_emitter_stream(partRain_sys,partRain_emit,partRain,5);

//Advance System
repeat (room_speed * 5) {
part_system_update(partRain_sys);
}
Code:
Step event
xmin = camera_get_view_x(view_camera[0]);
xmax = camera_get_view_x(view_camera[0]) + 400;
ymin = camera_get_view_y(view_camera[0]);
ymax = camera_get_view_y(view_camera[0]) + 400;

//Update Emitter
part_emitter_region(partRain_sys,partRain_emit, xmin, xmax, ymin, ymax, ps_shape_line, ps_distr_linear);
part_particles_clear(partRain);
The particle system is stationary in the above example. I've tried multiple x- and y-inputs, but it remains stationary. Perhaps the idea of moving the emitter is outside the scope of what the intention in GM2 is?

Is there some sort of best practice, or better examples of how to large systems, that wont spand the entire room, but only whats inside the view?
 
Last edited:

NightFrost

Member
That's odd, altering emitter region should work. Incidentally, I notice you don't set region before you advance the system, so I'm not sure where the initial raindrops will be created... but that shouldn't be the cause of the problem as the emitter would start working properly after the Step runs the first time, anyway. Try checking the actual x/y values you are getting in the debugger, perhaps the camera is returning zeroes so the emitter won't move.

However, even if you get it working you still have a slight visual problem. Moving an emitter means it leaves a trail of particles. Your emitter being the size of the screen instead of a point or some other shape doesn't change this. Particles are fire-and-forget, after they have spawned they pay no attention to the emitter, only the particle values they received on creation; the emitter switching positions does not concern them. To have the rain smoothly follow the camera as it moves, you must update the position of the entire particle system with part_system_position. and leave the region as [0, 0, view width, view height]. Updating system position moves everything associated with it, from emitters to all created particles.

(Also, when I make rain particles, I don't use gravity, letting them fall at set speed. I feel it looks better than accelerating raindrops.)

EDIT - I said particles look only at the values they received at creation. This is mostly true, I've observed, and changing any value only affects particles created thereafter. Except the sprite setting. It changes even particles that already exist, so updating it in Step would cause generally undesirable behavior.
 
Last edited:
I couldn't get it to work with part_system_position.

I found out I screwed around a bit too much with what to place where. As the documentation states, part_emitter_region needs to be used in a step event, if one wants movement. Here's the final code, which works:

Code:
create event

xmin = camera_get_view_x(view_camera[0]);
xmax = camera_get_view_x(view_camera[0]) + camera_get_view_width(view_camera[0]);
ymin = camera_get_view_y(view_camera[0]) + camera_get_view_height(view_camera[0]);
ymax = camera_get_view_y(view_camera[0]) + camera_get_view_height(view_camera[0]);

//Rain System
partRain_sys = part_system_create();

//Rain Particle
partRain = part_type_create();
part_type_shape(partRain,pt_shape_line);
part_type_size(partRain, 0.1, 0.1, 0, 0);
part_type_color2(partRain, c_blue, c_white);
part_type_alpha2(partRain, 0.25, 0.75);
part_type_gravity(partRain, 0.1, 290);
part_type_speed(partRain, 0.5, 0.5, 0, 0);
part_type_direction(partRain, 250, 330,0,1);
part_type_orientation(partRain,290, 290, 0, 0, 0);
part_type_life(partRain,room_speed,room_speed*2.2);
gpu_set_blendmode(bm_add);

//Create Emitter

partRain_emit = part_emitter_create(partRain_sys);
part_emitter_region(partRain_sys,partRain_emit, xmin, xmax, ymin, ymax, ps_shape_line, ps_distr_linear);
part_emitter_stream(partRain_sys,partRain_emit,partRain,5);
part_particles_clear(partRain);

//Advance System
repeat (room_speed * 5) {
part_system_update(partRain_sys);
}
Code:
Step event

xmin = camera_get_view_x(view_camera[0]) - 150;
xmax = camera_get_view_x(view_camera[0]) + camera_get_view_width(view_camera[0]) + 150;
ymin = camera_get_view_y(view_camera[0]);
ymax = camera_get_view_y(view_camera[0]);
part_emitter_region(partRain_sys,partRain_emit, xmin, xmax, ymin, ymax, ps_shape_line, ps_distr_linear);
You're right that there is a slight visual problem with this method, as the particles are trailing. However, I think it's mediated to the point of being not noticeble when making a buffer on the x-axis.
 
Top