粒子系统

粒子系统
粒子系统本质就是同时渲染很多个quad.它有两种运动模式,一种是重力,一种是旋转。
/********************************************************************
 Copyright(C), 2012-2013,
 FileName:ParticleSystem.h
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:41 by
*********************************************************************/
#pragma once
#include "export/Node.h"
#include "base/GameMath.h"
#include "base/Value.h"
#include "base/TextureManager.h"
#include "base/render/Quad.h"
namespace cloud
{
	enum kParticleTypes {
		kParticleTypeGravity,
		kParticleTypeRadial
	};

	// Structure used to hold particle specific information
	typedef struct {
		Vec2 position;
		Vec2 direction;
		Vec2 startPos;
		Color  color;
		Color  deltaColor;
		float rotation;
		float rotationDelta;
		float radialAcceleration;
		float tangentialAcceleration;
		float radius;
		float radiusDelta;
		float angle;
		float degreesPerSecond;
		float particleSize;
		float particleSizeDelta;
		float timeToLive;
	} Particle;

	class ParticleSystem :public Node
	{
	public:
		ParticleSystem(const char* particleList);
		~ParticleSystem();
		void update(float dt);

		//定时喷射粒子和到点结束粒子
		void managerParticleLife( float dt );


		void stopSystem();
		void reset();
		void initParticle(const std::string& dirPath) ;
		bool isAutoRemoveOnFinish() const;
		void setAutoRemoveOnFinish(bool var);
	protected:
		virtual void updateParticleQuads(Particle *currentParticle);
		void initWithDictionary(ValueMap& dictionary);
		// Adds a particle from the particle pool to the emitter
		bool addParticle();
		// Initialises a particle ready for use
		void initParticle(Particle* particle);
		// Set up the arrays that are going to store our particles
		

		
		int _width;
		int _height;
		std::string imgPath;
		std::string imageData;
		bool _isAutoRemoveOnFinish;

		int emitterType;
		//GLKTextureInfo *texture;

		//粒子生命周期
		int _totalParticles;
		int _particleCount;
		float _emissionRate;
		float _emitCounter;	
		float _elapsedTime;
		float _duration;




		Vec2 sourcePosition, sourcePositionVariance;
		float angle, angleVariance;								
		float speed, speedVariance;	
		float radialAcceleration, tangentialAcceleration;
		float radialAccelVariance, tangentialAccelVariance;
		Vec2 gravity;
		float particleLifespan, particleLifespanVariance;			
		Color  startColor, startColorVariance;
		Color  finishColor, finishColorVariance;
		float startParticleSize, startParticleSizeVariance;
		float finishParticleSize, finishParticleSizeVariance;
		
		float rotationStart, rotationStartVariance;
		float rotationEnd, rotationEndVariance;

		int vertexArrayName;

		

		int blendFuncSource, blendFuncDestination; // to _blendFunc

		

		 Particle ivars only used when a maxRadius value is provided.  These values are used for
		 the special purpose of creating the spinning portal emitter
		float maxRadius;						// Max radius at which particles are drawn when rotating
		float maxRadiusVariance;				// Variance of the maxRadius
		float radiusSpeed;					// The speed at which a particle moves from maxRadius to minRadius
		float minRadius;						// Radius from source below which a particle dies
		float minRadiusVariance;				// Variance of the minRadius
		float rotatePerSecond;				// Numeber of degress to rotate a particle around the source pos per second
		float rotatePerSecondVariance;		// Variance in degrees for rotatePerSecond

		 Particle Emitter iVars
		bool  _isActive;
		bool  useTexture;
		int particleIndex;		// Stores the number of particles that are going to be rendered
		int vertexIndex;         // Stores the index of the vertices being used for each particle

		Particle *particles;		// Array of particles that hold the particle emitters particle details
	};
}

/********************************************************************
 Copyright(C), 2012-2013,
 FileName:ParticleSystem.cpp
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:42 by
*********************************************************************/
#include "base/fileUtils/FileUtils.h"
#include "base/TextureManager.h"
#include "base/EngineMacro.h"
#include "ParticleSystem.h"
//#define  POSITION_TYPE

namespace cloud
{	
	ParticleSystem::ParticleSystem(const char* particleList):particles(NULL),_isAutoRemoveOnFinish(false)
	{
		ValueMap dictionary = FileUtils::getInstance()->getDictFormFile(particleList);
		
		initWithDictionary(dictionary);
		
		
	}

