第一次玩EasyX,写一个比较简单的消砖块游戏。
主函数包括Game的类的开始,运行和结束。
1 #include "BrickElimination.h"
2
3 int main()
4 {
5 GameBrickElimination NewGame;
6
7 NewGame.game_start();
8 NewGame.game_run();
9 NewGame.game_over();
10
11 return 0;
12 }
game_start()是所有元素的初始化,包括图像,砖块,弹球和挡板。
game_run()是游戏的主体,包括刷新界面,更新球的运动情况等。
game_over()是游戏的结束,停掉绘制。
头文件,定义了所有使用的类。
1 #ifndef _BRICK_ELIMINATION_
2 #define _BRICK_ELIMINATION_
3
4 /* Settings */
5 #define GRAPH_HEIGHT 480
6 #define GRAPH_WIDTH 720
7 #define BRICK_NUM 20
8 #define BAR_MOVE_SPEED 15
9 #define BAR_WIDTH (GRAPH_WIDTH/5)
10 #define BALL_MOVE_SPEED 1
11 #define BALL_RADIUS 20
12
13 #define BRICK_EXIST 1
14 #define BRICK_NOT_EXIST 0
15
16
17 /* type define */
18 typedef enum
19 {
20 Ball_Hit_Wall = 0,
21 Ball_Hit_Bar,
22 Ball_Hit_Brick,
23 Ball_Sill_Moving
24 }Ball_Hit_Type;
25
26 typedef struct
27 {
28 int left;
29 int right;
30 int top;
31 int bottom;
32 }Brick_Group;
33
34
35 /* class ball define */
36 class CBall
37 {
38 private:
39 int m_ball_x, m_ball_y;
40 int m_ball_vx, m_ball_vy;
41 int m_radius;
42
43 public:
44 CBall();
45 ~CBall();
46 void ball_init_v();
47 void ball_clean_v();
48 void ball_show_v();
49 void ball_move_v();
50 int get_x() { return m_ball_x; };
51 int get_y() { return m_ball_y; };
52 int get_r() { return m_radius; };
53 int get_vx() { return m_ball_vx; };
54 int get_vy() { return m_ball_vy; };
55 void set_vx(int vx) { m_ball_vx = vx; };
56 void set_vy(int vy) { m_ball_vy = vy; };
57
58 };
59
60 /* class brick define */
61 class CBrick
62 {
63 private:
64 Brick_Group Bricks[BRICK_NUM];
65 int m_isBrickExisted[BRICK_NUM];
66 int m_brick_height, m_brick_width;
67
68 public:
69 CBrick();
70 ~CBrick();
71 void brick_init_v();
72 void brick_clean_v();
73 void brick_show_v();
74 int isBrickExist(int i) { return m_isBrickExisted[i]; };
75 void setBrickExist(int i, int state) { m_isBrickExisted[i] = state; };
76 int bricks_left(int i) { return Bricks[i].left; };
77 int bricks_right(int i) { return Bricks[i].right; };
78 int bricks_top(int i) { return Bricks[i].top; };
79 int bricks_bottom(int i) { return Bricks[i].bottom; };
80 };
81
82 /* class bar define */
83 class CBar
84 {
85 private:
86 int m_bar_x, m_bar_y;
87 int m_bar_width, m_bar_height;
88 int m_bar_left, m_bar_right, m_bar_top, m_bar_bottom;
89
90 public:
91 CBar();
92 ~CBar();
93 void bar_init_v();
94 void bar_clean_v();
95 void bar_show_v();
96 void bar_move_v();
97 int get_left() { return m_bar_left; };
98 int get_right() { return m_bar_right; };
99 int get_top() { return m_bar_top; };
100 int get_bottom() { return m_bar_bottom; };
101 int get_width() { return m_bar_width; };
102 int get_height() { return m_bar_height; };
103 };
104
105 /* class game define */
106 class GameBrickElimination
107 {
108 private:
109 CBall ball;
110 CBar bar;
111 CBrick brick;
112
113 public:
114 GameBrickElimination();
115 ~GameBrickElimination();
116 Ball_Hit_Type check_ball_hit(Ball_Hit_Type isHit);
117 void game_start();
118 void game_run();
119 void game_over();
120 };
121
122 #endif
类的实现,有几个关键点。
1.使用BeginBatchDraw(),FlushBatchDraw(),EndBatchDraw()来不闪屏地刷新界面,原理是在旧位置上画黑色图形覆盖掉旧位置,同时画出新位置,然后批量绘制。
2.判断球的相撞,其实就是比较球和砖块,挡板的坐标。
3.球的位置通过坐标和速度更新,球反弹的效果通过撞击以后速度设为反方向来实现。使用一个标志量来判断某个砖块是否消失。
1 /* BrickEliminationElements.cpp */
2
3 #include "BrickElimination.h"
4 #include <graphics.h>
5 #include <conio.h>
6 #include "windows.h"
7
8 /* class ball realization */
9 CBall::CBall()
10 {
11 }
12
13 CBall::~CBall()
14 {
15 }
16
17 void CBall::ball_init_v()
18 {
19 m_ball_x = GRAPH_WIDTH / 2;
20 m_ball_y = GRAPH_HEIGHT / 2;
21 m_ball_vx = BALL_MOVE_SPEED;
22 m_ball_vy = BALL_MOVE_SPEED;
23 m_radius = BALL_RADIUS;
24 }
25
26 void CBall::ball_clean_v()
27 {
28 setcolor(BLACK);
29 setfillcolor(BLACK);
30 fillcircle(m_ball_x, m_ball_y, m_radius);
31 }
32
33 void CBall::ball_show_v()
34 {
35 setcolor(YELLOW);
36 setfillcolor(GREEN);
37 fillcircle(m_ball_x, m_ball_y, m_radius);
38 }
39
40 void CBall::ball_move_v()
41 {
42 m_ball_x += m_ball_vx;
43 m_ball_y += m_ball_vy;
44 }
45
46 /* class brick realization */
47 CBrick::CBrick()
48 {
49 }
50
51 CBrick::~CBrick()
52 {
53 }
54
55 void CBrick::brick_init_v()
56 {
57 m_brick_width = GRAPH_WIDTH / BRICK_NUM;
58 m_brick_height = GRAPH_HEIGHT / BRICK_NUM;
59
60 for (int i = 0; i < BRICK_NUM; i++)
61 {
62 Bricks[i].left = i * m_brick_width;
63 Bricks[i].right = Bricks[i].left + m_brick_width;
64 Bricks[i].top = 0;
65 Bricks[i].bottom = m_brick_height;
66 m_isBrickExisted[i] = BRICK_EXIST;
67 }
68 }
69
70 void CBrick::brick_clean_v()
71 {
72 setcolor(BLACK);
73 setfillcolor(BLACK);
74
75 for (int i = 0; i < BRICK_NUM; i++)
76 {
77 if (m_isBrickExisted[i] == BRICK_NOT_EXIST)
78 {
79 fillrectangle(Bricks[i].left, Bricks[i].top, Bricks[i].right, Bricks[i].bottom);
80 }
81 else
82 {
83 /* do thing */
84 }
85 }
86 }
87
88 void CBrick::brick_show_v()
89 {
90 for (int i = 0; i < BRICK_NUM; i++)
91 {
92 if (m_isBrickExisted[i])
93 {
94 setcolor(WHITE);
95 setfillcolor(RED);
96 fillrectangle(Bricks[i].left, Bricks[i].top, Bricks[i].right, Bricks[i].bottom);
97 }
98 else
99 {
100 /* do thing */
101 }
102 }
103 }
104
105 /* class bar realization */
106 CBar::CBar()
107 {
108 }
109
110 CBar::~CBar()
111 {
112 }
113
114 void CBar::bar_init_v()
115 {
116 m_bar_width = BAR_WIDTH;
117 m_bar_height = GRAPH_HEIGHT / 20;
118 m_bar_x = GRAPH_WIDTH / 2;
119 m_bar_y = GRAPH_HEIGHT - m_bar_height / 2;
120 m_bar_left = m_bar_x - m_bar_width / 2;
121 m_bar_right = m_bar_x + m_bar_width / 2;
122 m_bar_top = m_bar_y - m_bar_height / 2;
123 m_bar_bottom = m_bar_y + m_bar_height / 2;
124 }
125
126 void CBar::bar_clean_v()
127 {
128 setcolor(BLACK);
129 setfillcolor(BLACK);
130 bar(m_bar_left, m_bar_top, m_bar_right, m_bar_bottom);
131 }
132
133 void CBar::bar_show_v()
134 {
135 setcolor(YELLOW);
136 setfillcolor(GREEN);
137 bar(m_bar_left, m_bar_top, m_bar_right, m_bar_bottom);
138 }
139
140 void CBar::bar_move_v()
141 {
142 char input;
143 if (_kbhit())
144 {
145 input = _getch();
146 if (input == 'a' && m_bar_left > 0)
147 {
148 m_bar_x -= BAR_MOVE_SPEED;
149 m_bar_left = m_bar_x - m_bar_width / 2;
150 m_bar_right = m_bar_x + m_bar_width / 2;
151 }
152 else if (input == 'd' && m_bar_right < GRAPH_WIDTH)
153 {
154 m_bar_x += BAR_MOVE_SPEED;
155 m_bar_left = m_bar_x - m_bar_width / 2;
156 m_bar_right = m_bar_x + m_bar_width / 2;
157 }
158 else
159 {
160 /* do thing */
161 }
162 }
163 else
164 {
165 /* do thing */
166 }
167 }
168
169 GameBrickElimination::GameBrickElimination()
170 {
171 }
172
173 GameBrickElimination::~GameBrickElimination()
174 {
175 }
176
177 Ball_Hit_Type GameBrickElimination::check_ball_hit(Ball_Hit_Type isHit)
178 {
179 switch (isHit)
180 {
181 case Ball_Hit_Wall:
182 {
183 //check ball hit wall or not
184 if ((ball.get_x() <= ball.get_r()) || (ball.get_x() >= GRAPH_WIDTH - ball.get_r()))
185 {
186 ball.set_vx(-ball.get_vx());
187 return Ball_Hit_Wall;
188 }
189 else
190 {
191 /* do nothing */
192 }
193
194 if ((ball.get_y() <= ball.get_r()) || (ball.get_y() >= GRAPH_HEIGHT - ball.get_r()))
195 {
196 ball.set_vy(-ball.get_vy());
197 return Ball_Hit_Wall;
198 }
199 else
200 {
201 /* do nothing */
202 }
203 break;
204 }
205 case Ball_Hit_Bar:
206 {
207 if (((ball.get_y() + ball.get_r() >= bar.get_top())
208 && (ball.get_y() + ball.get_r() < bar.get_bottom() - bar.get_height() / 3))
209 || ((ball.get_y() - ball.get_r() <= bar.get_bottom())
210 && (ball.get_y() - ball.get_r() > bar.get_top() - bar.get_height() / 3)))
211 {
212 if ((ball.get_x() > bar.get_left()) && (ball.get_x() < bar.get_right()))
213 {
214 ball.set_vy(-ball.get_vy());
215 return Ball_Hit_Bar;
216 }
217 else
218 {
219 /* do nothing */
220 }
221 }
222 else
223 {
224 /* do nothing */
225 }
226 break;
227 }
228 case Ball_Hit_Brick:
229 {
230 for (int i = 0; i < BRICK_NUM; i++)
231 {
232 if (brick.isBrickExist(i) == BRICK_EXIST)
233 {
234 if ((ball.get_y() <= brick.bricks_bottom(i) + ball.get_r())
235 && (ball.get_x() >= brick.bricks_left(i))
236 && (ball.get_x() <= brick.bricks_right(i)))
237 {
238 brick.setBrickExist(i, BRICK_NOT_EXIST);
239 ball.set_vy(-ball.get_vy());
240 return Ball_Hit_Brick;
241 }
242 else
243 {
244 /* do nothing */
245 }
246 }
247 else
248 {
249 /* do nothing */
250 }
251 }
252 break;
253 }
254 default:
255 {
256 break;
257 }
258 }
259 }
260
261 /* class game realization */
262 void GameBrickElimination::game_start()
263 {
264 ball.ball_init_v();
265 bar.bar_init_v();
266 brick.brick_init_v();
267
268 initgraph(GRAPH_WIDTH, GRAPH_HEIGHT);
269 BeginBatchDraw();
270 }
271
272 void GameBrickElimination::game_run()
273 {
274 while (1)
275 {
276 ball.ball_clean_v();
277 bar.bar_clean_v();
278 brick.brick_clean_v();
279
280 check_ball_hit(Ball_Hit_Wall);
281 ball.ball_move_v();
282
283 check_ball_hit(Ball_Hit_Bar);
284 bar.bar_move_v();
285
286 check_ball_hit(Ball_Hit_Brick);
287
288 ball.ball_show_v();
289 bar.bar_show_v();
290 brick.brick_show_v();
291
292 FlushBatchDraw();
293 Sleep(3);
294 }
295 }
296
297 void GameBrickElimination::game_over()
298 {
299 EndBatchDraw();
300 closegraph();
301 }
效果: