⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 particle.cpp

📁 经典开源游戏glest的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ==============================================================
//	This file is part of Glest Shared Library (www.glest.org)
//
//	Copyright (C) 2001-2008 Marti駉 Figueroa
//
//	You can redistribute this code and/or modify it under 
//	the terms of the GNU General Public License as published 
//	by the Free Software Foundation; either version 2 of the 
//	License, or (at your option) any later version
// ==============================================================

#include "particle.h"

#include <cassert>
#include <algorithm>

#include "util.h"
#include "particle_renderer.h"
#include "math_util.h"
#include "leak_dumper.h"

using namespace Shared::Util;

namespace Shared{ namespace Graphics{

// =====================================================
//	class ParticleSystem
// =====================================================

ParticleSystem::ParticleSystem(int particleCount){

	//init particle vector
	blendMode = bmOne;
	particles= new Particle[particleCount];
	state= sPlay;
	aliveParticleCount=0;
	active= true;
	visible= true;

	//vars
	texture= NULL;
	particleObserver= NULL;
	
	//params
	this->particleCount= particleCount;
	maxParticleEnergy= 250;
	varParticleEnergy= 50;
	pos= Vec3f(0.0f);
	color= Vec4f(1.0f);
	colorNoEnergy= Vec4f(0.0f);
	emissionRate= 15;
	speed= 1.0f;
}

ParticleSystem::~ParticleSystem(){
	delete [] particles;
}


// =============== VIRTUAL ======================

//updates all living particles and creates new ones
void ParticleSystem::update(){

	if(state!=sPause){
		for(int i=0; i<aliveParticleCount; ++i){
			updateParticle(&particles[i]);

			if(deathTest(&particles[i])){
				
				//kill the particle
				killParticle(&particles[i]);

				//mantain alive particles at front of the array
				if(aliveParticleCount>0){
					particles[i]= particles[aliveParticleCount];
				}

			}
		}

		if(state!=sFade){
			for(int i=0; i<emissionRate; ++i){
				Particle *p= createParticle();
				initParticle(p, i);
			}
		}
	}
}

void ParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
	if(active){
		pr->renderSystem(this);
	}
}


// =============== SET ==========================

void ParticleSystem::setState(State state){
	this->state= state;
}

void ParticleSystem::setTexture(Texture *texture){
	this->texture= texture;
}

void ParticleSystem::setPos(Vec3f pos){
	this->pos= pos;
}

void ParticleSystem::setColor(Vec4f color){
	this->color= color;
}

void ParticleSystem::setColorNoEnergy(Vec4f colorNoEnergy){
	this->colorNoEnergy= colorNoEnergy;
}

void ParticleSystem::setEmissionRate(int emissionRate){
	this->emissionRate= emissionRate;
}

void ParticleSystem::setMaxParticleEnergy(int maxParticleEnergy){
	this->maxParticleEnergy= maxParticleEnergy; 
}

void ParticleSystem::setVarParticleEnergy(int varParticleEnergy){
	this->varParticleEnergy= varParticleEnergy;
}

void ParticleSystem::setParticleSize(float particleSize){
	this->particleSize= particleSize;
}

void ParticleSystem::setSpeed(float speed){
	this->speed= speed;
}

void ParticleSystem::setActive(bool active){
	this->active= active;
}

void ParticleSystem::setObserver(ParticleObserver *particleObserver){
	this->particleObserver= particleObserver;
}

void ParticleSystem::setVisible(bool visible){
	this->visible= visible;
}

// =============== MISC =========================
void ParticleSystem::fade(){
	assert(state==sPlay);
	state= sFade;
	if(particleObserver!=NULL){
		particleObserver->update(this);
	}
}

int ParticleSystem::isEmpty() const{
	assert(aliveParticleCount>=0);
	return aliveParticleCount==0 && state!=sPause;
}

// =============== PROTECTED =========================

// if there is one dead particle it returns it else, return the particle with 
// less energy
Particle * ParticleSystem::createParticle(){

	//if any dead particles
	if(aliveParticleCount<particleCount){
		++aliveParticleCount;
		return &particles[aliveParticleCount-1];
	}

	//if not
	int minEnergy= particles[0].energy;
	int minEnergyParticle= 0;

	for(int i=0; i<particleCount; ++i){
		if(particles[i].energy<minEnergy){
			minEnergy= particles[i].energy;
			minEnergyParticle= i;
		}
	}

	return &particles[minEnergyParticle];
}

void ParticleSystem::initParticle(Particle *p, int particleIndex){
	p->pos= pos;
	p->lastPos= p->pos;
	p->speed= Vec3f(0.0f);
	p->accel= Vec3f(0.0f);
	p->color= Vec4f(1.0f, 1.0f, 1.0f, 1.0);
	p->size= particleSize;
	p->energy= maxParticleEnergy + random.randRange(-varParticleEnergy, varParticleEnergy);
}

void ParticleSystem::updateParticle(Particle *p){
	p->lastPos= p->pos;
	p->pos= p->pos + p->speed;
	p->speed= p->speed + p->accel;
	p->energy--;
}

bool ParticleSystem::deathTest(Particle *p){
	return p->energy <= 0;
}

void ParticleSystem::killParticle(Particle *p){
	aliveParticleCount--;
}

// ===========================================================================
//  FireParticleSystem
// ===========================================================================


FireParticleSystem::FireParticleSystem(int particleCount): ParticleSystem(particleCount){
	
	radius= 0.5f;
	speed= 0.01f;
	windSpeed= Vec3f(0.0f);
	
	setParticleSize(0.6f);
	setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
}

void FireParticleSystem::initParticle(Particle *p, int particleIndex){
	ParticleSystem::initParticle(p, particleIndex);
	
	float ang= random.randRange(-2.0f*pi, 2.0f*pi);
	float mod= fabsf(random.randRange(-radius, radius));
	
	float x= sinf(ang)*mod;
	float y= cosf(ang)*mod;
	
	float radRatio= sqrtf(sqrtf(mod/radius));

	p->color= colorNoEnergy*0.5f + colorNoEnergy*0.5f*radRatio;
	p->energy= static_cast<int>(maxParticleEnergy*radRatio) + random.randRange(-varParticleEnergy, varParticleEnergy);
	p->pos= Vec3f(pos.x+x, pos.y+random.randRange(-radius/2, radius/2), pos.z+y); 
	p->lastPos= pos;
	p->size= particleSize;
	p->speed= Vec3f(0, speed+speed*random.randRange(-0.5f, 0.5f), 0) +  windSpeed;
}

void FireParticleSystem::updateParticle(Particle *p){
	p->lastPos= p->pos;
	p->pos= p->pos+p->speed;
	p->energy--;

	if(p->color.x>0.0f)
		p->color.x*= 0.98f;
	if(p->color.y>0.0f)
		p->color.y*= 0.98f;
	if(p->color.w>0.0f)
		p->color.w*= 0.98f;

	p->speed.x*=1.001f;

}

// ================= SET PARAMS ====================

void FireParticleSystem::setRadius(float radius){
	this->radius= radius;
}

void FireParticleSystem::setWind(float windAngle, float windSpeed){
	this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
	this->windSpeed.y= 0.0f;
	this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}

// ===========================================================================
//  RainParticleSystem
// ===========================================================================


RainParticleSystem::RainParticleSystem(int particleCount):ParticleSystem(particleCount){
	setWind(0.0f, 0.0f);
	setRadius(20.0f);

	setEmissionRate(25);
	setParticleSize(3.0f);
	setColor(Vec4f(0.5f, 0.5f, 0.5f, 0.3f));
	setSpeed(0.2f);
}

void RainParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
	pr->renderSystemLineAlpha(this);
}

