GDI打砖块游戏

Posted 第二根杈

tags:

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

//header.h文件

#pragma once
#include <windows.h>
#include <stdio.h>

#define KEYDOWN(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)    ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

//Game.h文件

#pragma once
#include "header.h"

const int    BRICKNUM = 20;
typedef struct
{
    int            x;        //球的位置
    int            y;
    int            radius;    //球的半径
    int            speed;    //球的速度
    int            moveX;    //每次移动的值(带正负)
    int            moveY;    //每次移动的值
    COLORREF        color;    //球的颜色
}BALL;

typedef struct
{
    int            width;    //砖的宽度
    int            height;    //砖的高度
    RECT        rect;
    COLORREF    color;    //砖的颜色
    bool        exist;
}BRICK;

class CGame
{
private:
    HWND        m_hWnd;
    HDC            m_hdc;
    RECT        m_wndRect;
    BALL        m_Ball;
    BRICK*        m_pBrick;
    BRICK        m_Bar;
public:
    CGame(HWND  hWnd);
    ~CGame(void);

    void    Render();
    void    ClearScreen();        //清除屏幕
    void    DrawBrick();        //画砖块
    void    DrawBar();            //画挡板
    void    DrawBall();            //画小球
    void    MoveBall();            //小球移动
    void    TestBrickCollide();    //判断碰撞砖块
    void    TestBarCollide();    //判断碰撞挡板
    void    MoveBar(int speed);    //移动挡板
};

//Game.cpp文件

#include "Game.h"
//---------------------------------------------------------
// Name: CGame
// Desc: 构造函数,初始化
//---------------------------------------------------------
CGame::CGame(HWND  hWnd)
{
    m_hWnd    = hWnd;
    m_hdc    = GetDC(m_hWnd);
    GetWindowRect(m_hWnd, &m_wndRect);

    //初始化砖块
    m_pBrick    = new BRICK[BRICKNUM];
    int StartX    = m_wndRect.right / 5;    //第一块砖块的位置
    int StartY    = m_wndRect.bottom / 6;
    for(int i = 0; i < BRICKNUM; i++)
    {
        (m_pBrick + i)->width = 50;
        (m_pBrick + i)->height = 25;
        (m_pBrick + i)->color = RGB(255, 40, 100);
        (m_pBrick + i)->rect.left = StartX +(i % 5) *(m_pBrick + i)->width;
        (m_pBrick + i)->rect.top = StartY +(i / 5) *(m_pBrick + i)->height;
        (m_pBrick + i)->rect.right =(m_pBrick + i)->rect.left +(m_pBrick + i)->width;
        (m_pBrick + i)->rect.bottom    =(m_pBrick + i)->rect.top +(m_pBrick + i)->height;
        (m_pBrick + i)->exist = true;
    }

    //初始化挡板
    m_Bar.color = RGB(0, 0, 255);
    m_Bar.exist = true;
    m_Bar.height = 15;
    m_Bar.width = 60;
    m_Bar.rect.left = m_wndRect.right / 2 - m_Bar.width / 2;    //游戏开始画在//窗口中央底部
    m_Bar.rect.top = m_wndRect.bottom *(8.0 / 10);
    m_Bar.rect.right = m_Bar.rect.left + m_Bar.width;
    m_Bar.rect.bottom = m_Bar.rect.top  + m_Bar.height;

    //初始化小球
    m_Ball.color = RGB(0, 255, 255);
    m_Ball.radius = 10;
    m_Ball.x = m_Bar.rect.left + m_Bar.width / 2;    //小球开始出现在挡板的正上方//中央

    m_Ball.y = m_Bar.rect.top  - m_Ball.radius;
    m_Ball.speed = 1;
    m_Ball.moveX = m_Ball.speed;
    m_Ball.moveY = -m_Ball.speed;

}
//---------------------------------------------------------
// Name: ~CGame
// Desc: 析构函数
//---------------------------------------------------------
CGame::~CGame(void)
{
    ReleaseDC(m_hWnd, m_hdc);
}

//---------------------------------------------------------
// Name: Render
// Desc: 游戏的渲染部分
//---------------------------------------------------------
void CGame::Render()
{
    ClearScreen();
    DrawBrick();
    MoveBar(3);
    DrawBar();
    TestBrickCollide();
    TestBarCollide();
    MoveBall();
    DrawBall();
}

