第一次玩EasyX,写一个比较简单的消砖块游戏。
主函数包括Game的类的开始,运行和结束。
#include "BrickElimination.h" int main() { GameBrickElimination NewGame; NewGame.game_start(); NewGame.game_run(); NewGame.game_over(); return 0; }
game_start()是所有元素的初始化,包括图像,砖块,弹球和挡板。
game_run()是游戏的主体,包括刷新界面,更新球的运动情况等。
game_over()是游戏的结束,停掉绘制。
头文件,定义了所有使用的类。
#ifndef _BRICK_ELIMINATION_ #define _BRICK_ELIMINATION_ /* Settings */ #define GRAPH_HEIGHT 480 #define GRAPH_WIDTH 720 #define BRICK_NUM 20 #define BAR_MOVE_SPEED 15 #define BAR_WIDTH (GRAPH_WIDTH/5) #define BALL_MOVE_SPEED 1 #define BALL_RADIUS 20 #define BRICK_EXIST 1 #define BRICK_NOT_EXIST 0 /* type define */ typedef enum { Ball_Hit_Wall = 0, Ball_Hit_Bar, Ball_Hit_Brick, Ball_Sill_Moving }Ball_Hit_Type; typedef struct { int left; int right; int top; int bottom; }Brick_Group; /* class ball define */ class CBall { private: int m_ball_x, m_ball_y; int m_ball_vx, m_ball_vy; int m_radius; public: CBall(); ~CBall(); void ball_init_v(); void ball_clean_v(); void ball_show_v(); void ball_move_v(); int get_x() { return m_ball_x; }; int get_y() { return m_ball_y; }; int get_r() { return m_radius; }; int get_vx() { return m_ball_vx; }; int get_vy() { return m_ball_vy; }; void set_vx(int vx) { m_ball_vx = vx; }; void set_vy(int vy) { m_ball_vy = vy; }; }; /* class brick define */ class CBrick { private: Brick_Group Bricks[BRICK_NUM]; int m_isBrickExisted[BRICK_NUM]; int m_brick_height, m_brick_width; public: CBrick(); ~CBrick(); void brick_init_v(); void brick_clean_v(); void brick_show_v(); int isBrickExist(int i) { return m_isBrickExisted[i]; }; void setBrickExist(int i, int state) { m_isBrickExisted[i] = state; }; int bricks_left(int i) { return Bricks[i].left; }; int bricks_right(int i) { return Bricks[i].right; }; int bricks_top(int i) { return Bricks[i].top; }; int bricks_bottom(int i) { return Bricks[i].bottom; }; }; /* class bar define */ class CBar { private: int m_bar_x, m_bar_y; int m_bar_width, m_bar_height; int m_bar_left, m_bar_right, m_bar_top, m_bar_bottom; public: CBar(); ~CBar(); void bar_init_v(); void bar_clean_v(); void bar_show_v(); void bar_move_v(); int get_left() { return m_bar_left; }; int get_right() { return m_bar_right; }; int get_top() { return m_bar_top; }; int get_bottom() { return m_bar_bottom; }; int get_width() { return m_bar_width; }; int get_height() { return m_bar_height; }; }; /* class game define */ class GameBrickElimination { private: CBall ball; CBar bar; CBrick brick; public: GameBrickElimination(); ~GameBrickElimination(); Ball_Hit_Type check_ball_hit(Ball_Hit_Type isHit); void game_start(); void game_run(); void game_over(); }; #endif
类的实现,有几个关键点。
1.使用BeginBatchDraw(),FlushBatchDraw(),EndBatchDraw()来不闪屏地刷新界面,原理是在旧位置上画黑色图形覆盖掉旧位置,同时画出新位置,然后批量绘制。
2.判断球的相撞,其实就是比较球和砖块,挡板的坐标。
3.球的位置通过坐标和速度更新,球反弹的效果通过撞击以后速度设为反方向来实现。使用一个标志量来判断某个砖块是否消失。
/* BrickEliminationElements.cpp */ #include "BrickElimination.h" #include <graphics.h> #include <conio.h> #include "windows.h" /* class ball realization */ CBall::CBall() { } CBall::~CBall() { } void CBall::ball_init_v() { m_ball_x = GRAPH_WIDTH / 2; m_ball_y = GRAPH_HEIGHT / 2; m_ball_vx = BALL_MOVE_SPEED; m_ball_vy = BALL_MOVE_SPEED; m_radius = BALL_RADIUS; } void CBall::ball_clean_v() { setcolor(BLACK); setfillcolor(BLACK); fillcircle(m_ball_x, m_ball_y, m_radius); } void CBall::ball_show_v() { setcolor(YELLOW); setfillcolor(GREEN); fillcircle(m_ball_x, m_ball_y, m_radius); } void CBall::ball_move_v() { m_ball_x += m_ball_vx; m_ball_y += m_ball_vy; } /* class brick realization */ CBrick::CBrick() { } CBrick::~CBrick() { } void CBrick::brick_init_v() { m_brick_width = GRAPH_WIDTH / BRICK_NUM; m_brick_height = GRAPH_HEIGHT / BRICK_NUM; for (int i = 0; i < BRICK_NUM; i++) { Bricks[i].left = i * m_brick_width; Bricks[i].right = Bricks[i].left + m_brick_width; Bricks[i].top = 0; Bricks[i].bottom = m_brick_height; m_isBrickExisted[i] = BRICK_EXIST; } } void CBrick::brick_clean_v() { setcolor(BLACK); setfillcolor(BLACK); for (int i = 0; i < BRICK_NUM; i++) { if (m_isBrickExisted[i] == BRICK_NOT_EXIST) { fillrectangle(Bricks[i].left, Bricks[i].top, Bricks[i].right, Bricks[i].bottom); } else { /* do thing */ } } } void CBrick::brick_show_v() { for (int i = 0; i < BRICK_NUM; i++) { if (m_isBrickExisted[i]) { setcolor(WHITE); setfillcolor(RED); fillrectangle(Bricks[i].left, Bricks[i].top, Bricks[i].right, Bricks[i].bottom); } else { /* do thing */ } } } /* class bar realization */ CBar::CBar() { } CBar::~CBar() { } void CBar::bar_init_v() { m_bar_width = BAR_WIDTH; m_bar_height = GRAPH_HEIGHT / 20; m_bar_x = GRAPH_WIDTH / 2; m_bar_y = GRAPH_HEIGHT - m_bar_height / 2; m_bar_left = m_bar_x - m_bar_width / 2; m_bar_right = m_bar_x + m_bar_width / 2; m_bar_top = m_bar_y - m_bar_height / 2; m_bar_bottom = m_bar_y + m_bar_height / 2; } void CBar::bar_clean_v() { setcolor(BLACK); setfillcolor(BLACK); bar(m_bar_left, m_bar_top, m_bar_right, m_bar_bottom); } void CBar::bar_show_v() { setcolor(YELLOW); setfillcolor(GREEN); bar(m_bar_left, m_bar_top, m_bar_right, m_bar_bottom); } void CBar::bar_move_v() { char input; if (_kbhit()) { input = _getch(); if (input == ‘a‘ && m_bar_left > 0) { m_bar_x -= BAR_MOVE_SPEED; m_bar_left = m_bar_x - m_bar_width / 2; m_bar_right = m_bar_x + m_bar_width / 2; } else if (input == ‘d‘ && m_bar_right < GRAPH_WIDTH) { m_bar_x += BAR_MOVE_SPEED; m_bar_left = m_bar_x - m_bar_width / 2; m_bar_right = m_bar_x + m_bar_width / 2; } else { /* do thing */ } } else { /* do thing */ } } GameBrickElimination::GameBrickElimination() { } GameBrickElimination::~GameBrickElimination() { } Ball_Hit_Type GameBrickElimination::check_ball_hit(Ball_Hit_Type isHit) { switch (isHit) { case Ball_Hit_Wall: { //check ball hit wall or not if ((ball.get_x() <= ball.get_r()) || (ball.get_x() >= GRAPH_WIDTH - ball.get_r())) { ball.set_vx(-ball.get_vx()); return Ball_Hit_Wall; } else { /* do nothing */ } if ((ball.get_y() <= ball.get_r()) || (ball.get_y() >= GRAPH_HEIGHT - ball.get_r())) { ball.set_vy(-ball.get_vy()); return Ball_Hit_Wall; } else { /* do nothing */ } break; } case Ball_Hit_Bar: { if (((ball.get_y() + ball.get_r() >= bar.get_top()) && (ball.get_y() + ball.get_r() < bar.get_bottom() - bar.get_height() / 3)) || ((ball.get_y() - ball.get_r() <= bar.get_bottom()) && (ball.get_y() - ball.get_r() > bar.get_top() - bar.get_height() / 3))) { if ((ball.get_x() > bar.get_left()) && (ball.get_x() < bar.get_right())) { ball.set_vy(-ball.get_vy()); return Ball_Hit_Bar; } else { /* do nothing */ } } else { /* do nothing */ } break; } case Ball_Hit_Brick: { for (int i = 0; i < BRICK_NUM; i++) { if (brick.isBrickExist(i) == BRICK_EXIST) { if ((ball.get_y() <= brick.bricks_bottom(i) + ball.get_r()) && (ball.get_x() >= brick.bricks_left(i)) && (ball.get_x() <= brick.bricks_right(i))) { brick.setBrickExist(i, BRICK_NOT_EXIST); ball.set_vy(-ball.get_vy()); return Ball_Hit_Brick; } else { /* do nothing */ } } else { /* do nothing */ } } break; } default: { break; } } } /* class game realization */ void GameBrickElimination::game_start() { ball.ball_init_v(); bar.bar_init_v(); brick.brick_init_v(); initgraph(GRAPH_WIDTH, GRAPH_HEIGHT); BeginBatchDraw(); } void GameBrickElimination::game_run() { while (1) { ball.ball_clean_v(); bar.bar_clean_v(); brick.brick_clean_v(); check_ball_hit(Ball_Hit_Wall); ball.ball_move_v(); check_ball_hit(Ball_Hit_Bar); bar.bar_move_v(); check_ball_hit(Ball_Hit_Brick); ball.ball_show_v(); bar.bar_show_v(); brick.brick_show_v(); FlushBatchDraw(); Sleep(3); } } void GameBrickElimination::game_over() { EndBatchDraw(); closegraph(); }
效果:
原文地址:https://www.cnblogs.com/banmei-brandy/p/12500087.html
时间: 2024-10-03 21:45:01