利用C++創建一個遊戲(9)憤怒的小鳥(代碼+註釋)

#include "stdafx.h"      
#include "MyGameFrame.h"      
#include <stdio.h>

//小鳥結構體
struct Bird
{
	int x, y;
};

//全局變量
HWND              hWnd;
HINSTANCE         hInst;
HDC               hdc, mdc, bufdc;
HBITMAP           bg, ship, bird;
int               x, y, nowX, nowY;
int               w = 0;
DWORD             tPre, tNow;
Bird              p[3];


// 此代碼模塊中包含的函數的前向聲明:     
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitWindow(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
VOID                AIGamePaint(HDC hdc);

int APIENTRY WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR    lpCmdLine,
	int       nCmdShow)
{
	// 初始化全局字符串    
	MyRegisterClass(hInstance);

	// 執行應用程序初始化:     
	if (!InitWindow(hInstance, nCmdShow))//初始化窗口    
	{
		return FALSE;//如果不成功則返回FALSE,並退出程序    
	}

	MSG msg; //創建消息類對象    

			 // TODO: 在此放置運行代碼。

			 //定義局部變量
	HBITMAP           bmp;
	POINT             pt, lt, rb;

	/*
	typedef struct tagRECT
	{
	LONG    left;
	LONG    top;
	LONG    right;
	LONG    bottom;
	} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
	RECT結構定義了一個矩形框左上角以及右下角的座標
	*/
	RECT              rect;

	//建立內存DC和窗口DC
	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);

	//建立適用位圖
	bmp = CreateCompatibleBitmap(hdc, 640, 480);
	SelectObject(mdc, bmp);

	//加載圖片
	bg = (HBITMAP)LoadImage(NULL, "sky.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);
	ship = (HBITMAP)LoadImage(NULL, "ship.bmp", IMAGE_BITMAP, 100, 148, LR_LOADFROMFILE);
	bird = (HBITMAP)LoadImage(NULL, "bird.bmp", IMAGE_BITMAP, 122, 122, LR_LOADFROMFILE);

	//定義鼠標初始位置
	x = 300;
	y = 300;

	//定義飛機初始位置
	nowX = 300;
	nowY = 300;

	//定義鼠標光標位置
	pt.x = 300;
	pt.y = 300;

	//把窗口座標轉換爲屏幕座標
	ClientToScreen(hWnd, &pt);

	//設定光標位置
	//SetCursorPos該函數把光標移到屏幕的指定位置(參數均爲屏幕座標)。
	//如果新位置不在由 ClipCursor()函數設置的屏幕矩形區域之內,則系統自動調整座標,使得光標在矩形之內。
	SetCursorPos(pt.x, pt.y);

	//不顯示光標
	ShowCursor(false);

	//限制鼠標光標僅僅在遊戲窗口內移動
	//GetClientRect用於取得指定窗口的客戶區域大小
	//每個窗口區域可分爲兩部分,用於顯示內容的區域叫Client區(客戶區),NonClient(非客戶區)用於顯示命令按鈕及窗口標題等。
	//非客戶區的繪圖是由WM_NCPAINT發出的。
	GetClientRect(hWnd, &rect);

	lt.x = rect.left;
	lt.y = rect.top;
	rb.x = rect.right;
	rb.y = rect.bottom;

	//轉化座標
	ClientToScreen(hWnd, <);
	ClientToScreen(hWnd, &rb);

	rect.left = lt.x;
	rect.top = lt.y;
	rect.right = rb.x;
	rect.bottom = rb.y;

	//設置區域大小
	ClipCursor(&rect);

	p[0].x = 30;                                            //第一個小鳥的位置
	p[0].y = 100;
	p[1].x = 250;                                          //第二個小鳥的位置
	p[1].y = 250;
	p[2].x = 500;                                          //第三個小鳥的位置
	p[2].y = 400;

	//繪圖
	AIGamePaint(hdc);

	// 主消息循環:     
	PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//賦初值    

	while (msg.message != WM_QUIT)         //進入遊戲消息循環:    
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg); //獲得遊戲玩家輸入的消息;    
			DispatchMessage(&msg);//分配玩家消息並響應用戶消息。    
		}
		else
		{
			tNow = GetTickCount();
			if (tNow - tPre >= 40)
				AIGamePaint(hdc);
		}
	}

	return (int)msg.wParam;
}



