Table of content

Previous: 1.d Finally, some particle programming

Lesson 2. Building a simple particle fountain

We first start with probably the simplest particle effect there is: a 'fountain' which sends sparks in the air at a constant rate (see lesson2.wed and .sed for a working level and the complete script for this lesson).

We start by defining the action of the fountain, a_minimal_source, which we attach to a model or a map entity in our level:

							
var velocity;

action a_minimal_source
{
	while(1)
	{
		// emit particles when user pushes "1" key
		if (key_1)
		{
			// generate initial velocity - push "shift" for a velocity boost
			velocity.x = (0.5-random(1))*(10+40*key_shift);
			velocity.y = (0.5-random(1))*(10+40*key_shift);
			velocity.z = 10 + 40*key_shift;
			
			// generate the particles
			effect(minimal_part,1,my.x,velocity);
		}
		
		wait(1);
	}
}

Here is how it works. A while(1) loop repeats the same set of instructions over and over at each frame: if the key "1" is pressed down, we first give to the vector velocity a random direction pointing roughly in the upward direction. We then create a particle (one at each frame) and launch it with initial speed velocity and with the function minimal_part() attached to it (see definition of effect() in equation (1.1)). The components x and y of velocity are each randomly drawn separately according to the following equations:

-5-20*key_shift < velocity.x <  5+20*key_shift		(2.1)
-5-20*key_shift < velocity.x <  5+20*key_shift		(2.2)

while velocity.z is equal to 10+40*key_shift. The factor key_shift allows us to control the 'force' with which particles are thrown in the air: if key_shift = 0, the particles merely drop on the floor; if key_shift = 1, the particles fly much higher and land all around the source. The non-zero x and y components of the velocity spread the sparks about the fountain.

The function minimal_part() attached to each particle, follows the basic organization described in lesson 1 (equation (1.11)).

Note: For simplicity and to keep this tutorial as short as possible, I will use variables instead of numbers only if they are repeated several times in the script, or if they are used in formulas.

bmap part_image = <novaB1.pcx>;			
var part_life = 20;							
var part_size = 100;

function minimal_part()
{
	if (my.lifespan==80)
	{ 
		my.bmap = part_image;
		my.size = part_size;
		my.bright = on;
		my.flare = on;
		my.alpha = 255;
		my.move  = on;
		my.red = 100;
		my.green = 100;
		my.blue = 255;
		my.gravity = 2;
		my.lifespan = part_life;
	}
}

It is hard to get any simpler: all we have here is instructions read only once at particle creation (when lifespan=80), which define the particle's bitmap, its size, its appearance (flare, bright, color, etc.) and its dynamic characteristics (lifespan, move and gravity). Their aspect therefore does not change: they are just created and then eliminated a while later.

To see what we have so far, just open the included lesson2.wed file in WED, adjust the path in lesson2.sed to your template_6 directory, compile, and launch the level. Press "1" or "1" and "shift" and you should get the effect shown on Figure 2.1 below.

Figure 2.1: On each image, the fountain on the left is running the minimal code, while the one on the right uses the improved code. (left image) The two fountains running at 80 fps. (right image) The same two fountains running at 30 fps or less. Note that the minimal fountain generates less sparks than the improved one when the frame rate drops. Also, particles seem to be emitted above the source's tip. The improved source looks about the same for both frame rates.

Though running without any serious problems and looking ok (I guess), the present script could stand some improvements.

Next: 2.a Adjusting the particle creation rate