// GraphicsTemplate.cpp
// 
//////////////////////////////////////////////////////////////////////////////////////////
// includes 
//////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <vector>
#include <ctime>

#define PI				  3.1415926
#define Base_num	      1100
#define Base_LifeTime     120
#define Base_size		  1.5

using namespace std;

//////////////////////////////////////////////////////////////////////////////////////////
// externals 
//////////////////////////////////////////////////////////////////////////////////////////
extern cRenderClass graphics;

typedef struct Particle
{
	double size;
	double direction;
	double speed;
	int lifeTime;
	int Time;
	double cur_X, cur_Y;
	sRGB color;
}Particle;

vector<Particle> g_particleV;
bool g_pause = false;
Particle *p1;
bool fireworkstatus = false;
bool firstfireworkstatus = false;
bool status = true;//status是ture代表此时爆炸烟花结束，已经删除内存的上升烟花动态分配了内存。
bool increasingFlag = true;//表明烟花是在上升还是需要创建，true表明上升，false表明需要创建上升烟花对象。
double original_X = 0, original_Y = 0;//用来存储上升烟花最后消散的位置。
int time1 = 1;

void initParticle(Particle &p) {//用来初始化结构体Particle的属性
	p.size = rand() % (int)Base_size + Base_size + 0.5;
	p.direction = 270;
	while (p.direction > 269 && p.direction < 271)
	{
		p.direction = rand() % 360;
	}
	p.direction = PI * p.direction / 180.0;//把p.direction转换成具体的度数。
	p.speed = ((double)(rand() % 101)) / 150.0-0.1;
	//p.color.r = ((double)(rand() % 201)) / 250.0;
	//p.color.g = ((double)(rand() % 201)) / 250.0;
	//p.color.b = ((double)(rand() % 201)) / 250.0;
	p.color.r = ((double)(rand() % 100))/110;
	p.color.g = ((double)(rand() % 100))/110;
	p.color.b = ((double)(rand() % 100))/110;
	p.Time = 0;
	p.lifeTime = rand() % Base_LifeTime + Base_LifeTime-10;
	p.cur_X = 0;
	p.cur_Y = 0;
}

void initfirstParticle(Particle *p) {//用来初始化结构体Particle的属性
	p->size = rand() % (int)Base_size + Base_size + 3;
	p->direction = 90;
	p->direction = PI * p->direction / 180.0;//把p.direction转换成具体的度数。
	p->speed = ((double)(rand() % 11)) / 25.0 + 0.25;
	p->color.r = ((double)(rand() % 101)) / 100.0;
	p->color.g = ((double)(rand() % 101)) / 100.0;
	p->color.b = ((double)(rand() % 101)) / 100.0;
	p->Time = 0;
	p->lifeTime = rand() % Base_LifeTime + Base_LifeTime + 600;
	p->cur_X = (double)(rand() % 400) + 50;
	p->cur_Y = 0;
}

void calfirstParticleCurPos(Particle &p) {//计算出当前粒子的位置。
	p.cur_Y += p.speed * sin(p.direction)-0.5*0.0006*time1;
	p.lifeTime--;
	time1++;
	if(p.lifeTime == 0)
	{
		time1 = 0;
	}
}

void calParticleCurPos(Particle &p) {
	p.cur_X += p.speed * cos(p.direction);
	p.cur_Y += p.speed * sin(p.direction)-0.5*0.0065*p.Time;
	p.lifeTime--;
	p.Time++;
	if (p.lifeTime == 0)
		p.Time = 0;
}


