-
Sparticles Engine : Particle engine developed by sparkon
LINKS TO IMAGES
http://postimage.org/image/mm3mbwy69/]http://postimage.org/image/mm3mbwy69/]http://postimage.org/image/mm3mbwy69/ (http://postimage.org/image/mm3mbwy69/)
http://postimage.org/image/q3fx7zj85/ (http://postimage.org/image/q3fx7zj85/)
( don't blame me for imagination )
Hello guys! this is my first "big" project with SFML, it maybe stupid for most of you, but for me it's really important. I was coding my game when i felt the need to create a particle engine, but i didn't want a costum-made one just for my game so i wrote this. It's a simple particle engine based on SFML 2.0 and nothing else.
As soon as i'll post this i'll write a couple of tutorials on how to use it, even though it will become clear while reading its features.
FEATURES
The library is composed by two main classes :
-> DirectionalEmitter
-> ExplosionEmitter
as the names suggest they have been create with two different purposes, even though if you work out your directionalemitter you can achieve pretty much ( not exactly) the same effect of the explosionemitter.
Since for the two emitters there are a lot of data that you need ( position, heading,speed,blending etc.....) i've created two costum structs to make the construction easier :
-> DirectionalEmitterMode
-> ExplosionEmitterMode
They work the same way of sf::VideoMode :
-> you initialize them
-> you choose your values
-> you put it in the Emitter constructor
Since there are a lot of variables, you can choose to initialize it with pre-defined values and tweak them later or hardcode them directly in the constructor. To make the whole thing working there is just 1 thing that you absolutely have to do before constructing the emitter, and it is :
CHOOSING THE PARTICLE
Sparticles emitter allows you to use 4 different kinds of "look" for your particles :
1 - TEXTURE Use your asset - fast,but not the fastest
2 - CONVEX SHAPE choose your cool shape - slowest one
3 - CIRCLE SHAPE
4 - PIXEL ARRAY Just pass the size of the screen and the color you want! easiest and fastest
Everything it's really straighforward. For the Pixel array i've added a few modes ( more will come in the future ) to make the effect really cool :
-> Color Range Avaiable for both emitters
-> Rainbow Mode DirectionalEmitter
-> RandomColor ExplosionEmitter
Again.. as the names suggest you can choose a random color within a predefined range, rainbow mode starting from a predefined range.
Color Range in my opinion is the best one, the particle will start from color A (you choose it ) and will change color ( based on lifetime ) til dying with color B ( you choose it ofc).
ENGINE
The last class you need to be aware of is the ParticleEngine that is nothing else than a higher-level wrapper to manage all your emitters. Every emitter has got his own ID you can access from. You add an emitter by passing its pointer and then place an Update in your main loop.
LINKS
The project is hosted on GitHub, but i've also added a link to mediafire.
In the ZIP file you'll find :
-> compiled headers (debug and release)
-> source code
-> include ( with headers file )
-> Tutorial ( not yet, i'll post it as soon as i can )
P.S : Excuse my english please.
MEDIAFIRE
http://www.mediafire.com/?1bben2471vl229c
GITHUB PROJECT
https://github.com/sparkon/Sparticles (https://github.com/sparkon/Sparticles)
CODE SAMPLES
Sample Explosion with pixels
#include "sparticles.h"
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow Window(sf::VideoMode(800,600,32),"PARTICLE SYSTEM TEST");
sp::ParticleEngine Engine;
Window.setFramerateLimit(120);
sp::ExplosionEmitterMode dmode(sp::Vector2D(400,300));
dmode.set_pixel_array(sf::Color(255,0,0),sf::Color(255,255,0));
dmode.n_of_particles_ = 6000;
dmode.life_time_ = 100;
dmode.blend_mode_ = sf::BlendAdd;
dmode.random_speed_ = 1;
sp::ExplosionEmitter* emitt = new sp::ExplosionEmitter(Window,dmode);
unsigned int ID = Engine.NewEmitter(emitt);
sf::Clock clock;
while ( Window.isOpen())
{
sf::Event Event;
while ( Window.pollEvent(Event))
{
switch(Event.type)
{
case sf::Event::Closed :
Window.close();
break;
default :
break;
}
}
Window.clear(sf::Color(0,0,0));
sf::Time dt = clock.restart();
Engine.Update(dt);
Window.display();
}
return 0;
}
Directional emitter sample
#include "sparticles.h"
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow Window(sf::VideoMode(800,600,32),"PARTICLE SYSTEM TEST");
sp::ParticleEngine Engine;
Window.setFramerateLimit(120);
sp::DirectionalEmitterMode dmode(sp::Vector2D(0,0));
dmode.set_texture("Particle0.png");
dmode.n_of_particles_ = 10000;
dmode.burst_rate = 0.001;
dmode.life_time_ = 150;
dmode.reuse_ = true;
dmode.blend_mode_ = sf::BlendAdd;
sp::DirectionalEmitter* emitt = new sp::DirectionalEmitter(Window,dmode);
unsigned int ID = Engine.NewEmitter(emitt);
sf::Clock clock;
while ( Window.isOpen())
{
sf::Event Event;
while ( Window.pollEvent(Event))
{
switch(Event.type)
{
case sf::Event::Closed :
Window.close();
break;
default :
break;
}
}
Window.clear(sf::Color(0,0,0));
sf::Time dt = clock.restart();
Engine.Update(dt);
Window.display();
}
return 0;
}
-
Images link's broken.
You can do namespace sp {} around everything in your cpp files too.
Don't put h files into both include and src folder, include sfml with <> instead of "".
Every header should do
#ifndef smt
#define smt
//code
#endif
Instead of what you're doing now with some of them:#ifndef UTILITIES_INCLUDE_H
#define UTILITIES_INCLUDE_H
#include "utilities.h"
#endif // utilities included
-
Posting more images. Thanks for reply
-
Well your images are still not what one would want, like this:
(http://s18.postimage.org/wh50b8o47/SC02.png) (http://postimage.org/image/q3fx7zj85/)
Also it would've been interesting if you had added an example to your code, so we could actually be able to test it, without having to go through the code and figure out how things work...
-
The Vector2D is weird.. ???
What's the point of it since this is exclusivly for sfml you could use sf vectors and define bunch of functions to do what you do with your vector.
// Deconstructor
~Vector2D(){};
That's destructor. But that's not that important.
Vector2D operator+(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Vector2D operator-(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Vector2D operator*(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Why three operators do the same and not take const reference to right?
Vector2D Scale(double S)
{
x_ /= S;
y_ /= S;
return *this;
}
Why doesn't that do *= instead of /= and return temp copy instead of reference?
double x_;
double y_;
Public vars with trailing underscores are.. weird?
-
Also it would've been interesting if you had added an example to your code, so we could actually be able to test it, without having to go through the code and figure out how things work...
Adding some code samples!
-
The Vector2D is weird.. ???
What's the point of it since this is exclusivly for sfml you could use sf vectors and define bunch of functions to do what you do with your vector.
// Deconstructor
~Vector2D(){};
That's destructor. But that's not that important.
Vector2D operator+(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Vector2D operator-(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Vector2D operator*(Vector2D& right)
{
return (Vector2D(x_ * right.x_,y_ * right.y_));
}
Why three operators do the same and not take const reference to right?
Vector2D Scale(double S)
{
x_ /= S;
y_ /= S;
return *this;
}
Why doesn't that do *= instead of /= and return temp copy instead of reference?
double x_;
double y_;
Public vars with trailing underscores are.. weird?
yes.. i know i was gonna replace that class with sf::Vector2f asap. Thanks for the hint!
-
void sp::ParticleEngine::DestroyAll()
{
for ( int i = 0; i < active_emitters_.size(); i++)
{
active_emitters_.erase(active_emitters_.begin() +i);
}
}
That loop looks dangerous. It'll only delete half of contents(every element with even index) of active_emitters. Is that intended?
-
void sp::ParticleEngine::DestroyAll()
{
for ( int i = 0; i < active_emitters_.size(); i++)
{
active_emitters_.erase(active_emitters_.begin() +i);
}
}
That loop looks dangerous. It'll only delete half of contents(every element with even index) of active_emitters. Is that intended?
I'm sorry but i don't get it. why even index? are you referring to "+i"?
-
int main()
{
std::vector<int> test;
for(int i=0;i<15;++i)test.push_back(i);
for ( int i = 0; i < test.size(); i++)
{
test.erase(test.begin() +i);
}
for(int i=0;i<test.size();++i)
std::cout<<test[i]<<std::endl;
}
Run that to see what happens, also, int should be unsigned int or unsigned or vectors sizetype to silence compiler warnings. Vector emptying should be done by clear() call on it.
If you're desperate for double precision the use sf::Vector<double> and typedef it in your namespace.
unsigned int sp::ParticleEngine::NewEmitter(BaseEmitter* Emitter)
{
// Adding it to the list
active_emitters_.push_back(Emitter);
// Adding ID TO EMITTER
Emitter->set_id(m_next_valid_id_);
// Returning the ID
return m_next_valid_id_;
// Increasing ID
m_next_valid_id_ += 1;
}
The last line of this code will not execute... ever..
What's the point of get by index instead of get by id?
Much of things there could be improved. Many inefficient loops, inconsistent passing of things: references/pointers. What's the point of engine if you have to manage lifetime of emiters yourself anyway. Maybe create factory functions that take some definition struct and create apropriate emitter from it(like box2d api). Missing consts ect.
I'm sorry but this code is full of errors.
-
You should really work on your code, there are many mistakes and questionable style. To name some:
- Use clear() to clear a container, instead of your loop of doom.
- Iterating over std::vector and erasing elements in the middle leads to quadratic time complexity (highly inefficient).
- Statements after return are never exectuted (ParticleEngine::NewEmitter()).
- I dont think sp::DirectionalEmitter::Setup() is valid C++, put the functions inside a namespace definition.
- Avoid new and delete and use automatic memory management and RAII.
- Prefer static_cast over C casts.
- List the parameters also in the function declaration, because the declaration usually forms the API.
- Make more variables private.
- Consider const-correctness.
- Don't use references when you need copies (for parameters).
- Group functionality. Your classes have tons of variables which could be gathered to an own class.
- Include only the headers you need (#include <SFML/Graphics.hpp> is useful for short example codes, but not for bigger libraries).
- Don't define empty default constructors or destructors.
- Header guards must cover the whole header, not its include directives.
There are many more. I don't want to offend you, but it looks like you are lacking important C++ knowledge. Maybe you could read a good book like the C++ Primer in parallel to development...?
-
Nexus you are not offending me :) you're just helping! thanks for all the hints. I'm gonna study more and will retry later!. Thanks to FRex too.
-
Nexus you are not offending me :) you're just helping! thanks for all the hints. I'm gonna study more and will retry later!. Thanks to FRex too.
Woah, someone who doesn't get upset when they're given C++ criticism?
Faith in humanity is restored just a little...