	bool ParticleSystem::isAutoRemoveOnFinish() const
	{
		return _isAutoRemoveOnFinish;
	}

	void ParticleSystem::setAutoRemoveOnFinish(bool var)
	{
		_isAutoRemoveOnFinish = var;
	}


	void ParticleSystem::initParticle(const std::string& dirPath)
	{
		particles = (Particle*)malloc( sizeof(Particle) * _totalParticles );
		// By default the particle emitter is active when created
		_isActive = true;
		// Set the particle count to zero
		_particleCount = 0;
		// Reset the elapsed time
		_elapsedTime = 0;	
		scheduleUpdate();
	}

	ParticleSystem::~ParticleSystem()
	{
		if(particles)
		{
			free(particles);
			particles = NULL;
		}
		
	}

	void ParticleSystem::initWithDictionary(ValueMap& dictionary)
	{
		
		// Load all of the values from the XML file into the particle emitter.  The functions below are using the
		// TBXMLAdditions category.  This adds convenience methods to TBXML to help cut down on the code in this method.
		_totalParticles                = dictionary["maxParticles"].asInt();
		emitterType                 = dictionary["emitterType"].asInt();
		sourcePosition              = Vec2(dictionary["sourcePositionx"].asFloat(),dictionary["sourcePositiony"].asFloat());
		sourcePositionVariance      = Vec2(dictionary["sourcePositionVariancex"].asFloat(),dictionary["sourcePositionVariancey"].asFloat());
		speed                       = dictionary["speed"].asFloat();
		speedVariance               = dictionary["speedVariance"].asFloat();
		particleLifespan            = dictionary["particleLifeSpan"].asFloat();
		particleLifespanVariance    = dictionary["particleLifespanVariance"].asFloat();
		angle                       = dictionary["angle"].asFloat();
		angleVariance               = dictionary["angleVariance"].asFloat();
		gravity                     = Vec2(dictionary["gravityx"].asFloat(),dictionary["gravityy"].asFloat());
		radialAcceleration          = dictionary["radialAcceleration"].asFloat();
		radialAccelVariance         = dictionary["radialAccelVariance"].asFloat();
		tangentialAcceleration      = dictionary["tangentialAcceleration"].asFloat();
		tangentialAccelVariance     = dictionary["tangentialAccelVariance"].asFloat();
		startColor                  = Color(dictionary["startColorRed"].asFloat(),dictionary["startColorGreen"].asFloat(),dictionary["startColorBlue"].asFloat(),dictionary["startColorAlpha"].asFloat());
		startColorVariance          = Color(dictionary["startColorVarianceRed"].asFloat(),dictionary["startColorVarianceGreen"].asFloat(),dictionary["startColorVarianceBlue"].asFloat(),dictionary["startColorVarianceAlpha"].asFloat());
		finishColor                 = Color(dictionary["finishColorRed"].asFloat(),dictionary["finishColorGreen"].asFloat(),dictionary["finishColorBlue"].asFloat(),dictionary["finishColorAlpha"].asFloat());
		finishColorVariance         = Color(dictionary["finishColorVarianceRed"].asFloat(),dictionary["finishColorVarianceGreen"].asFloat(),dictionary["finishColorVarianceBlue"].asFloat(),dictionary["finishColorVarianceAlpha"].asFloat());
		
		startParticleSize           = dictionary["startParticleSize"].asFloat();
		startParticleSizeVariance   = dictionary["startParticleSizeVariance"].asFloat();
		finishParticleSize          = dictionary["finishParticleSize"].asFloat();
		finishParticleSizeVariance  = dictionary["finishParticleSizeVariance"].asFloat();
		_duration                    = dictionary["duration"].asFloat();
		blendFuncSource             = dictionary["blendFuncSource"].asInt();
		blendFuncDestination        = dictionary["blendFuncDestination"].asInt();

		// These paramters are used when you want to have the particles spinning around the source location
		maxRadius                   = dictionary["maxRadius"].asFloat();
		maxRadiusVariance           = dictionary["maxRadiusVariance"].asFloat();
		minRadius                   = dictionary["minRadius"].asFloat();
		minRadiusVariance           = dictionary["minRadiusVariance"].asFloat();
		rotatePerSecond             = dictionary["rotatePerSecond"].asFloat();
		rotatePerSecondVariance     = dictionary["rotatePerSecondVariance"].asFloat();
		rotationStart               = dictionary["rotationStart"].asFloat();
		rotationStartVariance       = dictionary["rotationStartVariance"].asFloat();
		rotationEnd                 = dictionary["rotationEnd"].asFloat();
		rotationEndVariance         = dictionary["rotationEndVariance"].asFloat();

		// Calculate the emission rate
		_emissionRate                = _totalParticles / particleLifespan;
		_emitCounter                 = 0;

		imgPath = dictionary["textureFileName"].asString();

		//_texture = TextureManager::getInstance()->createTexture(_imgPath.c_str(),_width,_height);
		imageData = dictionary["textureImageData"].asString();

	
	}

