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 }