//---------------------------------------------------------
// Name: DrawBrick
// Desc: 画出没被小球打中的砖块
//---------------------------------------------------------
void CGame::DrawBrick()
{
    bool gamesuccess = true;
    for(int i = 0; i < BRICKNUM; i++)
    {
        if((m_pBrick + i)->exist)
        {
            //画实心矩形
            HBRUSH    hBrush    = ::CreateSolidBrush((m_pBrick + i)->color);
            SelectObject(m_hdc, hBrush);
            ::FillRect(m_hdc, &(m_pBrick + i)->rect, hBrush);
            SelectObject(m_hdc, hBrush);
            DeleteObject(hBrush);

            //画矩形外框
            HPEN hPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
            SelectObject(m_hdc, hPen);
            MoveToEx(m_hdc,(m_pBrick + i)->rect.left, (m_pBrick + i)->rect.top, NULL);
            LineTo(m_hdc, (m_pBrick + i)->rect.right, (m_pBrick + i)->rect.top);
            LineTo(m_hdc, (m_pBrick + i)->rect.right, (m_pBrick + i)->
rect.bottom);
            LineTo(m_hdc, (m_pBrick + i)->rect.left, (m_pBrick + i)->
rect.bottom);
            LineTo(m_hdc, (m_pBrick + i)->rect.left, (m_pBrick + i)->rect.top);
            SelectObject(m_hdc, hPen);
            DeleteObject(hPen);

            gamesuccess = false;
        }
    }
    
    if(gamesuccess)
    {
        MessageBox(m_hWnd, L"游戏成功!", L"Congratulation!", MB_OK);
        exit(0);
    }
}

//---------------------------------------------------------
// Name: DrawBar
// Desc: 画挡板
//---------------------------------------------------------
void CGame::DrawBar()
{
    HBRUSH hBrush = CreateSolidBrush(m_Bar.color);
    SelectObject(m_hdc, hBrush);
    FillRect(m_hdc, &m_Bar.rect, hBrush);
    SelectObject(m_hdc, hBrush);
    DeleteObject(hBrush);

    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
    SelectObject(m_hdc, hPen);
    MoveToEx(m_hdc, m_Bar.rect.left, m_Bar.rect.top, NULL);
    LineTo(m_hdc, m_Bar.rect.right, m_Bar.rect.top);
    LineTo(m_hdc, m_Bar.rect.right, m_Bar.rect.bottom);
    LineTo(m_hdc, m_Bar.rect.left, m_Bar.rect.bottom);
    LineTo(m_hdc, m_Bar.rect.left, m_Bar.rect.top);
    SelectObject(m_hdc, hPen);
    DeleteObject(hPen);
}

//---------------------------------------------------------
// Name: DrawBall
// Desc: 画小球
//---------------------------------------------------------
void CGame::DrawBall()
{
    HBRUSH hBrush = CreateSolidBrush(m_Ball.color);
    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 255));
    SelectObject(m_hdc, hBrush);
    SelectObject(m_hdc, hPen);
    Ellipse(m_hdc, m_Ball.x - m_Ball.radius, m_Ball.y - m_Ball.radius, m_Ball.x + m_Ball.radius, m_Ball.y + m_Ball.radius);
    SelectObject(m_hdc, hPen);
    SelectObject(m_hdc, hBrush);
    DeleteObject(hPen);
    DeleteObject(hBrush);
}

//---------------------------------------------------------
// Name: ClearScreen
// Desc: 清屏
//---------------------------------------------------------
void CGame::ClearScreen()
{
    HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
    SelectObject(m_hdc, hBrush);
    FillRect(m_hdc, &m_wndRect, hBrush);
    SelectObject(m_hdc, hBrush);
    DeleteObject(hBrush);
}

//---------------------------------------------------------
// Name: MoveBall
// Desc: 移动小球
//---------------------------------------------------------
void CGame::MoveBall()
{
    if(m_Ball.x + m_Ball.moveX + m_Ball.radius > m_wndRect.right ||
        m_Ball.x + m_Ball.moveX - m_Ball.radius < m_wndRect.left)
    {
        m_Ball.moveX = -m_Ball.moveX;
    }
    if(m_Ball.y + m_Ball.moveY - m_Ball.radius < m_wndRect.top)
    {
        m_Ball.moveY = -m_Ball.moveY;
    }
    if(m_Ball.y + m_Ball.moveY + m_Ball.radius > m_wndRect.bottom)
    {
        MessageBox(m_hWnd, L"游戏结束!", L"GameOver", MB_OK);
        exit(0);
    }
    m_Ball.x += m_Ball.moveX;
    m_Ball.y += m_Ball.moveY;
}

