#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)); }
利用VS创建一个游戏(2)实现半透明化处理(代码+注释)
猜你喜欢
转载自blog.csdn.net/hao5119266/article/details/80008187
今日推荐
周排行