使用EasyX和C++写一个消砖块游戏

Posted 半昧白兰地

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用EasyX和C++写一个消砖块游戏相关的知识,希望对你有一定的参考价值。

 第一次玩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 }

 

效果:

以上是关于使用EasyX和C++写一个消砖块游戏的主要内容,如果未能解决你的问题,请参考以下文章

2019春第三次课程设计实验报告

2019春第二次课程设计实验报告

C++经典绘图工具EasyX

贪吃蛇easyx版本

实时钟表,Easyx,C++

第二次课程设计实验报告