	// Adds a particle from the particle pool to the emitter
	bool ParticleSystem::addParticle()
	{
		// If we have already reached the maximum number of particles then do nothing
		if (_particleCount == _totalParticles)
			return false;

		// Take the next particle out of the particle pool we have created and initialize it
		Particle *particle = &particles[_particleCount];
		initParticle(particle);

		// Increment the particle count
		_particleCount++;

		// Return YES to show that a particle has been created
		return true;
	}

	// Initialises a particle ready for use
	void ParticleSystem::initParticle(Particle* particle)
	{
		// Init the position of the particle.  This is based on the source position of the particle emitter
		// plus a configured variance.  The RANDOM_MINUS_1_TO_1 macro allows the number to be both positive
		// and negative

		particle->position.x = sourcePosition.x + sourcePositionVariance.x * RANDOM_MINUS_1_TO_1();
		particle->position.y = sourcePosition.y + sourcePositionVariance.y * RANDOM_MINUS_1_TO_1();
		particle->startPos.x = sourcePosition.x;
		particle->startPos.y = sourcePosition.y;

		// Init the direction of the particle.  The newAngle is calculated using the angle passed in and the
		// angle variance.
		GLfloat newAngle = angleToRadian(angle + angleVariance * RANDOM_MINUS_1_TO_1());

		// Create a new GLKVector2 using the newAngle
		Vec2 vector = Vec2(cosf(newAngle), sinf(newAngle));

		// Calculate the vectorSpeed using the speed and speedVariance which has been passed in
		GLfloat vectorSpeed = speed + speedVariance * RANDOM_MINUS_1_TO_1();

		// The particles direction vector is calculated by taking the vector calculated above and
		// multiplying that by the speed
		particle->direction = vector * vectorSpeed;

		// Calculate the particles life span using the life span and variance passed in
		particle->timeToLive = MAX(0, particleLifespan + particleLifespanVariance * RANDOM_MINUS_1_TO_1());

		float startRadius = maxRadius + maxRadiusVariance * RANDOM_MINUS_1_TO_1();
		float endRadius = minRadius + minRadiusVariance * RANDOM_MINUS_1_TO_1();

		// Set the default diameter of the particle from the source position
		particle->radius = startRadius;
		particle->radiusDelta = (endRadius - startRadius) / particle->timeToLive;
		particle->angle = angleToRadian(angle + angleVariance * RANDOM_MINUS_1_TO_1());
		particle->degreesPerSecond = angleToRadian(rotatePerSecond + rotatePerSecondVariance * RANDOM_MINUS_1_TO_1());

		particle->radialAcceleration = radialAcceleration + radialAccelVariance * RANDOM_MINUS_1_TO_1();
		particle->tangentialAcceleration = tangentialAcceleration + tangentialAccelVariance * RANDOM_MINUS_1_TO_1();

		// Calculate the particle size using the start and finish particle sizes
		GLfloat particleStartSize = startParticleSize + startParticleSizeVariance * RANDOM_MINUS_1_TO_1();
		GLfloat particleFinishSize = finishParticleSize + finishParticleSizeVariance * RANDOM_MINUS_1_TO_1();
		particle->particleSizeDelta = ((particleFinishSize - particleStartSize) / particle->timeToLive);
		particle->particleSize = MAX(0, particleStartSize);

		// Calculate the color the particle should have when it starts its life.  All the elements
		// of the start color passed in along with the variance are used to calculate the star color
		Color start = Color(0, 0, 0, 0);
		start.r = startColor.r + startColorVariance.r * RANDOM_MINUS_1_TO_1();
		start.g = startColor.g + startColorVariance.g * RANDOM_MINUS_1_TO_1();
		start.b = startColor.b + startColorVariance.b * RANDOM_MINUS_1_TO_1();
		start.a = startColor.a + startColorVariance.a * RANDOM_MINUS_1_TO_1();

		// Calculate the color the particle should be when its life is over.  This is done the same
		// way as the start color above
		Color end = Color(0, 0, 0, 0);
		end.r = finishColor.r + finishColorVariance.r * RANDOM_MINUS_1_TO_1();
		end.g = finishColor.g + finishColorVariance.g * RANDOM_MINUS_1_TO_1();
		end.b = finishColor.b + finishColorVariance.b * RANDOM_MINUS_1_TO_1();
		end.a = finishColor.a + finishColorVariance.a * RANDOM_MINUS_1_TO_1();

		// Calculate the delta which is to be applied to the particles color during each cycle of its
		// life.  The delta calculation uses the life span of the particle to make sure that the 
		// particles color will transition from the start to end color during its life time.  As the game
		// loop is using a fixed delta value we can calculate the delta color once saving cycles in the 
		// update method

		particle->color = start;
		particle->deltaColor.r = ((end.r - start.r) / particle->timeToLive);
		particle->deltaColor.g = ((end.g - start.g) / particle->timeToLive);
		particle->deltaColor.b = ((end.b - start.b) / particle->timeToLive);
		particle->deltaColor.a = ((end.a - start.a) / particle->timeToLive);

		// Calculate the rotation
		GLfloat startA = rotationStart + rotationStartVariance * RANDOM_MINUS_1_TO_1();
		GLfloat endA = rotationEnd + rotationEndVariance * RANDOM_MINUS_1_TO_1();
		particle->rotation = startA;
		particle->rotationDelta = (endA - startA) / particle->timeToLive;


	} 

