#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));
}