-
Notifications
You must be signed in to change notification settings - Fork 2
/
ParticleRoutine.cpp
330 lines (295 loc) · 19.4 KB
/
ParticleRoutine.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
//////////////////////////////////////////////////
//类名:CParticleRoutine
//功能:粒子系统可实现仿爆炸、环形波、尾汽等效果
//修改:徐景周(Johnny Xu, xujingzhou2016@gmail.com)
//组织:未来工作室(Future Studio)
//日期:2002.1.1
//////////////////////////////////////////////////
#include "stdafx.h"
#include "ParticleRoutine.h"
#include "math.h" // 加入数学运算头文件
// 环境因素
float particle_wind = 0; // 环境风速
float particle_gravity = 0; // 环境重力
// 粒子状态
const int PARTICLE_STATE_DEAD = 0; // 死亡
const int PARTICLE_STATE_ALIVE = 1; // 存活
// 粒子类型
const int PARTICLE_TYPE_FLICKER = 0; // 闪烁
const int PARTICLE_TYPE_FADE = 1; // 退色
// 粒子基本颜色ID
const int PARTICLE_COLOR_BLUE = 0; // 蓝
const int PARTICLE_COLOR_GREEN = 1; // 绿
const int PARTICLE_COLOR_CYAN = 2; // 青
const int PARTICLE_COLOR_RED = 3; // 红
const int PARTICLE_COLOR_MAGENTA = 4; // 洋红
const int PARTICLE_COLOR_YELLOW = 5; // 黄
const int PARTICLE_COLOR_WHITE = 6; // 白
// 粒子基本颜色范围
const COLORREF COLOR_BLUE_START = RGB(0,0,0); // 从黑到蓝
const COLORREF COLOR_BLUE_END = RGB(0,0,255);
const COLORREF COLOR_GREEN_START = RGB(0,0,255); // 从蓝到绿
const COLORREF COLOR_GREEN_END = RGB(0,255,0);
const COLORREF COLOR_CYAN_START = RGB(0,255,0); // 从绿到青
const COLORREF COLOR_CYAN_END = RGB(0,255,255);
const COLORREF COLOR_RED_START = RGB(0,255,255); // 从青到红
const COLORREF COLOR_RED_END = RGB(255,0,0);
const COLORREF COLOR_MAGENTA_START = RGB(255,0,0); // 从红到洋红
const COLORREF COLOR_MAGENTA_END = RGB(255,0,255);
const COLORREF COLOR_YELLOW_START = RGB(255,0,255); // 从洋红到黄
const COLORREF COLOR_YELLOW_END = RGB(255,255,0);
const COLORREF COLOR_WHITE_START = RGB(255,255,0); // 从黄到白
const COLORREF COLOR_WHITE_END = RGB(255,255,255);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// ---------------------------------------------------------
// 名称: CParticleRoutine
// 功能: 初始化工作
// 参数: 无
// 返回: 无
// 编写: 徐景周(Johnny Xu, xujingzhou2016@gmail.com),2002.4.8
// ---------------------------------------------------------
CParticleRoutine::CParticleRoutine()
{
// 预先计算360度各角度的正弦、余弦值,以避免重复浪费
for(int ang = 0; ang <360; ++ang)
{
float a = static_cast<float>(ang*3.14159/180);
cos_value[ang] = static_cast<float>(cos(a));
sin_value[ang] = static_cast<float>(sin(a));
}
}
// ---------------------------------------------------------
// 名称: ~CParticleRoutine
// 功能: 退出时清除工作
// 参数: 无
// 返回: 无
// 编写: 徐景周(Johnny Xu, xujingzhou2016@gmail.com),2002.4.8
// ---------------------------------------------------------
CParticleRoutine::~CParticleRoutine()
{
}
// ---------------------------------------------------------
// 名称: Reset_Particles
// 功能: 初始化、复位粒子系统
// 参数: nWidth -- 传入位图宽度, nHeight -- 传入位图高度
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Reset_Particles(int nWidth,int nHeight)
{
for(int index=0; index < MAX_PARTICLES; ++index)
{
particles[index].state = PARTICLE_STATE_DEAD;
particles[index].type = PARTICLE_TYPE_FADE;
particles[index].x = 0;
particles[index].y = 0;
particles[index].xv = 0;
particles[index].yv = 0;
particles[index].start_color = RGB(0,0,0);
particles[index].end_color = RGB(0,0,0);
particles[index].current_color = RGB(0,0,0);
particles[index].counter = 0;
particles[index].max_count = 0;
}
m_bmpWidth = nWidth;
m_bmpHeight = nHeight;
}
// ---------------------------------------------------------
// 名称: Start_Particle
// 功能: 处理各粒子数据
// 参数: type -- 粒子类型, color -- 粒子颜色类型,count -- 粒子生命周期
// x,y -- 粒子位置,xv,xy -- 粒子初速度
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Start_Particle(int type,int color,int count,int x,int y,float xv,float yv)
{
int pindex = -1;
// 寻找一个空闲的粒子
for(int index=0; index < MAX_PARTICLES; ++index)
{
if(PARTICLE_STATE_DEAD == particles[index].state)
{
pindex = index;
break;
}
}
if(-1 == pindex)
return;
// 找到后给它设置相关值
particles[pindex].state = PARTICLE_STATE_ALIVE;
particles[pindex].type = type;
particles[pindex].x = x;
particles[pindex].y = y;
particles[pindex].xv = xv;
particles[pindex].yv = yv;
particles[pindex].counter = 0;
particles[pindex].max_count = count;
switch(color)
{
case PARTICLE_COLOR_BLUE: // 蓝
{
particles[pindex].start_color = COLOR_BLUE_START;
particles[pindex].end_color = COLOR_BLUE_END;
break;
}
case PARTICLE_COLOR_GREEN: // 绿
{
particles[pindex].start_color = COLOR_GREEN_START;
particles[pindex].end_color = COLOR_GREEN_END;
break;
}
case PARTICLE_COLOR_CYAN: // 青
{
particles[pindex].start_color = COLOR_CYAN_START;
particles[pindex].end_color = COLOR_CYAN_END;
break;
}
case PARTICLE_COLOR_RED: // 红
{
particles[pindex].start_color = COLOR_RED_START;
particles[pindex].end_color = COLOR_RED_END;
break;
}
case PARTICLE_COLOR_MAGENTA: // 洋红
{
particles[pindex].start_color = COLOR_MAGENTA_START;
particles[pindex].end_color = COLOR_MAGENTA_END;
break;
}
case PARTICLE_COLOR_YELLOW: // 黄
{
particles[pindex].start_color = COLOR_YELLOW_START;
particles[pindex].end_color = COLOR_YELLOW_END;
break;
}
case PARTICLE_COLOR_WHITE: // 白
{
particles[pindex].start_color = COLOR_WHITE_START;
particles[pindex].end_color = COLOR_WHITE_END;
break;
}
}
if(PARTICLE_TYPE_FLICKER == type)
{
particles[pindex].current_color = GetRandom(particles[pindex].start_color, particles[pindex].end_color);
}
else
{
particles[pindex].current_color = particles[pindex].start_color;
}
}
// ---------------------------------------------------------
// 名称: Draw_Particles
// 功能: 将处理后各粒子数据传入位图中
// 参数: pTargetImage -- 传入位图指针
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Draw_Particles(DWORD* pTargetImage)
{
for(int index=0; index < MAX_PARTICLES; ++index)
{
int x = particles[index].x;
int y = particles[index].y;
if(x >= m_bmpWidth || x < 0 || y >= m_bmpHeight || y < 0)
continue;
pTargetImage[y*m_bmpWidth + x] = particles[index].current_color;
}
}
// ---------------------------------------------------------
// 名称: Process_Particles
// 功能: 处理运动中各粒子后,调用Draw_Particles()
// 参数: pTargetImage -- 传入位图指针
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Process_Particles(DWORD* pTargetImage)
{
for(int index=0; index < MAX_PARTICLES; ++index)
{
if(PARTICLE_STATE_ALIVE == particles[index].state)
{
particles[index].x += static_cast<int>(particles[index].xv);
particles[index].y += static_cast<int>(particles[index].yv);
particles[index].xv += particle_wind;
particles[index].yv += particle_gravity;
if(PARTICLE_TYPE_FLICKER == particles[index].type) // 粒子在激活闪烁
{
particles[index].current_color = GetRandom(particles[index].start_color, particles[index].end_color);
// 更新计数器,看是否超过生命周期
if(++particles[index].counter >= particles[index].max_count)
particles[index].state = PARTICLE_STATE_DEAD;
}
else // 粒子未激活
{
if(++particles[index].counter >= particles[index].max_count)
{
particles[index].counter = 0;
// 更新颜色值
if(++particles[index].current_color > particles[index].end_color)
particles[index].state = PARTICLE_STATE_DEAD;
}
}
if(particles[index].x > m_bmpWidth || particles[index].x < 0 || particles[index].y > m_bmpHeight || particles[index].y < 0)
particles[index].state = PARTICLE_STATE_DEAD;
// 绘制粒子
Draw_Particles(pTargetImage);
}
}
}
// ---------------------------------------------------------
// 名称: Set_Particle_Explosion
// 功能: 爆炸效果处理
// 参数: type -- 粒子类型, color -- 粒子颜色类型,count -- 粒子生命周期
// x,y -- 粒子位置,xv,xy -- 粒子初速度
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Set_Particle_Explosion(int type, int color, int count, int x, int y, int xv, int yv)
{
int nNum = MAX_PARTICLES;
while(--nNum >= 0)
{
int ang = rand()%360;
float vel = static_cast<float>(2 + rand()%4);
Start_Particle(type,color,count,x+GetRandom(-4,4),y+GetRandom(-4,4),xv+cos_value[ang]*vel,yv+sin_value[ang]*vel);
}
}
// ---------------------------------------------------------
// 名称: Set_Particle_Ring
// 功能: 环形波效果处理
// 参数: type -- 粒子类型, color -- 粒子颜色类型,count -- 粒子生命周期
// x,y -- 粒子位置,xv,xy -- 粒子初速度
// 返回: 无
// 编写: 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Set_Particle_Ring(int type, int color, int count, int x, int y, int xv, int yv)
{
float vel = static_cast<float>(2 + rand()%4);
int nNum = MAX_PARTICLES;
while(--nNum >= 0)
{
int ang = rand()%360;
Start_Particle(type,color,count,x,y,xv+cos_value[ang]*vel,yv+sin_value[ang]*vel);
}
}
// ---------------------------------------------------------
// 名称: Set_Particle_Gas
// 功能: 尾汽效果处理
// 参数: type -- 粒子类型, color -- 粒子颜色类型,emit_x -- 发射时X坐标
// emit_y -- 发射时Y坐标,emit_xv,emit_xy -- 发射时初速度
// 返回: 无
// 编写 徐景周,2002.4.8
// ---------------------------------------------------------
void CParticleRoutine::Set_Particle_Gas(int type, int color, int emit_x, int emit_y, int emit_xv, int emit_yv)
{
int nNum = MAX_PARTICLES;
while(--nNum >= 0)
{
if(1 == (rand()%10))
Start_Particle(type,color,GetRandom(30,60),emit_x+GetRandom(4,-4),emit_y+GetRandom(4,-4),static_cast<float>(emit_xv+GetRandom(2,-2)),static_cast<float>(emit_yv+GetRandom(2,-2)));
}
}