Visual C++游戏开发笔记之十一 基础动画显示四 排序贴图.docx
- 文档编号:8861780
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:15
- 大小:263.60KB
Visual C++游戏开发笔记之十一 基础动画显示四 排序贴图.docx
《Visual C++游戏开发笔记之十一 基础动画显示四 排序贴图.docx》由会员分享,可在线阅读,更多相关《Visual C++游戏开发笔记之十一 基础动画显示四 排序贴图.docx(15页珍藏版)》请在冰豆网上搜索。
VisualC++游戏开发笔记之十一基础动画显示四排序贴图
【VisualC++】游戏开发笔记之十一基础动画显示(四)排序贴图
本系列文章由zhmxy555编写,转载请注明出处。
作者:
毛星云 邮箱:
happylifemxy@ 欢迎邮件交流编程心得
“排序贴图”是源自于物体远近呈现的一种贴图概念。
回忆我们之前笔记的贴图思想,先进行距离比较远的物体的贴图操作,然后再进行近距离物体的贴图操作,一旦定出贴图的顺序之后就无法再改变了。
然而这样的作法在画面上物体会彼此遮掩的情况下就会不适用。
也许会出现后面的物体反而遮住了前面的物体的这种不协调的画面。
为了避免这种因为贴图顺序而固定而产生的错误画面,必须在每一次窗口重新显示时动态地重新决定画面上每一个物体的贴图顺序。
那么,如何动态决定贴图顺序呢?
我们可以采用排序的方式。
为了演示排序如何运用在贴图中,我们举一个例子。
假设现在有10只要进行贴图的小牛图案,先把它存在一个数组之中,从2D平面的远近角度来看,Y轴坐标比较小的是比较远的物体。
如果我们以小牛的Y轴坐标(要排序的值被我们称作键值)来对小牛数组由小到大进行排序,最后会使得Y轴坐标小的小牛排在数组的前面,而进行画面贴图时则由数组由小到大一个个进行处理,这样便可实现“远的物体先贴图“的目的了。
这里我们使用气泡排序(Bubble Sort)作为我们的排序法,因为此方法有程序代码简单,排序效率中等,属于稳定(stable)排序法的特点。
这里的稳定排序法的特性,会使得Y轴坐标相同的物体,不必再去考虑它X坐标上的排序。
下面我们贴出以C/C++写出的气泡排序法的代码,对”pop[]“数组的各数据成员的Y值为键值来排序,输出的参数为”n“表示要排序的数组大小:
[cpp] viewplaincopyprint?
1.void BubSort(int n)
2.{
3. int i,j;
4. bool f;
5. pop tmp;
6.
7. for(i=0;i 8. { 9. f = false; 10. for(j=0;j 11. { 12. if(pop[j+1].y < pop[j].y) 13. { //进行数组元素的交换 14. tmp = pop[j+1]; 15. pop[j+1] = pop[j]; 16. pop[j] = tmp; 17. f = true; 18. } 19. } 20. if(! f) //无交换操作则结束循环 21. break; 22. } 23.} 各种排序法为C/C++中比较核心的知识点,还不太熟悉的朋友,可以参看各种C++,数据结构的教程进行深入学习。 在这里我就不多做介绍了。 接下来,我们来利用一个范例来演示气泡排序法在画面上贴图的运用,让动画能呈现出接近真实的远近层次效果。 这个范例比较有趣,会产生多只恐龙随机跑动,每次进行画面贴图前先完成排序操作,并对恐龙跑动进行贴图坐标的修正,呈现出比较顺畅真实的动画来。 废话这里就不多说了,直接上已经详细注释的代码(这回的代码量就有些大了,不过我专门注释得更详细了些,其实它比之前的代码还更好懂): [cpp] viewplaincopyprint? 1.#include "stdafx.h" 2.#include 3. 4.//定义一个结构体 5.struct dragon //定义dragon结构,代表画面上的恐龙,其结构成员x和y为贴图坐标,dir为目前恐龙的移动方向 6.{ 7. int x,y; 8. int dir; 9.}; 10. 11.//定义常数 12.const int draNum = 12; //定义常数draNum,代表程序在画面上要出现的恐龙数目,在此设定为12个 13.//全局变量定义 14.HINSTANCE hInst; 15.HBITMAP draPic[4],bg; //draPic[4]储存恐龙上下左右移动的连续图案,bg为存储背景图 16.HDC hdc,mdc,bufdc; 17.HWND hWnd; 18.DWORD tPre,tNow; 19.int picNum; 20.dragon dra[draNum]; //按照draNum的值建立数组dra[],产生画面上出现的恐龙。 21. 22. 23.//全局函数声明 24.ATOM MyRegisterClass(HINSTANCE hInstance); 25.BOOL InitInstance(HINSTANCE, int); 26.LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 27.void MyPaint(HDC hdc); 28. 29.//****WinMain函数,程序入口点函数************************************** 30.int APIENTRY WinMain(HINSTANCE hInstance, 31. HINSTANCE hPrevInstance, 32. LPSTR lpCmdLine, 33. int nCmdShow) 34.{ 35. MSG msg; 36. 37. MyRegisterClass(hInstance); 38. 39. //初始化 40. if (! InitInstance (hInstance, nCmdShow)) 41. { 42. return FALSE; 43. } 44. GetMessage(&msg,NULL,NULL,NULL);//初始化msg 45. //消息循环 46. while( msg.message! =WM_QUIT ) 47. { 48. if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) ) 49. { 50. TranslateMessage( &msg ); 51. DispatchMessage( &msg ); 52. } 53. else 54. { 55. tNow = GetTickCount(); 56. if(tNow-tPre >= 100) 57. MyPaint(hdc); 58. } 59. } 60. 61. return msg.wParam; 62.} 63. 64.//****设计一个窗口类,类似填空题,使用窗口结构体************************* 65.ATOM MyRegisterClass(HINSTANCE hInstance) 66.{ 67. WNDCLASSEX wcex; 68. 69. wcex.cbSize = sizeof(WNDCLASSEX); 70. wcex.style = CS_HREDRAW | CS_VREDRAW; 71. wcex.lpfnWndProc = (WNDPROC)WndProc; 72. wcex.cbClsExtra = 0; 73. wcex.cbWndExtra = 0; 74. wcex.hInstance = hInstance; 75. wcex.hIcon = NULL; 76. wcex.hCursor = NULL; 77. wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 78. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 79. wcex.lpszMenuName = NULL; 80. wcex.lpszClassName = "canvas"; 81. wcex.hIconSm = NULL; 82. 83. return RegisterClassEx(&wcex); 84.} 85. 86.//****初始化函数************************************* 87.// 加载位图并设定各初始值 88.BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 89.{ 90. HBITMAP bmp; 91. hInst = hInstance; 92. int i; 93. 94. hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW, 95. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 96. 97. if (! hWnd) 98. { 99. return FALSE; 100. } 101. 102. MoveWindow(hWnd,10,10,640,480,true); 103. ShowWindow(hWnd, nCmdShow); 104. UpdateWindow(hWnd); 105. 106. hdc = GetDC(hWnd); 107. mdc = CreateCompatibleDC(hdc); 108. bufdc = CreateCompatibleDC(hdc); 109. 110. bmp = CreateCompatibleBitmap(hdc,640,480); //建立一个空位图并放入mdc中 111. SelectObject(mdc,bmp); 112. 113. 114. //加载各张恐龙跑动图及背景图,这里以0,1,2,3来代表恐龙的上,下,左,右移动 115. draPic[0] = (HBITMAP)LoadImage(NULL,"dra0.bmp",IMAGE_BITMAP,528,188,LR_LOADFROMFILE); 116. draPic[1] = (HBITMAP)LoadImage(NULL,"dra1.bmp",IMAGE_BITMAP,544,164,LR_LOADFROMFILE); 117. draPic[2] = (HBITMAP)LoadImage(NULL,"dra2.bmp",IMAGE_BITMAP,760,198,LR_LOADFROMFILE); 118. draPic[3] = (HBITMAP)LoadImage(NULL,"dra3.bmp",IMAGE_BITMAP,760,198,LR_LOADFROMFILE); 119. bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,640,480,LR_LOADFROMFILE); 120. 121. 122. //设定所有恐龙初始的贴图坐标都为(200,200),初始的移动方向都为向左。 123. for(i=0;i 124. { 125. dra[i].dir = 3; //起始方向 126. dra[i].x = 200; //贴图的起始X坐标 127. dra[i].y = 200; //贴图的起始Y坐标 128. } 129. 130. MyPaint(hdc); 131. 132. return TRUE; 133.} 134. 135.//气泡排序 136.void BubSort(int n) 137.{ 138. int i,j; 139. bool f; 140. dragon tmp; 141. 142. for(i=0;i 143. { 144. f = false; 145. for(j=0;j 146. { 147. if(dra[j+1].y < dra[j].y) 148. { 149. tmp = dra[j+1]; 150. dra[j+1] = dra[j]; 151. dra[j] = tmp; 152. f = true; 153. } 154. } 155. if(! f) 156. break; 157. } 158.} 159. 160.//****自定义绘图函数********************************* 161.// 1.对窗口中跑动的恐龙进行排序贴图 162.// 2.恐龙贴图坐标修正 163.void MyPaint(HDC hdc) 164.{ 165. int w,h,i; 166. 167. if(picNum == 8) 168. picNum = 0; 169. 170. //在mdc中先贴上背景图 171. SelectObject(bufdc,bg); 172. BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY); 173. 174. BubSort(draNum); //贴上恐龙图之前调用BubSort()函数进行排序 175. 176. 177. //下面这个for循环,按照目前恐龙的移动方向dra[i].dir,选取对应的位图到bufdc中,并设定截切的大小。 每一张要在窗口上出现的恐龙图案依次先在mdc上进行透明贴图的操作。 178. for(i=0;i 179. { 180. SelectObject(bufdc,draPic[dra[i].dir]); 181. switch(dra[i].dir) 182. { 183. case 0: 184. w = 66; 185. h = 94; 186. break; 187. case 1: 188. w = 68; 189. h = 82; 190. break; 191. case 2: 192. w = 95; 193. h = 99; 194. break; 195. case 3: 196. w = 95; 197. h = 99; 198. break; 199. } 200. BitBlt(mdc,dra[i].x,dra[i].y,w,h,bufdc,picNum*w,h,SRCAND); 201. BitBlt(mdc,dra[i].x,dra[i].y,w,h,bufdc,picNum*w,0,SRCPAINT); 202. } 203. 204. //将最后画面显示在窗口中 205. BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY); 206. 207. tPre = GetTickCount(); //记录此次绘图时间 208. picNum++; 209. 210. 211. //下面这个for循环,决定每一只恐龙下一次的移动方向及贴图坐标 212. for(i=0;i 213. { 214. switch(rand()%4) //随机数除以4的余数来决定下次移动方向,余数0,1,2,3分别代表上,下,左,右 215. { 216. //case 0里面的代码,按照目前的移动方向来修正因为各个方向图案尺寸不一致而产生的贴图坐标误差,加入恐龙每次移动的单位量(上,下,左,右每次20个单位)而得到下次新的贴图坐标 217. case 0: //上 218. switch(dra[i].dir) 219. { 220. case 0: 221. dra[i].y -= 20; 222. break; 223. case 1: 224. dra[i].x += 2; 225. dra[i].y -= 31; 226. break; 227. case 2: 228. dra[i].x += 14; 229. dra[i].y -= 20; 230. break; 231. case 3: 232. dra[i].x += 14; 233. dra[i].y -= 20; 234. break; 235. } 236. //在计算出新的贴图坐标之后,还需判断此新的坐标会不会使得恐龙贴图超出窗口边界,若超出,则将该方向上的坐标设定为刚好等于临界值 237. if(dra[i].y < 0) 238. dra[i].y = 0; 239. dra[i].dir = 0; 240. break; 241. //其他方向按照和上面相同的方法计算 242. case 1: //下 243. switch(dra[i].dir) 244. { 245. case 0: 246. dra[i].x -= 2; 247. dra[i].y += 31; 248. break; 249.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Visual C+游戏开发笔记之十一 基础动画显示四 排序贴图 C+ 游戏 开发 笔记 十一 基础 动画 显示 排序 贴图