//    
//  函數: MyRegisterClass()    
//    
//  註冊Windows類,一款遊戲有且僅有一個主窗口,與遊戲程序唯一對應。創建遊戲窗口前要填寫窗口類結構體WNDCLASSEX    
//    
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex =
	{
		wcex.cbSize = sizeof(WNDCLASSEX),


		CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,

		WndProc,0,0,

		hInstance,

		LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),

		LoadCursor(NULL, IDC_ARROW),


		(HBRUSH)(COLOR_WINDOW + 1),NULL,

		_T("GameFrame"),

		LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
	};
	return RegisterClassEx(&wcex);
}

//    
//   函數: InitInstance(HINSTANCE, int)    
//    
//   目的: 保存實例句柄並創建主窗口    
//    
//   註釋:     
//    
//        在此函數中,我們在全局變量中保存實例句柄並    
//        創建和顯示主程序窗口。    
//    
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // 將實例句柄存儲在全局變量中    

	hWnd = CreateWindow
	(
		_T("GameFrame"),
		_T("遊戲框架"),
		WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通樣式,不能改變大小,不能最大化    
		CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, nullptr, nullptr, hInstance, nullptr
	);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//    
//  函數: WndProc(HWND, UINT, WPARAM, LPARAM)    
//    
//  目的:    處理主窗口的消息。    
//    
//  WM_COMMAND  - 處理應用程序菜單    
//  WM_PAINT    - 繪製主窗口    
//  WM_DESTROY  - 發送退出消息並返回    
//    
//    
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{  
	switch (msg)                        //判斷消息    
	{
	case WM_CREATE:
		//執行初始化代碼                  
		return(0);
		break;
	//esc退出程序
	case WM_KEYDOWN:
		if (wparam == VK_ESCAPE)
			PostQuitMessage(0);
		break;
	case WM_MOUSEMOVE:
		//獲取鼠標X座標
		x = LOWORD(lparam);
		if (x > 530)
			x = 530;
		else if (x < 0)
			x = 0;
		//獲取鼠標Y座標
		y = HIWORD(lparam);
		if (y > 380)
			y = 380;
		else  if (y < 0)
			y = 0;
		break;
	case WM_DESTROY:
		//關閉程序,發送WM_QUIT消息    
		PostQuitMessage(0);
		return(0);
		break;
	default:
		break;
	}
	return (DefWindowProc(hwnd, msg, wparam, lparam));
}
void AIGamePaint(HDC hdc)
{
	int i;
	SelectObject(bufdc, bg);

	//背景移動
	BitBlt(mdc, 0, 0, w, 480, bufdc, 640 - w, 0, SRCCOPY);
	BitBlt(mdc, w, 0, 640 - w, 480, bufdc, 0, 0, SRCCOPY);

	//根據光標點擊位置進行X位置修正
	if (nowX < x)
	{
		nowX += 10;
		if (nowX > x)
			nowX = x;
	}
	else
	{
		nowX -= 10;
		if (nowX < x)
			nowX = x;
	}

	//根據光標點擊位置進行Y位置修正
	if (nowY < y)
	{
		nowY += 10;
		if (nowY > y)
			nowY = y;
	}
	else
	{
		nowY -= 10;
		if (nowY < y)
			nowY = y;
	}

	//貼飛機
	SelectObject(bufdc, ship);

	//透明處理
	BitBlt(mdc, nowX, nowY, 100, 74, bufdc, 0, 74, SRCAND);
	BitBlt(mdc, nowX, nowY, 100, 74, bufdc, 0, 0, SRCPAINT);

	//貼小鳥
	SelectObject(bufdc, bird);                                       

	for (i = 0; i<3; i++) {
		if (rand() % 3 != 1) {                              //設定追逐機率
			if (p[i].y > nowY - 16)
				p[i].y -= 5;
			else
				p[i].y += 5;
			if (p[i].x > nowX - 25)
				p[i].x -= 5;
			else
				p[i].x += 5;
		}
		if (p[i].x > nowX - 25) {                     
			//判斷小鳥移動方向	   	         
			BitBlt(mdc,p[i].x,p[i].y,61,61,bufdc,61,61,SRCAND);
			BitBlt(mdc,p[i].x,p[i].y,61,61,bufdc,0,61,SRCPAINT); 
		}
		else {
			BitBlt(mdc, p[i].x, p[i].y, 61, 61, bufdc, 61, 0, SRCAND);
			BitBlt(mdc, p[i].x, p[i].y, 61, 61, bufdc, 0, 0, SRCPAINT);
		}
	}

	BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
	tPre = GetTickCount();

	//背景移動
	w += 10;
	if (w >= 640)
		w = 0;
} 

結果如圖所示:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章