	void ParticleSystem::stopSystem()
	{
		_isActive = false;
		_elapsedTime = 0;
		_emitCounter = 0;
	}	

	void ParticleSystem::reset()
	{
		_isActive = true;
		_elapsedTime = 0;
		for (int i = 0; i < _particleCount; i++) {
			Particle *p = &particles[i];
			p->timeToLive = 0;
		}
		_emitCounter = 0;
		_emissionRate = _totalParticles / particleLifespan;
	}

	void ParticleSystem::update(float dt)
	{
		managerParticleLife(dt);


		// Reset the particle index before updating the particles in this emitter
		particleIndex = 0;
#ifdef POSITION_TYPE
		Vec2 currentPosition = Vec2::ZERO;
		if (_positionType == PositionType::FREE)
		{
			currentPosition = this->convertToWorldSpace(Vec2::ZERO);
		}
		else if (_positionType == PositionType::RELATIVE)
		{
			currentPosition = _position;
		}
#endif
		// Loop through all the particles updating their location and color
		while (particleIndex < _particleCount) {

			// Get the particle for the current particle index
			Particle *currentParticle = &particles[particleIndex];

			// FIX 1
			// Reduce the life span of the particle
			currentParticle->timeToLive -= dt;

			// If the current particle is alive then update it
			if (currentParticle->timeToLive > 0) {

				// If maxRadius is greater than 0 then the particles are going to spin otherwise they are effected by speed and gravity
				if (emitterType == kParticleTypeRadial) {

					// FIX 2
					// Update the angle of the particle from the sourcePosition and the radius.  This is only done of the particles are rotating
					currentParticle->angle += currentParticle->degreesPerSecond * dt;
					currentParticle->radius += currentParticle->radiusDelta * dt;

					Vec2 tmp;
					tmp.x = sourcePosition.x - cosf(currentParticle->angle) * currentParticle->radius;
					tmp.y = sourcePosition.y - sinf(currentParticle->angle) * currentParticle->radius;
					currentParticle->position = tmp;

				} else {
					Vec2 tmp, radial, tangential;

					radial = Vec2(0,0);

					// By default this emitters particles are moved relative to the emitter node position
					Vec2 positionDifference = currentParticle->startPos;
					currentParticle->position = currentParticle->position - positionDifference;

					if (currentParticle->position.x || currentParticle->position.y)
						radial = currentParticle->position.getNormalized();

					tangential = radial;
					radial = radial * currentParticle->radialAcceleration;

					float newy = tangential.x;
					tangential.x = -tangential.y;
					tangential.y = newy;
					tangential = tangential * currentParticle->tangentialAcceleration;

					tmp = radial+tangential + gravity;
					tmp = tmp * dt;
					currentParticle->direction = currentParticle->direction + tmp;
					tmp = currentParticle->direction * dt;
					currentParticle->position = currentParticle->position + tmp;

					// Now apply the difference calculated early causing the particles to be relative in position to the emitter position
					currentParticle->position = currentParticle->position + positionDifference;
				}

				// Update the particles color
				currentParticle->color.r += currentParticle->deltaColor.r * dt;
				currentParticle->color.g += currentParticle->deltaColor.g * dt;
				currentParticle->color.b += currentParticle->deltaColor.b * dt;
				currentParticle->color.a += currentParticle->deltaColor.a * dt;

				// Update the particle size
				currentParticle->particleSize += currentParticle->particleSizeDelta * dt;
				currentParticle->particleSize = MAX(0, currentParticle->particleSize);

				// Update the rotation of the particle
				currentParticle->rotation += currentParticle->rotationDelta * dt;

				// As we are rendering the particles as quads, we need to define 6 vertices for each particle
				

				// If a rotation has been defined for this particle then apply the rotation to the vertices that define
				// the particle
#ifdef POSITION_TYPE
				Vec2    newPos;

				if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE)
				{
					Vec2 diff = currentPosition - p->startPos;
					newPos = p->pos - diff;
				} 
				else
				{
					newPos = p->pos;
				}
#endif
				updateParticleQuads(currentParticle);
				

				// Update the particle and vertex counters
				particleIndex++;
			} else {

				// As the particle is not alive anymore replace it with the last active particle 
				// in the array and reduce the count of particles by one.  This causes all active particles
				// to be packed together at the start of the array so that a particle which has run out of
				// life will only drop into this clause once
				if (particleIndex != _particleCount - 1)
					particles[particleIndex] = particles[_particleCount - 1];

				_particleCount--;

				if( _particleCount == 0 && _isAutoRemoveOnFinish )
				{
					this->unscheduleUpdate();
					_parent->removeNodeAndChild(this);
					return;
				}
			}
		}
	}

	void ParticleSystem::updateParticleQuads(Particle *currentParticle)
	{

	}

	void ParticleSystem::managerParticleLife( float dt )
	{
		// If the emitter is active and the emission rate is greater than zero then emit particles
		if (_isActive && _emissionRate)
		{
			GLfloat rate = 1.0f/_emissionRate;//每个粒子的喷射时间

			if (_particleCount < _totalParticles)
				_emitCounter += dt;

			while (_particleCount < _totalParticles && _emitCounter > rate) {
				addParticle();
				_emitCounter -= rate;
			}

			_elapsedTime += dt;

			if (_duration != -1 && _duration < _elapsedTime)
				stopSystem();
		}
	}

}
渲染块
/********************************************************************
 Copyright(C), 2012-2013,
 FileName:ParticleSystem.h
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:41 by
*********************************************************************/
#pragma once
#include "export/particle/ParticleSystem.h"
#include "export/Sprite.h"

