使用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++写一个消砖块游戏的主要内容,如果未能解决你的问题,请参考以下文章