GDI打磚塊遊戲
阿新 • • 發佈:2018-03-29
菜單 ips 窗口 nbsp ide cpp instance 碰撞 style
//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; typedefstruct { 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打磚塊遊戲