windows游戏大师编程技巧之以硬拷贝方式剪切位图

windows游戏大师编程技巧之以硬拷贝方式剪切位图
下面是完整的1920*1080 32位色深的实现

#include <Windows.h>
#include <ddraw.h>
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")

#define SCREEN_WIDTH 1920
#define SCREEN_HEIGHT 1080
#define SCREEN_BPP 32
#define KEYDOWN(vk_code) (GetAsyncKeyState(vk_code)&0x8000 ? 1 : 0)
#define KEYUP(vk_code) (GetAsyncKeyState(vk_code)&0x8000 ? 0 : 1)

int Game_Init(void* params = nullptr, int num_params = 0);
int Game_Main(void* params = nullptr, int num_params = 0);
int Game_Shutdown(void* params = nullptr, int num_params = 0);
void Blit_Clipped(int x, int y, int width, int height, LONG* bitmap, LONG* video_buffer, LONG lpitch);

HWND main_hwnd = nullptr;
LPDIRECTDRAW7 lpdd7 = nullptr;
LPDIRECTDRAWSURFACE7 lpddsprimary = nullptr;
LPDIRECTDRAWSURFACE7 lpddsback = nullptr;
DDSURFACEDESC2 ddsd;
int window_closed = 0;

LONG bitmap[64] = {
	RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,0,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,0,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,255,0), RGB(0,0,0), RGB(0,255,0), RGB(0,255,0), RGB(0,0,0), RGB(0,255,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,255,0), RGB(0,0,0), RGB(0,255,0), RGB(0,255,0), RGB(0,0,0), RGB(0,255,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,0,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,255,0), RGB(0,0,0), RGB(0,0,0),
	RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0)
};

struct face {
	int x;
	int y;
	int xv;
	int yv;
};
face happy_faces[100];

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
	TCHAR szAppName[] = TEXT("DxDemo");
	MSG msg;
	WNDCLASS wndclass;

	wndclass.style = CS_HREDRAW | CS_HREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = nullptr;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(nullptr, TEXT("Register class failed"), szAppName, MB_ICONERROR);
		return 0;
	}

	main_hwnd = CreateWindow(
		szAppName, TEXT("DxDemo1"), WS_POPUP | WS_VISIBLE,
		CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT,
		nullptr, nullptr, hInstance, nullptr
	);

	Game_Init();
	
	while (true)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		Game_Main();
	}

	Game_Shutdown();

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		//draw
		EndPaint(hwnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}
	return 0;
}

