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 }