1 /* 2 ** Haaf's Game Engine 1.8 3 ** Copyright (C) 2003-2007, Relish Games 4 ** hge.relishgames.com 5 ** 6 ** hge_tut04 - Using render targets 7 */ 8 9 10 // 复制"particles.png","menu.wav","font1.fnt","font1.png"以及"trail.psi" 11 12 13 #include <hge.h> 14 #include <hgesprite.h> 15 #include <hgefont.h> 16 #include <hgeparticle.h> 17 #pragma comment(lib,"hge.lib") 18 #pragma comment(lib,"hgehelp.lib") 19 20 HGE *hge=0; 21 22 23 hgeSprite* spr; 24 hgeSprite* spt; 25 hgeSprite* tar; 26 hgeFont* fnt; 27 hgeParticleSystem* par; 28 29 HTEXTURE tex; 30 HEFFECT snd; 31 32 // HGE渲染目标句柄 33 HTARGET target; 34 35 float x=100.0f, y=100.0f; 36 float dx=0.0f, dy=0.0f; 37 38 const float speed=90; 39 const float friction=0.98f; 40 41 void boom() { 42 int pan=int((x-256)/2.56f); 43 float pitch=(dx*dx+dy*dy)*0.0005f+0.2f; 44 hge->Effect_PlayEx(snd,100,pan,pitch); 45 } 46 47 // 这个函数会在 渲染目标 丢失和重建的时候被HGE调用 48 // 由于渲染目标可能丢失(重建之后target的纹理和之前的纹理就不一样了), 49 // 因此在重建的需要重新设置tar引用的target纹理 50 // 后面会解释为什么要这么做. 51 bool GfxRestoreFunc() 52 { 53 if(tar && target) tar->SetTexture(hge->Target_GetTexture(target)); 54 return false; 55 } 56 57 58 bool FrameFunc() 59 { 60 float dt=hge->Timer_GetDelta(); 61 62 // 检测按键 63 if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true; 64 if (hge->Input_GetKeyState(HGEK_LEFT)) dx-=speed*dt; 65 if (hge->Input_GetKeyState(HGEK_RIGHT)) dx+=speed*dt; 66 if (hge->Input_GetKeyState(HGEK_UP)) dy-=speed*dt; 67 if (hge->Input_GetKeyState(HGEK_DOWN)) dy+=speed*dt; 68 69 // 运动计算和碰撞判断 70 dx*=friction; dy*=friction; x+=dx; y+=dy; 71 if(x>496) {x=496-(x-496);dx=-dx;boom();} 72 if(x<16) {x=16+16-x;dx=-dx;boom();} 73 if(y>496) {y=496-(y-496);dy=-dy;boom();} 74 if(y<16) {y=16+16-y;dy=-dy;boom();} 75 76 // 更新粒子系统 77 par->info.nEmission=(int)(dx*dx+dy*dy); 78 par->MoveTo(x,y); 79 par->Update(dt); 80 81 return false; 82 } 83 84 85 bool RenderFunc() 86 { 87 int i; 88 89 // 绘制到 渲染目标 上 90 // 实际上是将各种图像先绘制到target的纹理中去 91 hge->Gfx_BeginScene(target); 92 hge->Gfx_Clear(0); 93 par->Render(); 94 spr->Render(x, y); 95 hge->Gfx_EndScene(); 96 97 // 现在把东西都绘制到屏幕上 98 hge->Gfx_BeginScene(); 99 hge->Gfx_Clear(0); 100 // 注意,由于tar的纹理引用自target的纹理,因此这里绘制tar就是在 101 // 屏幕上显示前面绘制到target中的东西. 102 // 这样做与双缓冲的原理类似,可以避免绘制过程中的闪烁. 103 // 所以在target丢失重建之后,需要重新设置纹理的引用 104 // 这个时候可能想知道为什么不直接用target来绘制到屏幕, 105 // 查阅hge头文件得知HTARGET实际上是DWORD类型(unsigned long), 106 // 没有任何可用的Render函数,也就无法用HTARGET直接方便的绘制了. 107 for(i=0;i<6;i++) 108 { 109 // 设置颜色的透明度 110 tar->SetColor(0xFFFFFF | (((5-i)*40+55)<<24)); 111 // RenderEx(左上角x,左上角y,旋转角度,水平缩放=1.0f,竖直缩放=0.0f), 112 // 当竖直缩放为0的时候(下面的调用不传参就表示使用默认值0.0f), 113 // HGE就使用水平缩放的值来表示竖直缩放的值,也就是说,竖直缩放的值也是1.0f-i*0.1f 114 tar->RenderEx(i*100.0f, i*50.0f, i*M_PI/8, 1.0f-i*0.1f); 115 } 116 fnt->printf(5, 5, HGETEXT_LEFT, "dt:%.3f\nFPS:%d (constant)", hge->Timer_GetDelta(), hge->Timer_GetFPS()); 117 hge->Gfx_EndScene(); 118 119 return false; 120 } 121 122 123 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) 124 { 125 hge = hgeCreate(HGE_VERSION); 126 127 hge->System_SetState(HGE_LOGFILE, "hge_tut04.log"); 128 hge->System_SetState(HGE_FRAMEFUNC, FrameFunc); 129 hge->System_SetState(HGE_RENDERFUNC, RenderFunc); 130 hge->System_SetState(HGE_GFXRESTOREFUNC, GfxRestoreFunc); 131 hge->System_SetState(HGE_TITLE, "HGE Tutorial 04 - Using render targets"); 132 hge->System_SetState(HGE_FPS, 100); 133 hge->System_SetState(HGE_WINDOWED, true); 134 hge->System_SetState(HGE_SCREENWIDTH, 800); 135 hge->System_SetState(HGE_SCREENHEIGHT, 600); 136 hge->System_SetState(HGE_SCREENBPP, 32); 137 138 tar=0; 139 target=0; 140 141 if(hge->System_Initiate()) { 142 snd=hge->Effect_Load("menu.wav"); 143 tex=hge->Texture_Load("particles.png"); 144 if(!snd || !tex) 145 { 146 MessageBox(NULL, "Can't load one of the following files:\nMENU.WAV, PARTICLES.PNG, FONT1.FNT, FONT1.PNG, TRAIL.PSI", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL); 147 hge->System_Shutdown(); 148 hge->Release(); 149 return 0; 150 } 151 152 spr=new hgeSprite(tex, 96, 64, 32, 32); 153 spr->SetColor(0xFFFFA000); 154 spr->SetHotSpot(16,16); 155 156 fnt=new hgeFont("font1.fnt"); 157 158 spt=new hgeSprite(tex, 32, 32, 32, 32); 159 spt->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_NOZWRITE); 160 spt->SetHotSpot(16,16); 161 par=new hgeParticleSystem("trail.psi",spt); 162 par->Fire(); 163 164 // 创建一个渲染目标和一个精灵(用于绘制渲染目标的纹理,上面的代码中有说明) 165 target=hge->Target_Create(512,512,false); 166 tar=new hgeSprite(hge->Target_GetTexture(target),0,0,512,512); 167 tar->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_NOZWRITE); 168 169 hge->System_Start(); 170 171 delete par; 172 delete fnt; 173 delete spt; 174 delete spr; 175 delete tar; 176 hge->Target_Free(target); 177 hge->Texture_Free(tex); 178 hge->Effect_Free(snd); 179 } 180 181 hge->System_Shutdown(); 182 hge->Release(); 183 return 0; 184 }