//---------------------------------------------------------
// Name: TestBrickCollide
// Desc: 测试小球是否与砖块碰撞
//---------------------------------------------------------
void CGame::TestBrickCollide()
{
    POINT    pt;
    pt.x = m_Ball.x;
    pt.y = m_Ball.y;
    HRGN hrgn = ::CreateRectRgn(m_Ball.x - m_Ball.radius, m_Ball.y - 
m_Ball.radius, m_Ball.x + m_Ball.radius, m_Ball.y + m_Ball.radius);
    for(int i = 0; i < BRICKNUM; i++)
    {
        
        if((m_pBrick + i)->exist &&
            RectInRegion(hrgn, &(m_pBrick + i)->rect))
        {
            if(m_Ball.x <(m_pBrick + i)->rect.left &&
                m_Ball.moveX > 0)
            {
                (m_pBrick + i)->exist = false;
                m_Ball.moveX = -m_Ball.moveX;
                return;
            }
            if(m_Ball.x >(m_pBrick + i)->rect.right &&
                m_Ball.moveX < 0)
            {
                (m_pBrick + i)->exist = false;
                m_Ball.moveX = -m_Ball.moveX;
                return;
            }
            if(m_Ball.y <(m_pBrick + i)->rect.top &&
                m_Ball.moveY > 0)
            {
                (m_pBrick + i)->exist = false;
                m_Ball.moveY = -m_Ball.moveY;
                return;
            }
            if(m_Ball.y >(m_pBrick + i)->rect.bottom &&
                m_Ball.moveY < 0)
            {
                (m_pBrick + i)->exist = false;
                m_Ball.moveY = -m_Ball.moveY;
                return;
            }
        }
    }
    DeleteObject(hrgn);
}
//---------------------------------------------------------
// Name: TestBarCollide
// Desc: 测试小球是否与挡板碰撞
//---------------------------------------------------------
void CGame::TestBarCollide()
{
    HRGN hrgn = ::CreateRectRgn(m_Ball.x - m_Ball.radius, m_Ball.y - 
m_Ball.radius, m_Ball.x + m_Ball.radius, m_Ball.y + m_Ball.radius);
    if(RectInRegion(hrgn, &m_Bar.rect))
    {
        m_Ball.moveY = -m_Ball.moveY;
        float a =(m_Ball.x - m_Bar.rect.left);
        float b = a / m_Bar.width;
        m_Ball.moveX =((b - 0.5) * 5);
    }
    DeleteObject(hrgn);
}

//---------------------------------------------------------
// Name: MoveBar
// Desc: 移动挡板
//---------------------------------------------------------
void CGame::MoveBar(int speed)
{
    if(KEYDOWN(VK_LEFT))
    {
        if(m_Bar.rect.left - speed < m_wndRect.left)
            return;
        m_Bar.rect.left  -= speed;
        m_Bar.rect.right -= speed;
    }
    if(KEYDOWN(VK_RIGHT))
    {
        if(m_Bar.rect.right + speed > m_wndRect.right)
            return;
        m_Bar.rect.left  += speed;
        m_Bar.rect.right += speed;
    }
}

//main.cpp文件

#include "header.h"
#include "Game.h"

CGame* g_pGame;
//windows 的回调函数
long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM    lParam)
{
    switch(message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);    //向操作系统传递退出的消息,只有当窗口销毁之后,WM_QUIT才能生效结束这个进程
    return 0;

    case WM_KEYDOWN:
        switch(wParam)
        {
            case VK_ESCAPE:
            PostMessage(hWnd, WM_CLOSE, 0, 0);    //向操作系统传递关闭窗口消息,WM_CLOSE会触发WM_DESTROY消息
            break;
        }
        break;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)    //缩放,如按最小化时,都由这个控制
{
    MSG msg;    //定义一个消息的对象
    HWND hWnd;    //窗口句柄
    WNDCLASS wc;        //定义窗口类

    //创建窗口类
    wc.style = CS_HREDRAW | CS_VREDRAW;    //支持水平和垂直重绘
    wc.lpfnWndProc = WindowProc;        //相应的消息处理函数
    wc.cbClsExtra = 0;                //附加内存空间
    wc.cbWndExtra = 0;                //附加内存空间
    wc.hInstance = hInstance;            //窗口的实例句柄
    wc.hIcon = NULL;                    //窗口的小图标
    wc.hCursor = NULL;                            //窗口的鼠标形状
    wc.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);//背景颜色
    wc.lpszMenuName = NULL;                        //窗口菜单
    wc.lpszClassName = L"createwindows";            //窗口名称

    RegisterClass(&wc);    //注册窗口句柄
    
    hWnd = CreateWindowEx(WS_EX_TOPMOST, L"createwindows", L"Create Window Title", WS_OVERLAPPEDWINDOW, 0,    0, 400, 300, NULL, NULL, hInstance,     NULL);            
    
    if(!hWnd)        //判断窗口是否建立成功
    {
        MessageBox(NULL, L"窗口建立失败!", L"error", NULL);
        return FALSE;
    }

    g_pGame = new CGame(hWnd);

    ShowWindow(hWnd, nCmdShow);        //显示窗口
    UpdateWindow(hWnd);                //更新窗口,默认调用了回调函数
    
    while(true)
    {
        //接受系统消息(&msg 为 MSG 类型的信息结构体,NULL 窗口句柄,0, 0 表示
        //接受所有的窗口信息)
        if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            if(msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);        //转化信息
            DispatchMessage(&msg);        //分配信息到相应的消息处理
        }
        else
        {
            g_pGame->Render();
            Sleep(10);
        }
    }
    return 1;
}

 

以上是关于GDI打砖块游戏的主要内容,如果未能解决你的问题,请参考以下文章

一百多行js代码实现打砖块小游戏

Unity3D OpenVR 虚拟现实 保龄球打砖块游戏开发

Unity项目 - 打砖块游戏

原生JS实现简单打砖块弹球小游戏

Unity3D OpenVR 虚拟现实 保龄球打砖块游戏开发

Unity3D OpenVR 虚拟现实 保龄球打砖块游戏开发