利用C++創建一個遊戲(2)實現半透明化處理(代碼+註釋)

#include "stdafx.h"  
#include "MyGameFrame.h" //源cpp文件引申出的頭文件 也可以用resource.h代替  
#include <stdio.h>       //標準輸入輸出頭文件  

// 全局變量:   
HINSTANCE hInst;                                // 當前實例  
HWND      hWnd;
HDC       hdc;                                  //窗口DC
HDC       mdc;                                  //內存DC  
HBITMAP   bg;                                   //背景圖  
HBITMAP   dra, draa;                              //前景圖  
BITMAP    bm1, bm2;                             //位圖指針
const int xstart = 320;
const int ystart = 240;


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

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

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

	/*
	MSG類型見 https://blog.csdn.net/wanghaofeng/article/details/6632165
	*/
	MSG msg; //創建消息類對象

			 // TODO: 在此放置運行代碼。 
	bg = (HBITMAP)LoadImage(NULL, _T("bg.bmp"), IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);//加載背景圖  
	dra = (HBITMAP)LoadImage(NULL, _T("dra.bmp"), IMAGE_BITMAP, 170, 99, LR_LOADFROMFILE);//加載前景圖  

	hdc = GetDC(hWnd);//創建內存DC  
	mdc = CreateCompatibleDC(hdc);//創建窗口DC,CreateCompatibleDC( )函數建立建立內存設備描述表,把存儲在內存DC上的位圖貼到窗口DC中
	HDC bufdc;
	bufdc = CreateCompatibleDC(hdc);

	draa = CreateCompatibleBitmap(hdc, 85, 99);
	SelectObject(mdc, draa);
	SelectObject(bufdc, bg);
	BitBlt(mdc, 0, 0, 85, 99, bufdc, xstart, ystart, SRCCOPY);

	SelectObject(bufdc, dra);     //bmp爲載入的恐龍位圖句柄
	BitBlt(mdc, 0, 0, 85, 99, bufdc, 85, 0, SRCAND);
	BitBlt(mdc, 0, 0, 85, 99, bufdc, 0, 0, SRCPAINT);

	/*------------------------------------------------------半透明理------------------------------------------------------------------------------*/
	unsigned char *px1, *px2;
	//取得位圖結構  
	/*
	半透明技術改變位圖部分像素值,需加載位圖結構
	int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
	hgdiobj:圖形對象句柄。可指向一個邏輯位圖、字體或調色板,可通過CreateDIBsection( )創建與設備無關的位圖。
	cbBuffer:寫到緩衝區信息的字節數目。
	lpvObject:指向緩衝區指針,該緩衝區指定將要檢索圖形對象的信息。緩衝區可接收的信息和類型用hgdiobj來指定。
	*/
	GetObject(bg, sizeof(BITMAP), &bm1);

	if (bm1.bmBitsPixel != 32 && bm1.bmBitsPixel != 24) {
		MessageBox(NULL, "只能在32bit 或24bit 顯示模式下運行", "警告", 0);
		return FALSE;
	}
	//建立暫存數組  
	/*
	取得位圖的結構後,必須建立一個暫存數組準備存儲位圖中所有像素的顏色值。
	暫存數組大小是由取得位圖的bmHeight與bmWidthBytes信息來決定的。
	*/
	px1 = new unsigned char[bm1.bmHeight*bm1.bmWidthBytes];

	//取得位圖數值  
	/*
	建立了暫存數組之後,可使用GetBitmapBits( )函數取出位圖的所有顏色值並存儲到數組中。
	*/
	GetBitmapBits(bg, bm1.bmHeight*bm1.bmWidthBytes, px1);

	//取得位圖結構  
	/*
	半透明技術改變位圖部分像素值,需加載位圖結構
	int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
	hgdiobj:圖形對象句柄。可指向一個邏輯位圖、字體或調色板,可通過CreateDIBsection( )創建與設備無關的位圖。
	cbBuffer:寫到緩衝區信息的字節數目。
	lpvObject:指向緩衝區指針,該緩衝區指定將要檢索圖形對象的信息。緩衝區可接收的信息和類型用hgdiobj來指定。
	*/
	GetObject(draa, sizeof(BITMAP), &bm2);

	//建立暫存數組  
	/*
	取得位圖的結構後,必須建立一個暫存數組準備存儲位圖中所有像素的顏色值。
	暫存數組大小是由取得位圖的bmHeight與bmWidthBytes信息來決定的。
	*/
	px2 = new unsigned char[bm2.bmHeight*bm2.bmWidthBytes];

	//取得位圖數值  
	/*
	建立了暫存數組之後,可使用GetBitmapBits( )函數取出位圖的所有顏色值並存儲到數組中。
	*/
	GetBitmapBits(draa, bm2.bmHeight*bm2.bmWidthBytes, px2);

	int x, y;
	int i;
	int rgb_b;
	int PxBytes = bm1.bmBitsPixel / 8;

	int xend = xstart + 85;
	int yend = ystart + 99;

	for (y = ystart; y<yend; y++) {
		for (x = xstart; x<xend; x++) {
			rgb_b = y * bm1.bmWidthBytes + x * PxBytes;
			px1[rgb_b] = px1[rgb_b] * 3 / 10;
			px1[rgb_b + 1] = px1[rgb_b + 1] * 3 / 10;
			px1[rgb_b + 2] = px1[rgb_b + 2] * 3 / 10;
		}
	}
	for (y = 0; y<(bm2.bmHeight); y++) {
		for (x = 0; x<bm2.bmWidth; x++) {
			rgb_b = y * bm2.bmWidthBytes + x * PxBytes;
			i = (ystart + y) * bm1.bmWidthBytes + (xstart + x) * PxBytes;
			px2[rgb_b] = px2[rgb_b] * 7 / 10 + px1[i];
			px2[rgb_b + 1] = px2[rgb_b + 1] * 7 / 10 + px1[i + 1];
			px2[rgb_b + 2] = px2[rgb_b + 2] * 7 / 10 + px1[i + 2];
		}
	}

	SetBitmapBits(draa, bm2.bmHeight*bm2.bmWidthBytes, px2);                      //根據數組的內容來重設位圖的顏色  
	SelectObject(mdc, bg);
	BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
	SelectObject(mdc, draa);
	BitBlt(hdc, xstart, ystart, 85, 99, mdc, 0, 0, SRCCOPY);

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

	while (msg.message != WM_QUIT)         //進入遊戲消息循環:  
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg); //獲得遊戲玩家輸入的消息;  
			DispatchMessage(&msg);//分配玩家消息並響應用戶消息。  
		}
	}
	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)
{
	PAINTSTRUCT ps;                     //用於WM_PAINT   
	switch (msg)                        //判斷消息  
	{
	case WM_CREATE:
		//執行初始化代碼                
		return(0);
		break;
	case WM_PAINT:
		//確定窗口是否有效  
		hdc = BeginPaint(hwnd, &ps);
		//執行繪製代碼  
		SelectObject(mdc, bg);
		BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);
		SelectObject(mdc, draa);
		BitBlt(hdc, xstart, ystart, 85, 99, mdc, 0, 0, SRCCOPY);

		//BitBlt(hdc, 320, 240, 85, 99, mdc, 85, 0, SRCAND);
		//BitBlt(hdc, 320, 240, 85, 99, mdc, 0, 0, SRCPAINT);
		//結束代碼  
		EndPaint(hwnd, &ps);
		return(0);
		break;
	case WM_DESTROY:
		//關閉程序,發送WM_QUIT消息  
		PostQuitMessage(0);
		return(0);
		break;
	default:
		break;
	}
	return (DefWindowProc(hwnd, msg, wparam, lparam));
}

 

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