int Game_Init(void* params, int num_params)
{
	//创建ddraw对象
	if (FAILED(DirectDrawCreateEx(NULL, (LPVOID*)&lpdd7, IID_IDirectDraw7, NULL)))
		return 0;
	//设置协助等级:全屏模式
	if (FAILED(lpdd7->SetCooperativeLevel(main_hwnd, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
		return 0;
	//设置显示模式
	if (FAILED(lpdd7->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
		return 0;

	//clear ddsd and set size
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

	ddsd.dwBackBufferCount = 1;

	//request primary surface
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;

	//create the primary surface
	if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL)))
		return 0;

	ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
	if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
		return 0;
	//init happy_faces
	for (int i = 0; i < 100; i++)
	{
		happy_faces[i].x = rand() % SCREEN_WIDTH;
		happy_faces[i].y = rand() % SCREEN_HEIGHT;
		happy_faces[i].xv = 10;
		happy_faces[i].yv = 10;
	}

	return 1;
}

int Game_Main(void* param, int num_params)
{
	DDBLTFX ddbltfx;

	if (window_closed)
		return 0;

	if (KEYDOWN(VK_ESCAPE))
	{
		SendMessage(main_hwnd, WM_CLOSE, 0, 0);
		window_closed = 1;
	}

	//clear ddbltfx and set size
	memset(&ddbltfx, 0, sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(ddbltfx);
	ddbltfx.dwFillColor = RGB(0, 0, 0);

	if (FAILED(lpddsback->Blt(nullptr, nullptr, nullptr, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
		return 0;

	//clear ddsd and set size
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);

	if (FAILED(lpddsback->Lock(nullptr, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, nullptr)))
		return 0;

	LONG* back_buffer = (LONG *)ddsd.lpSurface;

	for (int i = 0; i < 100; i++)
		Blit_Clipped(happy_faces[i].x, happy_faces[i].y, 8, 8, bitmap, back_buffer, ddsd.lPitch>>2);

	for (int i = 0; i < 100; i++)
	{
		happy_faces[i].x += happy_faces[i].xv;
		happy_faces[i].y += happy_faces[i].yv;

		if (happy_faces[i].x > SCREEN_WIDTH)
			happy_faces[i].x = -8;
		else if (happy_faces[i].x < 0)
			happy_faces[i].x = SCREEN_WIDTH - 1;
		if (happy_faces[i].y > SCREEN_HEIGHT)
			happy_faces[i].y = -8;
		else if (happy_faces[i].y < 0)
			happy_faces[i].y = SCREEN_HEIGHT - 1;
	}

	//clear the back buffer
	/*if (ddsd.lPitch >> 2 == SCREEN_WIDTH)
		memset(back_buffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT * (SCREEN_BPP / 8));
	else
	{
		for (int i = 0; i < SCREEN_HEIGHT; i++)
		{
			memset(back_buffer, 0, SCREEN_WIDTH * (SCREEN_BPP / 8));
			back_buffer += ddsd.lPitch;
		}
	}

	for (int i = 0; i < 5000; i++)
	{
		int x = rand() % SCREEN_WIDTH;
		int y = rand() % SCREEN_HEIGHT;
		back_buffer[x + y * (ddsd.lPitch >> 2)] = RGB(rand() % 256, rand() % 256, rand() % 256);
	}*/

	if (FAILED(lpddsback->Unlock(nullptr)))
		return 0;

	while (FAILED(lpddsprimary->Flip(nullptr, DDFLIP_WAIT)));
	/*RECT source_rect, dest_rect;

	source_rect.left = rand() % SCREEN_WIDTH;
	source_rect.top = rand() % SCREEN_HEIGHT;
	source_rect.right = rand() % SCREEN_WIDTH;
	source_rect.bottom = rand() % SCREEN_HEIGHT;

	dest_rect.left = rand() % SCREEN_WIDTH;
	dest_rect.top = rand() % SCREEN_HEIGHT;
	dest_rect.right = rand() % SCREEN_WIDTH;
	dest_rect.bottom = rand() % SCREEN_HEIGHT;

	if (FAILED(lpddsprimary->Blt(&dest_rect, lpddsback, &source_rect, DDBLT_WAIT, nullptr)))
		return 0;*/

	Sleep(30);

	//if (FAILED(lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
	//	return 0;
	//int mempitch = ddsd.lPitch;//32位色深1920个像素所占的字节数
	//LONG* video_buffer = (LONG *)ddsd.lpSurface;

	//for (int i = 0; i < 1000; i++)
	//{
	//	int x = rand() % SCREEN_WIDTH;
	//	int y = rand() % SCREEN_HEIGHT;
	//	video_buffer[x + (y * mempitch >> 2)] = RGB(rand() % 256, rand() % 256, rand() % 256);
	//}

	//if (FAILED(lpddsprimary->Unlock(NULL)))
	//	return 0;
	//Sleep(30);

	return 1;
}

int Game_Shutdown(void* params, int num_params)
{
	if (lpddsback)
	{
		lpddsback->Release();
		lpddsback = nullptr;
	}
	if (lpddsprimary)
	{
		lpddsprimary->Release();
		lpddsprimary = nullptr;
	}
	if (lpdd7)
	{
		lpdd7->Release();
		lpdd7 = nullptr;
	}

	return 1;
}

void Blit_Clipped(int x, int y, int width, int height, LONG* bitmap, LONG* video_buffer, LONG lpitch)
{
	int xStart = x, yStart = y;
	int xEnd = xStart + width - 1, yEnd = yStart + height - 1;

	if (xStart < 0)
		xStart = 0;
	if (yStart < 0)
		yStart = 0;
	if (xEnd > SCREEN_WIDTH)
		xEnd = SCREEN_WIDTH - 1;
	if (yEnd > SCREEN_HEIGHT)
		yEnd = SCREEN_HEIGHT - 1;

	int x_off = xStart - x;
	int y_off = yStart - y;
	int dx = xEnd - xStart;
	int dy = yEnd - yStart;

	//init video_buffer and bitmap
	video_buffer += xStart + yStart * lpitch;
	bitmap += x_off + y_off * width;
	LONG pixel;

	for (int index_y=0; index_y < dy; index_y++)
	{
		for (int index_x = 0; index_x < dx; index_x++)
		{
			if (pixel = bitmap[index_x])
				video_buffer[index_x] = pixel;
		}
		video_buffer += lpitch;
		bitmap += width;
	}
}

下面是效果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值