1 /*
2 ** Haaf's Game Engine 1.8
3 ** Copyright (C) 2003-2007, Relish Games
4 ** hge.relishgames.com
5 **
6 ** hge_tut08 - The Big Calm
7 */
8
9
10 // 复制"font2.fnt","font2.png","objects.png"
11
12
13 // 本教程模拟了太阳和月亮的运转,以及天空和海面的情况
14
15
16 #include <math.h>
17
18 #include <hge.h>
19 #include <hgecolor.h>
20 #include <hgesprite.h>
21 #include <hgedistort.h>
22 #include <hgefont.h>
23 #pragma comment(lib,"hge.lib")
24 #pragma comment(lib,"hgehelp.lib")
25
26
27 HGE *hge=0;
28 hgeFont *fnt=0;
29
30 // 一些常量和变量
31
32 #define SCREEN_WIDTH 800
33 #define SCREEN_HEIGHT 600
34 #define NUM_STARS 100
35 #define SEA_SUBDIVISION 16
36
37 #define SKY_HEIGHT (SCREEN_HEIGHT*0.6f)
38 #define STARS_HEIGHT (SKY_HEIGHT*0.9f)
39 #define ORBITS_RADIUS (SCREEN_WIDTH*0.43f)
40
41 DWORD skyTopColors[] = {0xFF15092A, 0xFF6C6480, 0xFF89B9D0};
42 DWORD skyBtmColors[] = {0xFF303E57, 0xFFAC7963, 0xFFCAD7DB};
43 DWORD seaTopColors[] = {0xFF3D546B, 0xFF927E76, 0xFF86A2AD};
44 DWORD seaBtmColors[] = {0xFF1E394C, 0xFF2F4E64, 0xFF2F4E64};
45
46 int seq[]={0, 0, 1, 2, 2, 2, 1, 0, 0};
47
48 // 资源句柄
49 HTEXTURE texObjects;
50
51 hgeSprite *sky;
52 hgeSprite *sun;
53 hgeSprite *moon;
54 hgeSprite *glow;
55 hgeSprite *seaglow;
56 hgeSprite *star;
57
58 hgeDistortionMesh *sea;
59
60 hgeColor colWhite;
61
62 // 保存状态的变量
63 float time; // 0-24 小时
64 float speed; // 指定一小时有多少秒
65
66 int seq_id;
67 float seq_residue;
68
69 //天上星星的的信息
70 float starX[NUM_STARS]; // x
71 float starY[NUM_STARS]; // y
72 float starS[NUM_STARS]; // 缩放
73 float starA[NUM_STARS]; // 透明度
74
75 float seaP[SEA_SUBDIVISION]; // 相移数组
76
77 hgeColor colSkyTop;
78 hgeColor colSkyBtm;
79 hgeColor colSeaTop;
80 hgeColor colSeaBtm;
81
82 hgeColor colSun;
83 hgeColor colSunGlow;
84 hgeColor colMoon;
85 hgeColor colMoonGlow;
86 hgeColor colSeaGlow;
87
88 float sunX, sunY, sunS, sunGlowS;
89 float moonX, moonY, moonS, moonGlowS;
90 float seaGlowX, seaGlowSX, seaGlowSY;
91
92 // 函数声明
93 bool InitSimulation();// 初始化数据
94 void DoneSimulation();// 删除数据
95 void UpdateSimulation();// 更新数据
96 void RenderSimulation();// 绘制数据
97
98
99 ///////////////////////// 函数实现 ///////////////////////////
100
101
102 bool FrameFunc()
103 {
104 // 检查按键
105 switch(hge->Input_GetKey())
106 {
107 case HGEK_0: speed=0.0f; break;
108 case HGEK_1: speed=0.1f; break;
109 case HGEK_2: speed=0.2f; break;
110 case HGEK_3: speed=0.4f; break;
111 case HGEK_4: speed=0.8f; break;
112 case HGEK_5: speed=1.6f; break;
113 case HGEK_6: speed=3.2f; break;
114 case HGEK_7: speed=6.4f; break;
115 case HGEK_8: speed=12.8f; break;
116 case HGEK_9: speed=25.6f; break;
117 case HGEK_ESCAPE: return true;
118 }
119
120 // 更新场景
121 UpdateSimulation();
122 return false;
123 }
124
125
126 bool RenderFunc()
127 {
128 int hrs, mins, secs;
129 float tmp;
130
131 // 计算用于显示的时间
132 hrs=(int)floorf(time);
133 tmp=(time-hrs)*60.0f;
134 mins=(int)floorf(tmp);
135 secs=(int)floorf((tmp-mins)*60.0f);
136
137 // 绘制场景
138 hge->Gfx_BeginScene();
139 RenderSimulation();
140 fnt->printf(7, 7, HGETEXT_LEFT, "Keys 1-9 to adjust simulation speed, 0 - real time\nFPS: %d", hge->Timer_GetFPS());
141 fnt->printf(SCREEN_WIDTH-50, 7, HGETEXT_LEFT, "%02d:%02d:%02d", hrs, mins, secs);
142 hge->Gfx_EndScene();
143
144 return false;
145 }
146
147
148 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
149 {
150 hge = hgeCreate(HGE_VERSION);
151
152 hge->System_SetState(HGE_LOGFILE, "hge_tut08.log");
153 hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
154 hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
155 hge->System_SetState(HGE_TITLE, "HGE Tutorial 08 - The Big Calm");
156 hge->System_SetState(HGE_USESOUND, false);
157 hge->System_SetState(HGE_WINDOWED, true);
158 hge->System_SetState(HGE_SCREENWIDTH, SCREEN_WIDTH);
159 hge->System_SetState(HGE_SCREENHEIGHT, SCREEN_HEIGHT);
160 hge->System_SetState(HGE_SCREENBPP, 32);
161
162 if(hge->System_Initiate())
163 {
164 fnt=new hgeFont("font2.fnt");
165
166 if(!InitSimulation())
167 {
168 MessageBox(NULL, "Can't load resources. See log for details.", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
169 hge->System_Shutdown();
170 hge->Release();
171 return 0;
172 }
173
174 hge->System_Start();
175
176 DoneSimulation();
177 delete fnt;
178 }
179
180 hge->System_Shutdown();
181 hge->Release();
182 return 0;
183 }
184
185
186 float GetTime()
187 {
188 SYSTEMTIME SysTime;
189 float tmp;
190
191 GetLocalTime(&SysTime);
192 tmp=SysTime.wSecond;
193 tmp=SysTime.wMinute+tmp/60.0f;
194 tmp=SysTime.wHour+tmp/60.0f;
195
196 return tmp;
197 }
198
199
200 bool InitSimulation()
201 {
202 // 加载纹理
203 texObjects=hge->Texture_Load("objects.png");
204 if(!texObjects) return false;
205
206 // 创建精灵
207 sky=new hgeSprite(0, 0, 0, SCREEN_WIDTH, SKY_HEIGHT);
208 sea=new hgeDistortionMesh(SEA_SUBDIVISION, SEA_SUBDIVISION);
209 sea->SetTextureRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-SKY_HEIGHT);
210
211 sun=new hgeSprite(texObjects,81,0,114,114);
212 sun->SetHotSpot(57,57);
213 moon=new hgeSprite(texObjects,0,0,81,81);
214 moon->SetHotSpot(40,40);
215 star=new hgeSprite(texObjects,72,81,9,9);
216 star->SetHotSpot(5,5);
217
218 glow=new hgeSprite(texObjects,128,128,128,128);
219 glow->SetHotSpot(64,64);
220 glow->SetBlendMode(BLEND_COLORADD | BLEND_ALPHABLEND | BLEND_NOZWRITE);
221 seaglow=new hgeSprite(texObjects,128,224,128,32);
222 seaglow->SetHotSpot(64,0);
223 seaglow->SetBlendMode(BLEND_COLORADD | BLEND_ALPHAADD | BLEND_NOZWRITE);
224
225 // 初始化状态量
226 colWhite.SetHWColor(0xFFFFFFFF);
227 time=GetTime();
228 speed=0.0f;
229
230 for(int i=0;i<NUM_STARS;i++) // 初始化星星的位置
231 {
232 starX[i]=hge->Random_Float(0, SCREEN_WIDTH);
233 starY[i]=hge->Random_Float(0, STARS_HEIGHT);
234 starS[i]=hge->Random_Float(0.1f, 0.7f);
235 }
236
237 for(i=0;i<SEA_SUBDIVISION;i++) // 设置海洋波浪的相位转换
238 {
239 seaP[i]=i+hge->Random_Float(-15.0f, 15.0f);
240 }
241
242 // 初始化完毕
243 return true;
244 }
245
246
247 void DoneSimulation()
248 {
249 // 删除精灵
250
251 delete seaglow;
252 delete glow;
253 delete star;
254 delete moon;
255 delete sun;
256
257 delete sky;
258 delete sea;
259
260 // 释放纹理
261 hge->Texture_Free(texObjects);
262 }
263
264
265 void UpdateSimulation()
266 {
267 int i, j, k;
268 float zenith, a, dy, fTime;
269 float posX, s1, s2;
270 const float cellw=SCREEN_WIDTH/(SEA_SUBDIVISION-1);
271 hgeColor col1, col2;
272 DWORD dwCol1, dwCol2;
273
274 // 更新时间
275 if(speed==0.0f) time=GetTime();
276 else
277 {
278 time+=hge->Timer_GetDelta()*speed;
279 if(time>=24.0f) time-=24.0f;
280 }
281
282 seq_id=(int)(time/3);
283 seq_residue=time/3-seq_id;
284 zenith=-(time/12.0f*M_PI-M_PI_2);
285
286 // 通过 插值计算 得到海洋和天空的颜色
287
288 col1.SetHWColor(skyTopColors[seq[seq_id]]);
289 col2.SetHWColor(skyTopColors[seq[seq_id+1]]);
290 colSkyTop=col2*seq_residue + col1*(1.0f-seq_residue);
291
292 col1.SetHWColor(skyBtmColors[seq[seq_id]]);
293 col2.SetHWColor(skyBtmColors[seq[seq_id+1]]);
294 colSkyBtm=col2*seq_residue + col1*(1.0f-seq_residue);
295
296 col1.SetHWColor(seaTopColors[seq[seq_id]]);
297 col2.SetHWColor(seaTopColors[seq[seq_id+1]]);
298 colSeaTop=col2*seq_residue + col1*(1.0f-seq_residue);
299
300 col1.SetHWColor(seaBtmColors[seq[seq_id]]);
301 col2.SetHWColor(seaBtmColors[seq[seq_id+1]]);
302 colSeaBtm=col2*seq_residue + col1*(1.0f-seq_residue);
303
304 // 更新星星的信息
305 if(seq_id>=6 || seq_id<2)
306 for(int i=0; i<NUM_STARS; i++)
307 {
308 a=1.0f-starY[i]/STARS_HEIGHT;
309 a*=hge->Random_Float(0.6f, 1.0f);
310 if(seq_id>=6) a*=sinf((time-18.0f)/6.0f*M_PI_2);
311 else a*=sinf((1.0f-time/6.0f)*M_PI_2);
312 starA[i]=a;
313 }
314
315 // 计算太阳的位置,缩放,颜色
316 if(seq_id==2) a=sinf(seq_residue*M_PI_2);
317 else if(seq_id==5) a=cosf(seq_residue*M_PI_2);
318 else if(seq_id>2 && seq_id<5) a=1.0f;
319 else a=0.0f;
320
321 colSun.SetHWColor(0xFFEAE1BE);
322 colSun=colSun*(1-a)+colWhite*a;
323
324 a=(cosf(time/6.0f*M_PI)+1.0f)/2.0f;
325 if(seq_id>=2 && seq_id<=6)
326 {
327 colSunGlow=colWhite*a;
328 colSunGlow.a=1.0f;
329 }
330 else colSunGlow.SetHWColor(0xFF000000);
331
332 sunX=SCREEN_WIDTH*0.5f+cosf(zenith)*ORBITS_RADIUS;
333 sunY=SKY_HEIGHT*1.2f+sinf(zenith)*ORBITS_RADIUS;
334 sunS=1.0f-0.3f*sinf((time-6.0f)/12.0f*M_PI);
335 sunGlowS=3.0f*(1.0f-a)+3.0f;
336
337 // 计算月亮的位置,缩放,颜色
338
339 if(seq_id>=6) a=sinf((time-18.0f)/6.0f*M_PI_2);
340 else a=sinf((1.0f-time/6.0f)*M_PI_2);
341 colMoon.SetHWColor(0x20FFFFFF);
342 colMoon=colMoon*(1-a)+colWhite*a;
343
344 colMoonGlow=colWhite;
345 colMoonGlow.a=0.5f*a;
346
347 moonX=SCREEN_WIDTH*0.5f+cosf(zenith-M_PI)*ORBITS_RADIUS;
348 moonY=SKY_HEIGHT*1.2f+sinf(zenith-M_PI)*ORBITS_RADIUS;
349 moonS=1.0f-0.3f*sinf((time+6.0f)/12.0f*M_PI);
350 moonGlowS=a*0.4f+0.5f;
351
352 // 计算海洋的光效
353
354 if(time>19.0f || time<4.5f) // 月亮下的情况
355 {
356 a=0.2f; // 强度
357 if(time>19.0f && time<20.0f) a*=(time-19.0f);
358 else if(time>3.5f && time<4.5f) a*=1.0f-(time-3.5f);
359
360 colSeaGlow=colMoonGlow;
361 colSeaGlow.a=a;
362 seaGlowX=moonX;
363 seaGlowSX=moonGlowS*3.0f;
364 seaGlowSY=moonGlowS*2.0f;
365 }
366 else if(time>6.5f && time<19.0f) // 太阳下的情况
367 {
368 a=0.3f; // 强度
369 if(time<7.5f) a*=(time-6.5f);
370 else if(time>18.0f) a*=1.0f-(time-18.0f);
371
372 colSeaGlow=colSunGlow;
373 colSeaGlow.a=a;
374 seaGlowX=sunX;
375 seaGlowSX=sunGlowS;
376 seaGlowSY=sunGlowS*0.6f;
377 }
378 else colSeaGlow.a=0.0f;
379
380 // 产生海浪并且更新海洋的颜色
381
382 for(i=1; i<SEA_SUBDIVISION-1; i++)
383 {
384 a=float(i)/(SEA_SUBDIVISION-1);
385 col1=colSeaTop*(1-a)+colSeaBtm*a;
386 dwCol1=col1.GetHWColor();
387 fTime=2.0f*hge->Timer_GetTime();
388 a*=20;
389
390 for(j=0; j<SEA_SUBDIVISION; j++)
391 {
392 sea->SetColor(j, i, dwCol1);
393
394 dy=a*sinf(seaP[i]+(float(j)/(SEA_SUBDIVISION-1)-0.5f)*M_PI*16.0f-fTime);
395 sea->SetDisplacement(j, i, 0.0f, dy, HGEDISP_NODE);
396 }
397 }
398
399 dwCol1=colSeaTop.GetHWColor();
400 dwCol2=colSeaBtm.GetHWColor();
401
402 for(j=0; j<SEA_SUBDIVISION; j++)
403 {
404 sea->SetColor(j, 0, dwCol1);
405 sea->SetColor(j, SEA_SUBDIVISION-1, dwCol2);
406 }
407
408 // 计算光线路径
409
410 if(time>19.0f || time<5.0f) // 月亮下的情况
411 {
412 a=0.12f; // 强度
413 if(time>19.0f && time<20.0f) a*=(time-19.0f);
414 else if(time>4.0f && time<5.0f) a*=1.0f-(time-4.0f);
415 posX=moonX;
416 }
417 else if(time>7.0f && time<17.0f) // 太阳下的情况
418 {
419 a=0.14f; // 强度
420 if(time<8.0f) a*=(time-7.0f);
421 else if(time>16.0f) a*=1.0f-(time-16.0f);
422 posX=sunX;
423 }
424 else a=0.0f;
425
426 if(a!=0.0f)
427 {
428 k=(int)floorf(posX/cellw);
429 s1=(1.0f-(posX-k*cellw)/cellw);
430 s2=(1.0f-((k+1)*cellw-posX)/cellw);
431
432 if(s1>0.7f) s1=0.7f;
433 if(s2>0.7f) s2=0.7f;
434
435 s1*=a;
436 s2*=a;
437
438 for(i=0; i<SEA_SUBDIVISION; i+=2)
439 {
440 a=sinf(float(i)/(SEA_SUBDIVISION-1)*M_PI_2);
441
442 col1.SetHWColor(sea->GetColor(k,i));
443 col1+=colSun*s1*(1-a);
444 col1.Clamp();
445 sea->SetColor(k, i, col1.GetHWColor());
446
447 col1.SetHWColor(sea->GetColor(k+1,i));
448 col1+=colSun*s2*(1-a);
449 col1.Clamp();
450 sea->SetColor(k+1, i, col1.GetHWColor());
451 }
452 }
453 }
454
455
456 void RenderSimulation()
457 {
458 // 绘制天空
459 sky->SetColor(colSkyTop.GetHWColor(), 0);
460 sky->SetColor(colSkyTop.GetHWColor(), 1);
461 sky->SetColor(colSkyBtm.GetHWColor(), 2);
462 sky->SetColor(colSkyBtm.GetHWColor(), 3);
463 sky->Render(0, 0);
464
465 // 绘制星星
466 if(seq_id>=6 || seq_id<2)
467 for(int i=0; i<NUM_STARS; i++)
468 {
469 star->SetColor((DWORD(starA[i]*255.0f)<<24) | 0xFFFFFF);
470 star->RenderEx(starX[i], starY[i], 0.0f, starS[i]);
471 }
472
473 // 绘制太阳
474 glow->SetColor(colSunGlow.GetHWColor());
475 glow->RenderEx(sunX, sunY, 0.0f, sunGlowS);
476 sun->SetColor(colSun.GetHWColor());
477 sun->RenderEx(sunX, sunY, 0.0f, sunS);
478
479 // 绘制月亮
480 glow->SetColor(colMoonGlow.GetHWColor());
481 glow->RenderEx(moonX, moonY, 0.0f, moonGlowS);
482 moon->SetColor(colMoon.GetHWColor());
483 moon->RenderEx(moonX, moonY, 0.0f, moonS);
484
485 // 绘制海洋
486 // 绘制月亮和太阳的时候不需要对时间进行判定
487 // 原因是当在海平线以下的时候,进行海洋的绘制会覆盖掉太阳或者月亮
488 sea->Render(0, SKY_HEIGHT);
489 seaglow->SetColor(colSeaGlow.GetHWColor());
490 seaglow->RenderEx(seaGlowX, SKY_HEIGHT, 0.0f, seaGlowSX, seaGlowSY);
491
492 // 总体上的绘制顺序就是后者会覆盖前者(当然,如果后者设置了一些融合属性,可能就不会完全的覆盖了,
493 // 但是本例中则是完全覆盖)
494 }