利用VS创建一个游戏(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));
}


猜你喜欢

转载自blog.csdn.net/hao5119266/article/details/80008187