Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / TDK's Particle Tutorial For DB Classic

Author
Message
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 6th Feb 2007 08:28 Edited at: 14th May 2007 13:54

TDK's Particle Tutorial For Beginners


If you are using DB Pro, then you have native support for particles. If however you are using DBC then you don't. This doesn't mean however that you can't have particles in your DBC programs, you just have to code them manually...

But first, just in case you don't know, what exactly are particles?

Well, a particle isn't the easiest of things to explain, so it's probably best to think of a smoke particle. Both clouds and smoke aren't solid objects - they are made up of trillions of tiny particles which move together in a fluid motion.

In DB, each particle is an object and as we obviously can't have that number of objects, we cheat by having a lot fewer, but make them bigger.

To prevent slowdown in DB due to high polygon counts, we use the simplest DB object - the plain - and make it as small as we can to fit the scale of world we are using.

We texture each plain and ghost them (make them semi-transparent) to give that 'fuzzy' look when lots of them are placed close to each other.

Created carefully, you can create acceptable effects for smoke, clouds, dust, steam, water spray, fireworks and so on. You can even get a very nice effect which makes street lights 'glow'.

The key to good particles however is the textures you use. Below is a typical image for a particle. As you can see, it's effectively a coloured sphere on a black background which is bright in the centre and fades to black as it moves outwards.



When you ghost a plain which is textured with this image, the black parts are transparent and it looks just like a soft glowing ball. Put hundreds of them together and/or stretch them and you have smoke or a cloud.

You don't have to stick to traditional particle texture image shapes. You can have square, triangular, star or snowflake shapes too. The important thing is to make the shape gradually fade to the background colour towards the extremities.

Most decent paint programs have an option to do this, but I find that a good effect is the Gaussian Blur in Paintshop Pro.

Simply create a 128x128 canvas with black backround and create a solid white circle (see first image below). Make sure it's positioned in the centre of the image.





Apply the Gaussian blur. The second image uses a blur value of 12 but you can experiment - just make sure that the outermost edges of the blur stay within the image frame or you will see flat edges on your particle.

And that's it. As mentioned before, the initial shape can be whatever you want - this one for example!



Note: You can have texture images bigger than 128x128, but the bigger they are, the bigger the impact on frame rate. No doubt many will say that 128x128 is too big and should be 32x32 or 64x64 pixels max.


What Next?

Once you have your textures, it's simply a case of creating plains, texturing and ghosting them and finally controlling their positions in your program. To be honest, it's only really the control of them that's tricky.

One of the reasons for this is that due to the sheer number of objects we are controlling, each one has a finite 'lifespan', at the end of which the particle is killed off. When dead, the object can be deleted and re-used. Without using this method we wouldn't be able to create nearly enough objects in DB.

And, to keep track of all these object's states and positions we depend heavily on functions and arrays - lots of them, so if you are not up to scratch on arrays or functions, I suggest you go and read my tutorials on both subjects here:

Functions: http://forum.thegamecreators.com/?m=forum_view&t=96040&b=7
Arrays: http://forum.thegamecreators.com/?m=forum_view&t=96069&b=7&p=0

Oh yes - another thing to bear in mind is that plains are two-dimensional 3D objects. I know that sounds daft, but plains are only 2D surfaces. They have an X and Y dimension, (width and height), but no depth. In other words, if you look at them from the side, they disappear.

So, your particle code has to make sure that they always face the camera or they won't be seen!

I'll be using the very first image above in the example code snippets, so if you right click on it you can save it to a folder with the name Figb2.jpg for use later...


Emitters:

The last thing to cover before we get to the actual coding is emitters. This is the fancy name given to the point in space which each particle originates. For example, with a 'Volcano' firework (the cone shaped one), the particles originate at the point of the cone.

Creating that particular firework with particles, you would create a cone and set the emitter X,Y,Z position at the apex of the cone.

You can also have multiple emitters - each with a different colour and shaped particle.

Combining different particles can create some interesting and nice effects. But, the thing to remember is that all the particles from a single emitter will be the same and the more emitters you have - the slower your program.


The Code!

