Create an early particle system
This commit is contained in:
parent
823c0b37c6
commit
d5eeeb4553
|
@ -1,3 +1,4 @@
|
||||||
# Add examples as a subdirectory
|
# Add examples as a subdirectory
|
||||||
add_subdirectory(snake)
|
add_subdirectory(snake)
|
||||||
add_subdirectory(animation)
|
add_subdirectory(animation)
|
||||||
|
add_subdirectory(particles)
|
|
@ -0,0 +1,15 @@
|
||||||
|
cmake_minimum_required (VERSION 3.6)
|
||||||
|
project(ParticlesExample)
|
||||||
|
|
||||||
|
add_executable(particles src/main.cpp)
|
||||||
|
|
||||||
|
# Link headers and source files.
|
||||||
|
file(GLOB_RECURSE source_list src/*.cpp)
|
||||||
|
target_sources(particles PRIVATE ${source_list})
|
||||||
|
target_include_directories(particles PUBLIC include)
|
||||||
|
|
||||||
|
# Link simpleengine
|
||||||
|
target_link_libraries(particles PUBLIC simpleengine)
|
||||||
|
|
||||||
|
# Set standard to C++17
|
||||||
|
set_target_properties(particles PROPERTIES CXX_STANDARD 17 CXX_EXTENSIONS OFF)
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/21/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Rect.hpp>
|
||||||
|
#include <SFML/Graphics/RenderStates.hpp>
|
||||||
|
#include <SFML/System/Vector3.hpp>
|
||||||
|
|
||||||
|
#include <simpleengine/game.h>
|
||||||
|
#include <simpleengine/event.h>
|
||||||
|
#include <simpleengine/entity.h>
|
||||||
|
#include <simpleengine/range.h>
|
||||||
|
|
||||||
|
// Particle
|
||||||
|
#include <simpleengine/particle/emitter.h>
|
||||||
|
#include <simpleengine/particle/particle_property.h>
|
||||||
|
#include <simpleengine/particle/properties/random_lifetime_property.h>
|
||||||
|
#include <simpleengine/particle/properties/random_velocity_property.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <ios>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace se = simpleengine;
|
||||||
|
|
||||||
|
class ParticleEmitter : public se::particle::ParticleEmitter {
|
||||||
|
private:
|
||||||
|
using super = se::particle::ParticleEmitter;
|
||||||
|
|
||||||
|
sf::Sprite sprite;
|
||||||
|
sf::Texture texture;
|
||||||
|
|
||||||
|
super::ParticlePropertyVector properties = {
|
||||||
|
std::make_shared<se::particle::RandomVelocityParticleProperty>(se::Range2f(-1.5f, 1.5f, -1.5f, 1.5f)),
|
||||||
|
std::make_shared<se::particle::RandomLifetimeParticleProperty>(se::Rangef(1'500, 9'500))
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
ParticleEmitter() : super(texture, sf::Vector2f(350, 350), 0.4, 5, 1500, se::Range2f(-15, 15, -15, -15), se::particle::ParticleAttributes{0, sf::Vector2f(), 5, sf::Vector2f(2, 2)}, properties) {
|
||||||
|
texture.loadFromFile("particle.png"); // The particle I tested with was 5x5 pixels
|
||||||
|
texture.setSmooth(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(const float& delta_time) override {
|
||||||
|
super::Update(delta_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render(sf::RenderTarget* target) override {
|
||||||
|
super::Render(target);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
simpleengine::Game game(700, 700, "SimpleEngine - Particles Example");
|
||||||
|
game.AddEvent(new ParticleEmitter());
|
||||||
|
|
||||||
|
return game.Run();
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/21/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_PARTICLE_EMITTER_H
|
||||||
|
#define SIMPLEENGINE_PARTICLE_EMITTER_H
|
||||||
|
|
||||||
|
#include "../event.h"
|
||||||
|
#include "particle_property.h"
|
||||||
|
#include "particle.h"
|
||||||
|
#include "../random.h"
|
||||||
|
#include "../range_2.h"
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Rect.hpp>
|
||||||
|
#include <SFML/Graphics/RectangleShape.hpp>
|
||||||
|
#include <SFML/Graphics/Sprite.hpp>
|
||||||
|
#include <SFML/System/Clock.hpp>
|
||||||
|
|
||||||
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
namespace particle {
|
||||||
|
struct ParticleAttributes {
|
||||||
|
uint32_t lifetime_ms;
|
||||||
|
sf::Vector2f start_velocity;
|
||||||
|
float rotation_velocity = 0;
|
||||||
|
sf::Vector2f scale = sf::Vector2f(1, 1);
|
||||||
|
|
||||||
|
/* ParticleAttributes(uint32_t lifetime_ms, sf::Vector2f start_velocity, float rotation_velocity) : lifetime_ms(lifetime_ms), start_velocity(start_velocity), rotation_velocity(rotation_velocity) {
|
||||||
|
|
||||||
|
} */
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParticleEmitter : public simpleengine::Event {
|
||||||
|
protected:
|
||||||
|
using ParticlePropertyPtr = std::shared_ptr<simpleengine::particle::ParticleProperty>;
|
||||||
|
using ParticlePropertyVector = std::vector<ParticlePropertyPtr>;
|
||||||
|
public:
|
||||||
|
explicit ParticleEmitter(sf::Texture& texture, sf::Vector2f position, double emit_variance, uint32_t emit_count, uint32_t particle_count, Range2f particle_range, ParticleAttributes attributes, ParticlePropertyVector& properties)
|
||||||
|
: texture(texture), position(position), emit_variance(emit_variance), emit_count(emit_count), particle_count(particle_count), particle_range(particle_range), attributes(attributes), properties(properties) {
|
||||||
|
time.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetProperties(ParticlePropertyVector& properties) {
|
||||||
|
this->properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Update(const float& delta_time) override {
|
||||||
|
for (std::vector<simpleengine::particle::Particle>::iterator it = particles.begin(); it != particles.end(); ) {
|
||||||
|
it->Update(delta_time);
|
||||||
|
|
||||||
|
if (it->IsDestroying()) {
|
||||||
|
it = particles.erase(it);
|
||||||
|
} else {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (particles.size() < particle_count) {
|
||||||
|
if (random.NextInRange(0, 1) < emit_variance) {
|
||||||
|
for (uint32_t i = 0; i < emit_count; i++) {
|
||||||
|
Particle particle(texture, attributes.start_velocity, attributes.lifetime_ms, attributes.rotation_velocity, properties);
|
||||||
|
|
||||||
|
// Offset the position of the particle randomly
|
||||||
|
sf::Vector2f new_pos;
|
||||||
|
new_pos.x = random.NextInRange(particle_range.min_x, particle_range.max_x);
|
||||||
|
new_pos.y = random.NextInRange(particle_range.min_y, particle_range.max_y);
|
||||||
|
new_pos += position;
|
||||||
|
particle.GetSprite().setPosition(new_pos);
|
||||||
|
|
||||||
|
particle.GetSprite().setScale(attributes.scale.x, attributes.scale.y);
|
||||||
|
|
||||||
|
particles.emplace_back(std::move(particle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render(sf::RenderTarget* target) override {
|
||||||
|
for (simpleengine::particle::Particle particle : particles) {
|
||||||
|
particle.Render(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
sf::Texture& texture;
|
||||||
|
sf::Vector2f position;
|
||||||
|
double emit_variance;
|
||||||
|
uint32_t emit_count;
|
||||||
|
uint32_t particle_count;
|
||||||
|
Range2f particle_range;
|
||||||
|
ParticleAttributes attributes;
|
||||||
|
ParticlePropertyVector& properties;
|
||||||
|
|
||||||
|
std::vector<simpleengine::particle::Particle> particles;
|
||||||
|
sf::Clock time;
|
||||||
|
simpleengine::Random<double> random;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_PARTICLE_EMITTER_H
|
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/21/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_PARTICLE_H
|
||||||
|
#define SIMPLEENGINE_PARTICLE_H
|
||||||
|
|
||||||
|
#include "../event.h"
|
||||||
|
#include "particle_property.h"
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Rect.hpp>
|
||||||
|
#include <SFML/Graphics/Sprite.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
namespace particle {
|
||||||
|
class Particle : public simpleengine::Event {
|
||||||
|
private:
|
||||||
|
using super = simpleengine::Event;
|
||||||
|
protected:
|
||||||
|
using ParticlePropertyPtr = std::shared_ptr<simpleengine::particle::ParticleProperty>;
|
||||||
|
using ParticlePropertyVector = std::vector<ParticlePropertyPtr>;
|
||||||
|
public:
|
||||||
|
Particle(sf::Texture& texture, sf::Vector2f velocity, uint32_t lifetime_ms, float rotation_velocity,
|
||||||
|
ParticlePropertyVector properties) : simpleengine::Event(nullptr), velocity(velocity), lifetime_ms(lifetime_ms),
|
||||||
|
rotation_velocity(rotation_velocity), properties(properties) {
|
||||||
|
age_clock.restart();
|
||||||
|
sprite.setTexture(texture);
|
||||||
|
|
||||||
|
for (ParticlePropertyPtr property : properties) {
|
||||||
|
property->OnParticleSpawn(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Update(const float& delta_time) override {
|
||||||
|
if (age_clock.getElapsedTime().asMilliseconds() >= lifetime_ms) {
|
||||||
|
super::Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ParticlePropertyPtr property : properties) {
|
||||||
|
property->Update(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.move(velocity.x, velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render(sf::RenderTarget* target) override {
|
||||||
|
target->draw(sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Sprite& GetSprite() {
|
||||||
|
return sprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void SetVelocity(const sf::Vector2f& velocity) {
|
||||||
|
this->velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sf::Vector2f& GetVelocity() {
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRotationVelocity(const float& rotation_velocity) {
|
||||||
|
this->rotation_velocity = rotation_velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float& GetRotationVelocity() {
|
||||||
|
return rotation_velocity;
|
||||||
|
}
|
||||||
|
private: */
|
||||||
|
|
||||||
|
const sf::Time GetAge() const {
|
||||||
|
return age_clock.getElapsedTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Sprite sprite;
|
||||||
|
sf::Vector2f velocity;
|
||||||
|
uint32_t lifetime_ms;
|
||||||
|
float rotation_velocity;
|
||||||
|
ParticlePropertyVector properties;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sf::Clock age_clock;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_PARTICLE_H
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/21/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_PARTICLE_PROPERTY_H
|
||||||
|
#define SIMPLEENGINE_PARTICLE_PROPERTY_H
|
||||||
|
|
||||||
|
#include "../event.h"
|
||||||
|
|
||||||
|
#include <SFML/Graphics/RenderStates.hpp>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
namespace particle {
|
||||||
|
class Particle;
|
||||||
|
class ParticleProperty {
|
||||||
|
public:
|
||||||
|
virtual void OnParticleSpawn(simpleengine::particle::Particle& particle) = 0;
|
||||||
|
virtual void Update(simpleengine::particle::Particle& particle) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_PARTICLE_PROPERTY_H
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/22/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_RANDOM_LIFETIME_PROPERTY_H
|
||||||
|
#define SIMPLEENGINE_RANDOM_LIFETIME_PROPERTY_H
|
||||||
|
|
||||||
|
#include "../particle_property.h"
|
||||||
|
#include "../../range.h"
|
||||||
|
#include "../../random.h"
|
||||||
|
#include "../particle.h"
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
namespace particle {
|
||||||
|
class RandomLifetimeParticleProperty : public ParticleProperty {
|
||||||
|
public:
|
||||||
|
RandomLifetimeParticleProperty(simpleengine::Rangef range) : range(range) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnParticleSpawn(simpleengine::particle::Particle& particle) override {
|
||||||
|
simpleengine::Random<float> rand;
|
||||||
|
particle.lifetime_ms = rand.NextInRange(range.min, range.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(simpleengine::particle::Particle& particle) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
simpleengine::Rangef range;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_RANDOM_LIFETIME_PROPERTY_H
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/22/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_RANDOM_VELOCITY_PROPERTY_H
|
||||||
|
#define SIMPLEENGINE_RANDOM_VELOCITY_PROPERTY_H
|
||||||
|
|
||||||
|
#include "../particle_property.h"
|
||||||
|
#include "../../range_2.h"
|
||||||
|
#include "../../random.h"
|
||||||
|
#include "../particle.h"
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
namespace particle {
|
||||||
|
class RandomVelocityParticleProperty : public ParticleProperty {
|
||||||
|
public:
|
||||||
|
RandomVelocityParticleProperty(simpleengine::Range2f range) : range(range) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnParticleSpawn(simpleengine::particle::Particle& particle) override {
|
||||||
|
simpleengine::Random<float> rand;
|
||||||
|
sf::Vector2f velocity;
|
||||||
|
velocity.x = rand.NextInRange(range.min_x, range.max_x);
|
||||||
|
velocity.y = rand.NextInRange(range.min_y, range.max_y);
|
||||||
|
|
||||||
|
particle.velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(simpleengine::particle::Particle& particle) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
simpleengine::Range2f range;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_RANDOM_VELOCITY_PROPERTY_H
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/22/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_RANGE_H
|
||||||
|
#define SIMPLEENGINE_RANGE_H
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
template<typename T>
|
||||||
|
class Range {
|
||||||
|
public:
|
||||||
|
Range() = default;
|
||||||
|
Range(T min, T max) : min(min), max(max) {}
|
||||||
|
|
||||||
|
T min = std::numeric_limits<T>::min();
|
||||||
|
T max = std::numeric_limits<T>::max();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Range<float> Rangef;
|
||||||
|
typedef Range<int> Rangei;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_RANGE_H
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// Created by SeanOMik on 3/22/2021.
|
||||||
|
// Github: https://github.com/SeanOMik
|
||||||
|
// Email: seanomik@gmail.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIMPLEENGINE_RANGE_2_H
|
||||||
|
#define SIMPLEENGINE_RANGE_2_H
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace simpleengine {
|
||||||
|
template<typename T>
|
||||||
|
class Range2 {
|
||||||
|
public:
|
||||||
|
Range2() = default;
|
||||||
|
Range2(T min_x, T max_x, T min_y, T max_y) : min_x(min_x), max_x(max_x), min_y(min_y), max_y(max_y) {}
|
||||||
|
|
||||||
|
T min_x = std::numeric_limits<T>::min();
|
||||||
|
T max_x = std::numeric_limits<T>::max();
|
||||||
|
T min_y = std::numeric_limits<T>::min();
|
||||||
|
T max_y = std::numeric_limits<T>::max();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Range2<float> Range2f;
|
||||||
|
typedef Range2<int> Range2i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SIMPLEENGINE_RANGE_H
|
Loading…
Reference in New Issue