//////////////////////////////////////////////////////////////////////////////////////////
// renderScene() - render the scene
//////////////////////////////////////////////////////////////////////////////////////////
void renderScene()
{
	// set a colour
	graphics.setColour(1.0f, 0.5f, 0.1f);

	// set pixel size..
	graphics.setPointSize(10);

	/////////////////////////////////////////////
	// render your particle here..
	/////////////////////////////////////////////
	if (firstfireworkstatus)
	{
		for (auto it = g_particleV.begin(); it != g_particleV.end(); it++) {
			graphics.setColour(it->color.r, it->color.g, it->color.b);
			// set pixel size..
			graphics.setPointSize(it->size);
			graphics.drawPixel(original_X + it->cur_X, original_Y + it->cur_Y);
		}
	}


	if (firstfireworkstatus == false && status) {
		graphics.setColour(p1->color.r, p1->color.g, p1->color.b);
		graphics.setPointSize(p1->size);
		graphics.drawPixel(p1->cur_X, p1->cur_Y);
	}


	// draw to an off screen buffer
	//graphics.drawPixel(250.0f, 250.0f);

	// render the scene
	graphics.render();
}

//////////////////////////////////////////////////////////////////////////////////////////
// update() - update function
//////////////////////////////////////////////////////////////////////////////////////////
void update()
{
	/////////////////////////////////////////////
	// update your particle here..
	/////////////////////////////////////////////
	//bool status = false;//status代表此时爆炸烟花结束，但是已经删除内存的上升烟花还没有动态分配内存。
	if (!firstfireworkstatus && status &&increasingFlag)
	{
		if (p1->lifeTime <= 0 && firstfireworkstatus == false)//上升烟花的寿命结束，第一朵烟花状态还在上升状态时
		{
			firstfireworkstatus = true;//firstfireworkstatus=true表明上升烟花已经结束，fireworkstatus=ture表明爆照烟花已经结束
			original_X = p1->cur_X;
			original_Y = p1->cur_Y;
			delete p1;
			status = false;
			increasingFlag = false;
		}
		else
			calfirstParticleCurPos(*p1);

	}
	if (fireworkstatus && firstfireworkstatus == false && increasingFlag == false)//爆炸烟花结束，上升烟花开始的时候
	{
		p1 = new Particle;
		initfirstParticle(p1);

		status = true;
		increasingFlag = true;
	}

	if (firstfireworkstatus)
	{
		for (auto it = g_particleV.begin(); it != g_particleV.end(); ) {
			if (it->cur_X + original_X > SCREEN_WIDTH || it->cur_Y + original_Y > SCREEN_HEIGHT //当粒子超过边界的时候和粒子的生命周期结束时
				|| it->lifeTime <= 0) {
				if (!g_pause) {//系统没有暂停
							   //initParticle(*it);//初始化粒子
					it = g_particleV.erase(it);
					if (g_particleV.empty())
					{
						fireworkstatus = true;
						firstfireworkstatus = false;
						srand(time(NULL));
						int n = rand() % Base_num + Base_num;
						for (int i = 0; i < n; i++) {
							Particle p;
							initParticle(p);
							g_particleV.push_back(p);
						}
						renderScene();
						break;
					}

				}
				else
					it = g_particleV.erase(it);//系统暂停，将结束的粒子内存逐一释放。
			}
			else {
				calParticleCurPos(*it);//计算粒子当前位置。
				it++;
			}


		}
	}


	// always re-render the scene..
	renderScene();
}


void processSpecialKeys(int key, int x, int y)
{
	switch (key)
	{
	case GLUT_KEY_F1:
		g_pause = true;
		break;
	case GLUT_KEY_F2:
	{
		g_pause = false;
		g_particleV.resize(rand() % Base_num + Base_num);
	}
	break;
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
// _tmain() - program entry point
//////////////////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
	// init glut stuff..
	graphics.create(argc, argv);

	// good place for one-off initialisations and objects creation..
	p1 = new Particle;
	initfirstParticle(p1);

	srand(time(NULL));
	int n = rand() % Base_num + Base_num;
	for (int i = 0; i < n; i++) {
		Particle p;
		initParticle(p);
		g_particleV.push_back(p);
	}



	glutSpecialFunc(processSpecialKeys);

	// enter game loop..
	graphics.loop();

	return 0;
}