In it's simplest form, creating a particle in DB is as follows:



I've just added a bit of rotation code in the main do loop for effect.

But that's just a single particle. When we need to control hundreds of particles, we need a control system which uses arrays.

Essentially, we create a particle and use a 'slot' in an array to store all the required information about that particle. All particles have a lifespan, after which they die and the slot is freed up for using again with another particle.

So now it's time to get our hands dirty with some real particle coding, but for this we need a game plan!

We are going to have one emitter and use 100 particles (plain objects). They will have a specific lifespan and when they die, we will re-use them. For this reason, as a minimum, we need to keep track of the following information for every single particle:

* It's number
* It's age (lifespan)
* It's X position
* It's Y position
* It's Z position
* It's X direction (velocity)
* It's Y direction (velocity)
* It's Z direction (velocity)

Later, you can add in other factors in like gravity, friction and so on...

The easiest way to store this information is in a multi-dimensioned array with:

Dim Particle#(100,6)

This allows for up to 100 particles and 7 pieces of information. For example:

Particle#(ParticleNum,0) = the particle's age
Particle#(ParticleNum,1) = the particle's X position
Particle#(ParticleNum,2) = the particle's Y position
Particle#(ParticleNum,3) = the particle's Z position
Particle#(ParticleNum,4) = the particle's X velocity
Particle#(ParticleNum,5) = the particle's Y velocity
Particle#(ParticleNum,6) = the particle's Z velocity

Our function merely checks the value in Particle#(ParticleNum,0) - it's 'age' - and if it's greater than 0 (zero) then the particle is alive. It then deducts one from the value found, calculates the particle's new position and positions it.

If the age is 0 (zero) then it's age is reset, it's X,Y,Z position is reset to that of the emitter and new random velocities for X, Y and Z are created ready for the next particle.

The following example uses a single emitter and particles are emitted in all directions. So let's see some code and then we'll go over the less obvious bits...



The first lines of interest are in the Dims section. The Particle#(100,6) one is covered above, but those following are arrays which have been used as global variables - hence the (0) on the end of each.

Dimensioning them here allows us to use these arrays as normal type variables globally and access them inside the function.

On the following lines we set NumParticles(0) to 100 - the number of particles we want to use, LifeSpan(0) to 100 so each particle will only last 100 cycles of our loop and EmitterX#(0), EmitterY#(0) and EmitterZ#(0) all to 0.0 - making all our particles originate from 0,0,0 in 3D space.

The next block simply creates 100 plains, textures them with the image loaded earlier and ghosts them to make them transparent.

Finally, we position the camera to get a good view, point it at the emitter at 0,0,0 and drop into the main loop.

The main loop continuously calls the UpdatePSystem() function and Sync's the screen. So what's going on inside the function?...

Well, we simply count in a loop from 1 to NumParticles(0) (100) and check to see if each particle is still alive. If it is, we deduct one as described above.

We then add the X, Y and Z velocities stored in Particle#(T,4), Particle#(T,5) and Particle#(T,6) to the particle's current X, Y and Z positions (stored in Particle#(T,1), Particle#(T,2) and Particle#(T,3)).

We finally position the object at it's new position and make sure that it's facing the camera.

If the particle's age is set to 0 (zero), we re-initialise all the setting so it starts again at the emitter - effectively creating a new particle.

Random values are used for both the lifespan and the X, Y and Z velocities. If the lifespan of all particles were the same, they would all die together and start together. This is handy for an explosion effect, but not what we want here.

Try changing the line:

Particle#(T,0) = Rnd(LifeSpan(0)/2)+LifeSpan(0)/2

to:

Particle#(T,0) = LifeSpan(0)

to see what I mean. As an aside, feel free to change any parts of the example programs to see what effect it has. Experimenting can't do any harm and if it helps you figure out what's going on then all the better...

The velocity values are random because we want the particles to be emitted at lots of different angles. So, Particle#(T,4) is the number of degrees left and right on the X axis. Using Rnd(40)-20 means we get random number between -20 and +20.

Try changing it to Rnd(10)-5 and see how the X axis spread is reduced.

Likewise, changing the YVelocity line to:

Particle#(T,5) = 0.0

results in no spread across the Y axis (up/down) and all the particles spread out as though rolling on a flat table. (Don't forget that the camera is slightly elevated in the program, looking slightly down on the particles).

So, restricting the spread of particles on the X, Y and Z axis you can create effects like rocket thrust - though it would need to take into account gravity and other things, making it much more complicated than what we've covered here.

Here's a simple image to explain what's going on...



As you can see, negative values for the X velocity make the particles head to the left while positive values make them head to the right. A value of 0 (zero) makes them go neither left or right, but (assuming there's a positive Y velocity) will instead head stright up.

Likewise for the Y and Z axis: Positive Y velocities send particles up and negative ones down. Positive Z velocities send particles away from you and negative ones towards you. Using these axis, you can direct particles in any direction you wish.

For example, fireworks send all their particles upwards not downwards and spread out along the X and Z axis. To do this, looking at the above diagram we can see that the Y velocity values must always be positive and the X and Z velocity values need to be both positive and negative.

Some firework code:



Notice it's basically the same as the last code snippet - but with a few tweaks in the settings. All we've done really is make the particles a little smaller to look like sparks and directed the particles in an upwards direction like a firework.

You will find that creating most effects use exactly the same code, but with different shaped and coloured particles, along with little tweaks to the movement values.

However, our firework doesn't look quite right yet. What we need is...


Gravity

To simulate gravity, all we need to do is deduct a small amount off each particle's Y position before we position it on the screen.



And there we have our firework. Try altering the gravity value to see what effect it has on the firework.


Clouds/Smoke

Once again - same program, different settings. This snippet attempts to look like you are flying through clouds, but a similar effect could be used for smoke in a burning building - or steam:




Starfield Effect:

Yet another variation on the same theme - the old starfield effect...



Well that's the end of this introduction to particles in DB Classic for beginners. Obviously there's lots more you can do now you know the basics.

If anyone finds this useful and would be interested in a more advanced part 2, then let me know.

There are many more tutorials and example code snippets on TGPF - my game programming forums. Click on the link below - it's free to join and everyone's welcome!

Visit TGPF

TDK_Man

citybee
17
Years of Service
User Offline
Joined: 27th Jan 2007
Location:
Posted: 8th Feb 2007 02:48
the fireworks particle doesnt work. it says that the function udatePSystem() is weird.

thx
Duke Blue Devils
18
Years of Service
User Offline
Joined: 11th Mar 2006
Location:
Posted: 8th Feb 2007 02:54
@TDK
Thanks for taking the time to make this tutorial. Didn't you make a program that could generate particles? I remember I used to have it.

@citybee
You need to make a texture.


Visit the official Chicago Rush website
http://chicagorush.servegame.com/index.php
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 8th Feb 2007 03:04
citybee:

I thought you were a DBPro user. This tutorial is only for DBC users who don't have particle commands. In any case:

Quote: "I'll be using the very first image above in the example code snippets, so if you right click on it you can save it to a folder with the name Fig 2.jpg for use later..."


Duke Blue Devils:

Yes - I did. I've recently dug it out again in order to (eventually) finish it!

TDK_Man

Anto
18
Years of Service
User Offline
Joined: 30th Oct 2005
Location: Brisbane, AUS
Posted: 9th Feb 2007 04:20
Thank you TDK

It a really good tutorial and very helpful, looking forward to see some more.

Cheers Anto
Lucifer
18
Years of Service
User Offline
Joined: 26th Dec 2005
Location:
Posted: 9th Feb 2007 14:46
tdk, you should sticky this!!! : D


i like pancakes..
TDK
Retired Moderator
21
Years of Service
User Offline
Joined: 19th Nov 2002
Location: UK
Posted: 9th Feb 2007 23:10
Quote: "you should sticky this"


It already is.

http://forum.thegamecreators.com/?m=forum_view&t=99497&b=7

(number 14).

TDK_Man

Login to post a reply

Server time is: 2024-03-29 15:08:05
Your offset time is: 2024-03-29 15:08:05