void RainParticleSystem::initParticle(Particle *p, int particleIndex){
	ParticleSystem::initParticle(p, particleIndex);

	float x= random.randRange(-radius, radius);
	float y= random.randRange(-radius, radius);
	
	p->color= color;
	p->energy= 10000;
	p->pos= Vec3f(pos.x+x, pos.y, pos.z+y); 
	p->lastPos= p->pos;
	p->speed= Vec3f(random.randRange(-speed/10, speed/10), -speed, random.randRange(-speed/10, speed/10)) + windSpeed;
}

bool RainParticleSystem::deathTest(Particle *p){
	return p->pos.y<0;
}

void RainParticleSystem::setRadius(float radius){
	this->radius= radius;

}	

void RainParticleSystem::setWind(float windAngle, float windSpeed){
	this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
	this->windSpeed.y= 0.0f;
	this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}

// ===========================================================================
//  SnowParticleSystem
// ===========================================================================

SnowParticleSystem::SnowParticleSystem(int particleCount):ParticleSystem(particleCount){
	setWind(0.0f, 0.0f);
	setRadius(30.0f);

	setEmissionRate(2);
	setParticleSize(0.2f);
	setColor(Vec4f(0.8f, 0.8f, 0.8f, 0.8f));
	setSpeed(0.025f);
}

void SnowParticleSystem::initParticle(Particle *p, int particleIndex){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -