- [Instructor] Hi.
This is video Building a Particle System.
In the previous video,
we looked at the SFML drawable class.
In this video,
we're going to take a look at coding the particle class,
coding the particleSystem class,
and using the particleSystem class.
Before we start coding,
it will be helpful to see exactly what it is
we are trying to achieve.
Take a look at this image.
This is an image of a particle effect on a plain background.
We will use the effect in our game.
The first way we achieve the effect is
first we spawn 1000 dots, particles,
one on top of the other at a chosen pixel position.
Then, in each frame of the game,
move each of the 1000 particles outward
at a predetermined but random speed and angle.
Repeat step two for two seconds
and then make the particles disappear.
We will use a vertex array to draw all the dots
and the primitive type of point
to represent each particle visually.
Furthermore, we will inherit from drawable
so that our particle system can take care of drawing itself.
The particle class will be a simple class
that represents just one of the 1000 particles.
Let's start coding.
Right-click Header Files in Solution Explorer
and select Add New Item.
In the Add New Item window,
click Header File and rename the file to Particle.
Finally, click Add button.
We are now ready to code the header file
for the particle class.
Add this code to the Particle.h file.
In this code,
we have two Vector2f objects.
One will represent the horizontal
and vertical coordinates of the particle,
and the other will represent the horizontal
and vertical speed.
When you have a rate of change, speed,
in more than one direction,
the combined values also define a direction.
This is called velocity.
Hence the Vector2f is called m_Velocity.
We also have a number of public functions.
First is the constructor.
It takes a Vector2f
which will be used to let it know what direction velocity
this particle will have.
This implies that the system,
not the particle itself,
will be choosing the velocity.
Next is the update function,
which takes the previous frame has taken.
We will use this to move the particle
by precisely the correct amount.
The final two functions,
setPosition and getPosition,
are used to move the particle into position
and find out its position, respectively.
All these functions will make complete sense
when we code them.
Now, moving on to coding the Particle.cpp file.
First right-click Source Files in the Solution Explorer
and select Add New Item.
In the open window, click C++ File,
and then in the Name field, type Particle.
Lastly, click Add.
We are now ready to code the .cpp file
for the particle class.
Add this highlighted code to the file.
All these functions use concepts we've seen before.
The constructor sets up the m_Velocity value .x
and m_Velocity.y values
using the passed in Vector2f object,
that is, direction.
The update function moves the horizontal
and vertical positions of the particle
by multiplying m_Velocity by the elapsed time, dtAsSeconds.
Notice that to achieve this,
we simply add the two Vector2f objects together.
There is no need to perform calculations
for both the x and y members separately.
The setPosition function initializes the m_Position object
with the passed in values.
The getPosition function returns m_Position
to the calling code.
We now have a fully functioning particle class.
Next we will code a particleSystem class
to spawn and control the particles.
So for coding header file for the particleSystem class,
create a .h file as we always do.
Just keep in mind the particleSystem class
does most of the work for our particle effects.
It is this class that we will create an instance of
in the engine class.
Name the particle system.
So the name would be ParticleSystem.h.
Click on Add once you rename it.
Cool.
We're now ready to code the header file
for the particleSystem class.
Add this code for the particleSystem class.
This is the entire highlighted code.
Let's go through this a bit at a time.
Firstly, notice that we are inheriting from Drawable.
This is what will enable us
to pass our particleSystem instance to m_Window.draw
because ParticleSystem is a drawable.
There is a vector named m_Particles of type Particle.
This vector will hold each and every instance of Particle.
Next we have a VertexArray called m_Vertices.
This will be used to draw all the particles
in the form of a whole bunch of point primitives.
The m_Duration float variable
is how long each effect will last.
We will initialize it in the Constructor function.
The Boolean m_IsRunning variable
will be used to indicate whether the particle system
is currently in use or not.
For now we have set it to false.
Next, in the public section,
we first have the pure virtual function draw
that we will soon implement to handle what happens
when we pass our instance of ParticleSystem
to m_Window.draw.
The init function will prepare the vertex array
and the vector.
It will also initialize all the particle objects
held by the vector
with their velocities and initial positions.
The update function will loop
through each and every particle instance in the vector
and call their individual update functions.
The running function provides access
to the m_IsRunning variable
so that the game engine can query
whether or not the particle system is currently in use.
Let's code the function definitions
to see what goes on inside ParticleSystem.
So for coding ParticleSystem.cpp file,
right-click Source Files in the Solution Explorer
and select Add New Item.
In the Add New Item window, click C++ File,
and then in the Name field, type ParticleSystem.
Finally, click the Add button.
Great.
We're ready to code the .cpp file
for the ParticleSystem class.
We'll split the file into five sections to code
and discuss it better.
Here I've added the first section of the code.
You'll have to add this highlighted code.
Let's take a look at it.
We've added the necessary includes at the start.
Then we have the definition of the init function.
We call setPrimitiveType with Points as the argument
so that m_VertexArray knows what types of primitive
it will be dealing with.
We resize m_Vertices with numParticles,
which was passed to the init function when it was called.
The for loop creates random values for speed and angle.
It then uses trigonometric functions
to convert those values into a vector,
which is stored in the Vector2f direction.
The last thing that happens in the for loop
and the init function
is that the vector is passed into the particle constructor.
The new particle instance is stored in m_Particles
using the push_back function.
Therefore, a call to init with a value of 1000
would mean we have 1000 instances of Particle
with random velocity stashed away in m_Particles
just waiting to blow.
Next add the update function to ParticleSystem.cpp.
I've highlighted the code you need to add.
The update function is simpler than it looks
at first glance.
First of all,
m_Duration is reduced by the passed in time dt.
This is so we know when the two seconds have elapsed.
A vector iterator i is declared for use with m_Particles
and currentVertex is set to zero.
The for loop goes through each of the particle instances
in m_Particles.
For each and every one,
it calls its update function
and passes in dt.
Each particle will update its position.
After the particle has updated itself,
the appropriate vertex in m_Vetices
is updated by using the particle's getPosition function.
At the end of each pass through,
the for loop currentVertex is incremented,
ready for the next vertex.
After the for loop has completed,
the if statement checks whether it's time
to switch off the effect.
If two seconds have elapsed,
m_IsRunning is set to false.
Next add the emitParticles function.
This is the code you need to add.
This is the function we will call
to start the particle system running.
So first we set m_IsRunning to true
and m_Duration to two.
We declare an iterator, i,
to iterate through all the particle objects in m_Particles,
and then we do so in a for loop.
Inside the for loop,
we set each particle and vertex array to Yellow
and set each position to startPosition,
which was passed in as a parameter.
Remember that each particle starts life
in exactly the same position,
but they are each assigned a different velocity.
Lastly we increment current vertex.
Now add the pure virtual draw function definition.
I'm writing the code you'll need to add.
In this code,
we simply use target to call draw
passing in m_Vertices and states.
This is exactly as we discussed
when talking about drawable earlier in the session,
except we pass in our vertex array,
which holds 1000 point primitives,
instead of the hypothetical spaceship sprite.
Finally we have the running function.
The running function is a simple getter function
that returns the value of m_IsRunning.
We will see where this is useful
to determine the current state of the particle system.
To put our particle system to work is straightforward,
especially because we inherited from Drawable.
Open Engine.h,
add an include directive for ParticleSystem.h,
and then we'll write ParticleSystem object, also.
After TextureHolder th,
add a comment.
Create a particle system,
ParticleSystem m_PS.
Next we initialize the system.
Open the Engine.cpp file
and then we'll write a short code
right at the end of the engine constructor.
First write a comment.
Initialize the particle system.
Then we'll write m_PS.init(1000).
So the vertex array and the vector of particle instances
are ready for action.
Moving on to updating the particle system in each frame,
open the Update.cpp file
and we'll write a code for updating the particle system.
We'll write this code after the closing curly braces
and before the End of Update Function comment.
First a comment.
Update the particles.
Then if m_PS is running
inside the block m_PS.update(dtAsSeconds).
All that is needed in the code is the call to update.
Notice that it is wrapped in a check
to make sure the system is currently running.
If it isn't running,
there is no point updating it.
Next let's see starting the particle system.
Open the DetectCollisions.cpp file,
which has the DetectCollisions function in it.
We left a comment in it
when we originally coded it back in section
Building Playable Levels and Collision Detection.
We'll add a code here after this comment.
This is the code to be added.
Here, first the code checks
that the particle system is already running.
If it isn't,
checks if the current tile being checked
is either a water or fire tile.
If either is the case,
it checks whether the character's feet are in contact.
When each of these if statements is true,
the particle system is started
by calling the emitParticles function
and passing in the location
of the center of the character
as the coordinates to start the effect.
Now for drawing the particle system.
First open the Draw.cpp file.
We'll write a few lines of code in full screen code block
as well as right and left code block.
After Draw Bob, write a comment.
Draw the particle system.
And write if m_PS.running function.
Inside the if block,
we write m_Window.draw(m_PS).
This is the best bit.
See how easy it is to draw the particle system?
We pass our instance directly to the m_Window.draw function
that is m_PS
after checking that the particle system is actually running.
We have the same code inside the split screen view also.
Notice I'm adding the same code to left view,
and we have to do that for right view, as well.
So we have drawn particle system
in all the left, right, and full screen code blocks.
You can now run the game
and move one of the character's feet
over the edge of a fire tile.
You'll notice the particle system
burst into life.
I'll show you.
See, there's our particle system.
Awesome.
In this video,
we have learned building the particle system.
Cool.
Next we'll take a look at OpenGL, Shaders,
and GLSL.