namespace cloud
{
	class ParticleSystemQuad :public ParticleSystem
	{
	public:
		ParticleSystemQuad(const char* particleList);
		~ParticleSystemQuad();
		void initParticleQuads(const std::string& dirPath) ;
		void render();
	protected:
		void updateParticleQuads(Particle *currentParticle);
		bool  _opacityModifyRGB;
		Quad* _quads;
		GLuint _textureID;
		QuadCommand      _quadCommand; 
		BlendFunc        _blendFunc; 
	};
}

/********************************************************************
 Copyright(C), 2012-2013,
 FileName:ParticleSystem.cpp
 Description:
 Author:cloud
 Created:2014/11/07
 history:
7:11:2014 15:42 by
*********************************************************************/
#include "base/fileUtils/FileUtils.h"
#include "base/TextureManager.h"
#include "base/EngineMacro.h"
#include "export/Particle/ParticleSystemQuad.h"
#include "base/render/Renderer.h"

namespace cloud
{	
	ParticleSystemQuad::ParticleSystemQuad(const char* particleList):ParticleSystem(particleList),_quads(NULL),_textureID(0)
	{
		std::string dirPath = particleList;
		int pos = dirPath.rfind("/");
		if (pos > -1)
		{
			dirPath = dirPath.substr(0,pos+1);
		}
		else
		{
			dirPath = "";
		}
		
		initParticleQuads(dirPath);
	}

