今天掌握了Bitmap的用法,忍不住再来一次升级版的应用------用键盘控制人物的走动,这个可能在游戏设计中用的很多,不过今儿就先来小试牛刀,呵呵……
本人学习编程有个"癖好" —— 那就是有了想法,下一步就是实现,越快实现越好,不实现就誓不罢休……
好了,F话少说了,还是先来逐步了解需求吧
(1)首先需要一个完整的人物走路分解图,每一个方向4张,分别是:直立、右脚向前、直立、左脚向前
(资源由本人亲自制作,待会儿上传^_^)
(2)加载位图到内存中,这个和Bitmap应用1一样,不再赘述
(3)获取位图ID
首先需要写两个方法:
[cpp]
1. IDB_BITMAP GetBitmapID(int dir, int dirCount); //获取当前绘制的位图ID
2. void DrawBitmap(HINSTANCE, HDC, int, int, int, int); //绘制位图
3. (IDB_BITMAP就是int)
本程序总共需要16张位图,位图ID是从101开始,每一张是紧挨着的(101~116),所以可以通过ID这个特点来控制位图的选择
GetBitmapID()的参数dir取以下4个之1:(位图的排列顺序为: 前后左右)
[cpp]
1. //位图的方位
2. #define DIR_FRONT 0
3. #define DIR_REAR 1
4. #define DIR_LEFT 2
5. #define DIR_RIGHT 3
参数dirCount取以下4个之1(也就是方向键连续按下的次数,每次对4求余数,因为每一个方向有4张分解图)
[cpp]
1. static int frontC, rearC, leftC, rightC;
2. //计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前)
然后简单的运算就能得到相应的位图ID号:
101 + dir*4 + dirCount
(4)用键盘控制人物的走动
由于每一个方向的处理类似,这里就简述一下向前走的控制算法:
[cpp]
1. rearC=leftC=rightC=0;//清除
2.
3. //控制移动的距离
4. if(!(frontC % 2)) //当人物直立时,移动距离控制为10
5. {
6. y += 10;
7. }
8. else //当人物左脚或右脚向前时,移动距离控制为2 这是经过多次测试得到的数据,这样控制的效果较好
9. {
10. y += 2;
11. }
12.
13. DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);//绘制人物的状态
14. frontC = (frontC+1) % 4;//计算本方向(如果继续按下Dowm键)的下一次移动
(5)清除上一步的状态,也就是将上一步的位图刷掉
方法还是调用BitBlt()方法,只不过是绘制一块白色的位图,仅仅需要将最后一个参数设定为WHITENESS就ok了
好了这就是全过程,以下就是完整代码:
[cpp]
1. //前后左右移动的小猫
2. #include<windows.h>
3. #include<stdio.h>
4. #include"resource.h"
5.
6. //位图的方位
7. #define DIR_FRONT 0
8. #define DIR_REAR 1
9. #define DIR_LEFT 2
10. #define DIR_RIGHT 3
11.
12. //类型的重定义
13. typedef int IDB_BITMAP;
14.
15. /** 为重绘保存上一步的信息 **/
16. //保存上一步的位图
17. BITMAP lastBitmap;
18. //保存上一步位图的坐标
19. int lastX, lastY;
20. //保存上一步位图的方向和按键计数
21. int lastDir, lastDirCount;
22.
23. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
24. IDB_BITMAP GetBitmapID(int, int); //获取当前绘制的位图ID
25. void DrawBitmap(HINSTANCE, HDC, int, int, int, int); //绘制位图
26.
27. int WINAPI WinMain(HINSTANCE hInstance,
28. HINSTANCE hPrevInstance,
29. PSTR szCmdLine,
30. int iCmdShow)
31. {
32. static TCHAR szAppName[] = TEXT("MoveCat");
33. HWND hwnd;
34. MSG msg;
35. WNDCLASS wndclass;
36.
37. wndclass.style = CS_HREDRAW | CS_VREDRAW;
38. wndclass.lpfnWndProc = WndProc;
39. wndclass.cbClsExtra = 0;
40. wndclass.cbWndExtra = 0;
41. wndclass.hInstance = hInstance;
42. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
43. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
44. HBRUSH)GetStockObject(WHITE_BRUSH);
45. wndclass.lpszMenuName = NULL;
46. wndclass.lpszClassName = szAppName;
47.
48. if(!RegisterClass(&wndclass))
49. {
50. "This program requires Windows NT!"),
51. szAppName, MB_ICONERROR);
52. return 0;
53. }
54.
55. hwnd = CreateWindow(szAppName,
56. "MoveCat Demo"),
57. WS_OVERLAPPEDWINDOW,
58. (1366 - 720) / 2,
59. (768 - 570) / 2,
60. 720,
61. 570,
62. NULL,
63. NULL,
64. hInstance,
65. NULL);
66.
67. ShowWindow(hwnd, iCmdShow);
68. UpdateWindow(hwnd);
69.
70. while(GetMessage(&msg, NULL, 0, 0))
71. {
72. TranslateMessage(&msg);
73. DispatchMessage(&msg);
74. }
75.
76. return msg.wParam;
77. }
78.
79. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
80. {
81. static HINSTANCE hInstance;//窗口的实例句柄
82. static int frontC, rearC, leftC, rightC, x, y;
83. //分别表示方位键按键计数和位图显示的位置 计数是为了控制每个方向所显示状态(立正、右脚向前、立正、左脚向前)
84. HDC hdc;
85. PAINTSTRUCT ps;
86.
87. switch(message)
88. {
89. case WM_CREATE:
90. hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
91. return 0 ;
92.
93. case WM_PAINT:
94. hdc = BeginPaint(hwnd, &ps);
95.
96. if(lastBitmap.bmWidth)
97. {
98. DrawBitmap(hInstance, hdc, lastDir, lastDirCount, lastX, lastY);
99. }
100. else
101. {
102. DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);
103. frontC = (frontC + 1) % 4;
104. }
105.
106. EndPaint(hwnd, &ps);
107. return 0;
108.
109. //用键盘控制位图的显示
110. case WM_KEYDOWN:
111. hdc = GetDC(hwnd);
112.
113. switch(wParam)
114. {
115. //向前
116. case VK_UP:
117. //清空除当前方向的所有计数
118.
119. //控制移动的距离
120. if(!(rearC % 2))
121. {
122. y -= 10;
123. }
124. else
125. {
126. y -= 2;
127. }
128.
129. DrawBitmap(hInstance, hdc, DIR_REAR, rearC, x, y);
130. rearC = (rearC+1) % 4;
131.
132. break;
133.
134. //向后
135. case VK_DOWN:
136. rearC=leftC=rightC=0;
137.
138. //控制移动的距离
139. if(!(frontC % 2))
140. {
141. y += 10;
142. }
143. else
144. {
145. y += 2;
146. }
147.
148. DrawBitmap(hInstance, hdc, DIR_FRONT, frontC, x, y);
149. frontC = (frontC+1) % 4;
150.
151. break;
152.
153. //向左
154. case VK_LEFT:
155. frontC=rearC=rightC=0;
156.
157. //控制移动的距离
158. if(!(leftC % 2))
159. {
160. x -= 15;
161. }
162. else
163. {
164. x -= 3;
165. }
166.
167. DrawBitmap(hInstance, hdc, DIR_LEFT, leftC, x, y);
168. leftC = (leftC+1) % 4;
169.
170. break;
171.
172. //向右
173. case VK_RIGHT:
174. frontC=rearC=leftC=0;
175.
176. //控制移动的距离
177. if(!(rightC % 2))
178. {
179. x += 15;
180. }
181. else
182. {
183. x += 3;
184. }
185.
186. DrawBitmap(hInstance, hdc, DIR_RIGHT, rightC, x, y);
187. rightC = (rightC+1) % 4;
188.
189. break;
190. }
191. ReleaseDC(hwnd, hdc);
192. return 0;
193.
194. case WM_DESTROY:
195. PostQuitMessage(0);
196. return 0;
197. }
198.
199. return DefWindowProc(hwnd, message, wParam, lParam);
200. }
201.
202. IDB_BITMAP GetBitmapID(int dir, int dirCount)
203. {
204. return 101 + dir*4 + dirCount;
205. }
206.
207. //绘制位图
208. void DrawBitmap(HINSTANCE hInstance, HDC hdc, int dir, int dirCount, int x, int y)
209. {
210. HBITMAP hBitmap;
211. BITMAP bitmap;
212. HDC hdcMem;
213.
214. //用于创建和hdc兼容的内存设备控制表句柄 也就相当于在内存中绘图,一个缓冲(当然,位图也能支持"截图")
215. hdcMem = CreateCompatibleDC(hdc);
216.
217. hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(GetBitmapID(dir, dirCount)));
218. sizeof(BITMAP), &bitmap);
219. SelectObject(hdcMem, hBitmap);
220.
221. //清除上一步位图信息
222. if(lastBitmap.bmWidth)
223. {
224. BitBlt(hdc, lastX - 1, lastY - 1, lastBitmap.bmWidth + 1, lastBitmap.bmHeight + 1, hdcMem, 0, 0, WHITENESS);
225. }
226.
227. //保存上一步信息
228. lastX = x;
229. lastY = y;
230. lastDir = dir;
231. lastDirCount = dirCount;
232. lastBitmap = bitmap;
233.
234. //绘制当前位图信息
235. BitBlt(hdc, x, y, bitmap.bmWidth - 1, bitmap.bmHeight - 1, hdcMem, 0, 0, SRCCOPY);
236.
237. DeleteObject(hBitmap);
238. DeleteDC(hdcMem);
239. }
运行效果:
download