码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2020-03-18 23:44:50      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:getch   red   就是   else   graph   otto   bsp   clean   clu   

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

 

效果:

技术图片

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

标签:getch   red   就是   else   graph   otto   bsp   clean   clu   

原文地址:https://www.cnblogs.com/banmei-brandy/p/12500087.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!