User:Crush/Particle Engine Tutorial
This will become a tutorial for creating particle effects. Still under construction.
- 1 Basics
- 2 Blinking
- 3 Water Fountain
- 4 Fireball Fountain
- 5 Cool Fireball Fountain
- 6 Orbiting Spheres
- 7 Smoke puffs
- 8 Triangle in circle
What is the particle engine?
The particle engine is a system to create dynamic graphic effects by creating a large number of small objects called particles which move through the game world independently. These particles are created by so-called emitters which are also particles and thus can (but don't have to) move through the world. By defining the physical properties and behavior rules of emitters and the particles they create you can create a vast range of beautiful effects like waterfalls, fire or all kind of magic phenomenons.
Although the TMW engine is usually two-dimensional the particle engine sees the world as a flat ground in a three-dimensional space and can move particles in all three dimensions. Thus it is very easy to create an illusion of 3d with the particle engine.
where are the files for what purpose
All particle-related files can be found in the folder data/graphics/particles in the tmw data files which you can get from SVN or from unpacking the updates you can find a tutorial how to get these files on the forum.
In this folder you can find a number of .png files. These are the particle images you can use to represent your particles in the game world. And then there are a number of .particle.xml files. These are particle effect definition files which define the properties of emitters and particles for different particle effects. During this tutorial you will learn how to write these files yourself and enrich the mana world with new, astounding particle effects.
how can particle effects be added to maps
Particle effects can be placed on maps where they immediately catch the eye of the player. Please refer to Particle_engine#Putting_particle_effects_on_maps for details.
how can particle effects be added to NPCs
- TODO: describe how to add and edit the npcs.xml file and add a <particlefx> tag to an NPC.
The first particle effect we are going to create is a bunch of blinking stars which tell the player "something magical is here". We will do so by creating an emitter which spawns particles in a box of 32x32x32 pixels. We will make the particles look like stars, constantly spawn new ones (one every game tick or 10ms) and we will make each of them disappear again after 10 game ticks (100ms). They will not move - we will have moving particles in the next tutorial.
First we start with the basic structure of a particle effect definition:
<?xml version="1.0"?> <effect> <particle> </particle> </effect>
What does this do? The first line defines that it is an XML file. XML is a markup language for representing all kinds of hierarchical data like our particle effects. Wikipedia got a nice article about the XML language, when you are interested in details of the language. The second line, <effect> says, that the definition of a particle effect will follow. Every particle effect needs to have at least one particle, the so-called root particle. The line <particle> says that we are now going to start defining one. We will soon equip this root particle with a particle emitter to make it create new particles. But this will come in the next step. So we finish its definition with the tag </particle>. We only need one root particle for this effect so we write </effect> to mark the end of the definition of this effect.
Now we are going to equip the particle with an emitter so that it creates new particles. We do it by adding an <emitter> child tag to the particle tag. The file will now look like this:
<?xml version="1.0"?> <effect> <particle> <emitter> </emitter> </particle> </effect>
The next thing we have to do is explain the emitter what properties the particles it creates are supposed to have. We do so by adding a bunch of <property> child elements to the emitter. Each property tag defines one property of the particles and its possible values. The value can either be fixed, in this case it looks like this: <property name="foo" value="bar" />, or we can define the value in a range between two values like this: <property name="foo" min="bar" max="baz"/>. in the latter case every created particle will have a random value in the given range.
I explained the meaning of each property in the following example with an XML comment. A comment is everything which is written between "<!--" and "-->". When you create more complex particle effects with multiple emitters you should write some comments too so that you remember which part of the file is for what purpose. You should also begin each particle effect with a comment describing how the effect looks, how many particles it requires and how much effect it has on the framerate.
<?xml version="1.0"?> <effect> <particle> <emitter> <property name="output" value= "1" /> <!-- We want one new particle per game tick --> <property name="lifetime" value= "10" /> <!-- we want each particle to survive for 10 game ticks --> <property name="image" value="graphics/particles/star-medium.png"/><!-- We want the particles to look like white stars. --> <property name="position-x" min="0" max="32" /> <!-- We want the particles to be spawned in an area 32 pixels wide...--> <property name="position-y" min="0" max="32" /> <!-- ...32 pixels deep and...--> <property name="position-z" min="0" max="32" /> <!-- ...32 pixels high. --> </emitter> </particle> </effect>
When you want to know more about the properties a particle can have and what exactly the values mean you should check out the particle engine documentation.Exercise: Make a box with the double size and with a different particle:
- TODO: Write about common mistakes when the particle effect doesn't show up ingame.
Moving particles with physics.
- horizontal- and vertical-angle
- Killed by floor contact
Now we are going to have some moving particles with (sort of) realistic physics. We are going to create a "water fountain" effect which will spawn particles at a central point and launch them away so that they fly to the ground in a ballistic arc.
First we have to set the angle in which the particles are defined. We have a horizontal-angle and a vertical-angle. Both are set in degree. In this case we are emitting the particles in a 360Â° horizontal circle and in a fixed 45Â° vertical angle.
Then we have to define the power with which the particles are emitted. It is the initial velocity of them.
To make them fall to the ground we are setting up the gravity. This is the acceleration with which the particles are dragged to the ground. A value of 0.1 means that the vertical speed is reduced by -0.1 pixels per tick per tick.
Note that we don't need a lifetime in this effect. Particles are removed automatically when they touch the ground (or the invisible "ceiling" at 800 pixels, but we don't have this situation here).
<?xml version="1.0"?> <effect> <particle> <emitter> <!-- no position-bla this time - all particles are spawned at the same point. --> <property name="output" value= "4" /> <!-- This time we need some more particles--> <property name="horizontal-angle" min="0" max="360" /> <!-- launched in a full horizontal circle --> <property name="vertical-angle" value="45" /> <!-- launched in a fixed vertical angle --> <property name="power" value="3" /> <!-- Initial speed of 3 pixels per tick --> <property name="gravity" value="0.1" /> <!-- Accelerated by 0.1 pixels per game tick to the ground --> <property name="image" value="graphics/particles/orb-medium.png"/><!-- This time we use the orb sprite. --> </emitter> </particle> </effect>Exercise: Make a "Firehose" which launches the particles in a narrow stream:
- negative range output
In the last exercise we played with water, now we are playing with fire. We are going to modify the effect from the last exercise so that it spawns fireballs which bounce a bit on the ground before they go out.
We start with the effect from last version.
First we have to reduce the output. Unfortunately even one particle per game tick is too much in this case. To make the emitter produce even less particles we use a little trick: We give the output property the random range min="-4" max="1". In 5 of 6 cases the engine will roll a 0 or a negative number. Because the engine can't produce a negative number of particles it will just produce no particles at all during this tick. The result is statistically one particle every 6 game ticks. This is how the line looks:
<property name="output" min="-4" max="1" />
Then we have to change is the color of the particles. We are using the image dyeing system for this purpose. As you might have noticed most particle images are greyscale images. The dyeing system allows us to apply a new color palette to grey areas of images whenever we state the filename of one. This can be done by appending |W:# to the filename followed by a list of RGB colors as hexadecimal triplets. We want red (red:ff green:00 blue:00) orbs for our fireball fountain, so our image line looks like this:
<property name="image" value="graphics/particles/orb-medium.png|W:#ff0000"/>
The last thing we are going to do is making the particles bounce when they reach the ground instead of making them disappear. We are using the bounce property for this. The value of the bounce property is how much of its current vertical speed the particle retains (just upwards instead of downwards) when it bounces from the ground. We want it to have about 70% of its original speed, so we set the value="0.7". Beware: The bounce property has a side effect. Particles with bounce do not get destroyed on ground contact because they technically (or rather mathematically) never stop bouncing. So you have to give them a limited lifetime to avoid them staying alive forever. The value 250, which I found through experimentation, makes the particles lay on the floor for a short moment before they disappear.
<property name="bounce" value="0.7" /> <property name="lifetime" value="250" />
This is the complete effect definition:
<?xml version="1.0"?> <effect> <particle position-x = "0" position-y = "0" position-z = "0"> <emitter> <property name="output" min="-10" max="1" /> <!--Keep it low this time...--> <property name="horizontal-angle" min="0" max="360" /> <property name="vertical-angle" value="70" /> <property name="power" value="4" /> <property name="gravity" value="0.1" /> <property name="bounce" value="0.7" /> <property name="lifetime" value="250" /> <property name="image" value="graphics/particles/orb-medium.png|W:#ff0000"/> </emitter> </particle> </effect>
Cool Fireball Fountain
- nested emitters
OK, OK, I admit, the last effect looked pretty lame. But now I will show you how to make it much cooler. We will do this by giving each of the particles created by the effect a particle emitter on its own and make it leave a trail of sparks. The technique we are using for this is called "nested emitters".
The following example is exactly the same as the last one with the difference that the first <emitter> has another <emitter> child tag in it. This means that each particle created by the first emitter will create the particles described in the second one on its current position every game tick. You could theoretically give these particles a child emitter too to create really complex particle effects.
I will leave explaining the properties of the child emitter as an exercise to the reader.
<?xml version="1.0"?> <effect> <particle position-x = "0" position-y = "0" position-z = "0"> <emitter> <property name="output" min="-4" max="1" /> <!--Keep it low this time...--> <property name="horizontal-angle" min="0" max="360" /> <property name="vertical-angle" value="70" /> <property name="power" value="4" /> <property name="gravity" value="0.1" /> <property name="bounce" value="0.7" /> <property name="lifetime" value="250" /> <property name="image" value="graphics/particles/orb-medium.png|W:#ff0000"/> <emitter> <property name="power" value="0.5"/> <property name="horizontal-angle" min="0" max="360"/> <property name="vertical-angle" min="0" max="360"/> <property name="lifetime" value="20"/> <property name="output" min="0" max="1"/> <property name="image" value="graphics/particles/star-small.png|W:#ff8800,ffffff"/> </emitter> </emitter> </particle> </effect>
Demonstrates the use of nested emitters for pulsating effects using the nomads pipe as an example
- Using nested emitters for timing purpose
Triangle in circle
- Using nested emitter for circular and linear effects
- Using trigonometrical calculations for creating geometric shapes.