	ParticleSystemQuad::~ParticleSystemQuad()
	{
		if(_quads)
		{
			free(_quads);
			_quads = NULL;
		}
	}

	void ParticleSystemQuad::initParticleQuads(const std::string& dirPath)
	{
		_quads = (Quad*)malloc( _totalParticles * sizeof(Quad));
		memset(_quads, 0, _totalParticles * sizeof(Quad));
		for(int i = 0;i < _totalParticles; ++i)
		{
			_quads[i].tl._texCoord = Vec2(0,1);
			_quads[i].bl._texCoord = Vec2(0,0);
			_quads[i].tr._texCoord = Vec2(1,1);
			_quads[i].br._texCoord = Vec2(1,0);	
		}
			

		_opacityModifyRGB = false;
		//TODO:图片alpha是否预处理二进制数据


		if (_textureID == 0 )
		{
			//搜索路径为plist目录下的
			imgPath = dirPath + imgPath;
			_textureID = TextureManager::getInstance()->createTexture(imgPath.c_str(),_width,_height);
			if (_textureID == 0 && imageData.length() > 0)
			{
				//TODO:解析图片二进制数据
			}


		}
		_blendFunc = BlendFunc(blendFuncSource,blendFuncDestination);	

		ParticleSystem::initParticle(dirPath);
	}

	void ParticleSystemQuad::render()
	{
		updateMatrix();
				
		_quadCommand.init(_quads,_textureID,particleIndex,_blendFunc,_model);
		Renderer::getInstance()->addQuadCommand(&_quadCommand);
	}

	void ParticleSystemQuad::updateParticleQuads(Particle *currentParticle)
	{
		float halfSize = currentParticle->particleSize * 0.5f;
		if (currentParticle->rotation) {
			
			float x1 = -halfSize;
			float y1 = -halfSize;
			float x2 = halfSize;
			float y2 = halfSize;
			float x = currentParticle->position.x;
			float y = currentParticle->position.y;
			float r = angleToRadian(currentParticle->rotation);
			float cr = cosf(r);
			float sr = sinf(r);
			float ax = x1 * cr - y1 * sr + x;
			float ay = x1 * sr + y1 * cr + y;
			float bx = x2 * cr - y1 * sr + x;
			float by = x2 * sr + y1 * cr + y;
			float cx = x2 * cr - y2 * sr + x;
			float cy = x2 * sr + y2 * cr + y;
			float dx = x1 * cr - y2 * sr + x;
			float dy = x1 * sr + y2 * cr + y;

			_quads[particleIndex].bl._position.x = ax;
			_quads[particleIndex].bl._position.y = ay;
			_quads[particleIndex].bl._color = currentParticle->color;


			_quads[particleIndex].br._position.x = bx;
			_quads[particleIndex].br._position.y = by;
			_quads[particleIndex].br._color = currentParticle->color;

			_quads[particleIndex].tl._position.x = dx;
			_quads[particleIndex].tl._position.y = dy;
			_quads[particleIndex].tl._color = currentParticle->color;

			_quads[particleIndex].tr._position.x = cx;
			_quads[particleIndex].tr._position.y = cy;
			_quads[particleIndex].tr._color = currentParticle->color;
		} else {
			// Using the position of the particle, work out the four vertices for the quad that will hold the particle
			// and load those into the _quads array.
			_quads[particleIndex].bl._position.x = currentParticle->position.x - halfSize;
			_quads[particleIndex].bl._position.y = currentParticle->position.y - halfSize;
			_quads[particleIndex].bl._color = currentParticle->color;

			_quads[particleIndex].br._position.x = currentParticle->position.x + halfSize;
			_quads[particleIndex].br._position.y = currentParticle->position.y - halfSize;
			_quads[particleIndex].br._color = currentParticle->color;

			_quads[particleIndex].tl._position.x = currentParticle->position.x - halfSize;
			_quads[particleIndex].tl._position.y = currentParticle->position.y + halfSize;
			_quads[particleIndex].tl._color = currentParticle->color;

			_quads[particleIndex].tr._position.x = currentParticle->position.x + halfSize;
			_quads[particleIndex].tr._position.y = currentParticle->position.y + halfSize;
			_quads[particleIndex].tr._color = currentParticle->color;
		}
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值