Particle system

Editor

The editor is made using Dear ImGui.
The editor is being worked on pretty much all the time, as I am working to add new functions to the system in collaboration with our procedural artists.

Some features from the editor are:

  • Change color of the particles
  • Change spawnrate
  • Make the particles spawn within a circle or square
  • Add force/wind to particles
  • Multiple bools for different interactions such as allowing movement, rotation, shrinking, growing, fading and more. 
  • Loading particle systems with all parameters
  • Loading sprites
  • Saving all parameters into a .json file
One of the earliest VFX in our game and engine
Change the color of particles
Change the spawn time of particles
One of the earliest VFX in our game and engine
Change the force/wind
5 particle systems running at the same time

The particle system can spawn particles on a trigger as shown below. 

Particle system triggered when flying enemies are destroyed

Particle manager

The particle manager exists for the duration of the application runtime.

class ParticleManager
{
public:
	ParticleManager();
	~ParticleManager();
	void Add2D(ParticleSystem* aParicleSystem);
	void AddDebug2D(ParticleSystem aParicleSystem);
	void Add3D(ParticleSystem3D* aParicleSystem);
	void AddDebug3D(ParticleSystem3D aParicleSystem);
	void Clear();
	void Render(DreamEngine::SpriteDrawer& aSpriteDrawer);
	void RenderToGBuffer(DreamEngine::SpriteDrawer& aSpriteDrawer);
	void Update(float aDeltaTime);
	void SetCameraTransform(DreamEngine::Transform* aCameraTransform);
	void SetActionCamera(bool aActionCamera);
	void SetWorldScale(float aScale);
	void SetPlayerPosition(DE::Vector3f aPlayerPos);

#ifndef _RETAIL
	void ImGui2DDebugMenu();
	void ImGui3DDebugMenu();
#endif // !_RETAIL
private:
	std::vector<ParticleSystem*> my2DParticleSystems;
	std::vector<ParticleSystem> my2DDebugParticleSystems;
	std::vector<ParticleSystem3D*> my3DParticleSystems;
	std::vector<ParticleSystem3D> my3DDebugParticleSystems;
	std::array<char[50], 10> myParticleSystemNames;
	float myWorldScale;
	int myCurrentParticleSystem;
	int mySizeOf2DParticleSystems;
	int mySizeOf3DParticleSystems;
	bool myPaticle2DDebugMode;
	bool myPaticle3DDebugMode;
	bool myActionCamera;
	bool myShouldResetParticleSystem;
	DreamEngine::Transform* myCameraTransform;
	DE::Vector3f myPlayerPosition;
};

Particle system

The particle system holds all the particles and all of the debug data connected to the editor.

void ParticleSystem3D::Init(int aSize)
{
	myParticleAmount = aSize;
	myTotalTime = 0;
	for (size_t i = 0; i < myParticleAmount; i++)
	{
		Particle3D particle;
		if (myPosPtr != 0)
		{
			particle.Init(*myPosPtr, myParticleStartInstance.myColor, myParticleScale, myParticleStartDecayTime, { (float)myParticlesShouldMove,(float)myParticlesShouldRotate,(float)myParticlesShouldShrink,(float)myParticlesShouldFade }, myParticleDirMin, myParticleDirMax, myCameraTransform, myActionCamera);
			//particle.SetOrigin(*myPosPtr);
		}
		else
		{
			particle.Init(myPos, myParticleStartInstance.myColor, myParticleScale, myParticleStartDecayTime, { (float)myParticlesShouldMove,(float)myParticlesShouldRotate,(float)myParticlesShouldShrink,(float)myParticlesShouldFade }, myParticleDirMin, myParticleDirMax, myCameraTransform, myActionCamera);
			//particle.SetOrigin(myPos);
		}
		particle.SetParticleSize(ourParticleData.myTexture->CalculateTextureSize());
		particle.SetAlpha(0);
		particle.SetForce(myForce);
		myParticles.push_back(particle);
		myParticleInstances.push_back(particle.GetSpriteInstance());
	}
}

To load a particle system a saved .json file is loaded and puts all the corresponding data into the system and then initializes the particle system.

void ParticleSystem3D::LoadParticleSystem(std::string aParticleSystemPath)
{
	myLoadedData = true;
	std::ifstream file(aParticleSystemPath);
	if (std::filesystem::exists(aParticleSystemPath))
	{
		nlohmann::json jsonData = nlohmann::json::parse(file);
		file.close();

		if (!jsonData["ParticleAmount"].is_null())
		{
			myParticleAmount = jsonData["ParticleAmount"];
		}
		if (!jsonData["DecayTime"].is_null())
		{
			myParticleStartDecayTime = jsonData["DecayTime"];
		}
		if (!jsonData["LifeTime"].is_null())
		{
			myLifeTime = jsonData["LifeTime"];
		}

                ... ("more similar data input")

		for (int i = 0; i < myParticles.size(); i++)
		{
			myParticles[i].SetAlpha(0);
			myParticles[i].SetForce(myForce);
			myParticleInstances[i] = myParticles[i].GetSpriteInstance();
		}

		myUvs.clear();

		Init(myParticleAmount);
	}
}