2D动态天空

BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);

首先我们需要一张天空的背景图


用Bitblt函数进行贴图

SelectObject(g_bufdc, g_hBackGround);
	BitBlt(g_mdc, 0,0 , g_iBGOffset, WINDOW_HEIGHT, g_bufdc, WINDOW_WIDTH - g_iBGOffset, 0, SRCCOPY);
	BitBlt(g_mdc, g_iBGOffset, 0, WINDOW_WIDTH - g_iBGOffset, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY);
BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);

这里用到缓冲链技术,两张图贴到g_mdc中再贴到g_hdc也就是屏幕,虽然这里差别不大,但是贴图如果多的话不用缓冲链直接贴图游戏显示会很不流畅。

g_tNow = GetTickCount();   //获取当前系统时间
			if (g_tNow - g_tPre >= 5)        //当此次循环运行与上次绘图时间相差0.005秒时再进行重绘操作
				Game_Paint(hwnd);
g_tPre = GetTickCount();

 g_iBGOffset是一个变量每次循环都会+5


下面在主函数里加入循环使Paint函数每隔o.oo5s重绘一次。

这样动态天空就实现了。
下面是完整代码

//--------------------------程序说明-----------------------------
//程序名称:GDIdemo
//描述:GDI绘图模版
//---------------------------------------------------------------
//------------------------头文件部分------------------------------
#include<Windows.h>
#include<time.h>

//可以在此区域继续添加头文件
//--------------------------------------------------------------------
//------------------------宏定义-------------------------------------
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE L"GDI程序框架"
//-------------------------------------------------------------------
//----------------------全局变量声明部分-----------------------------

HDC g_hdc = NULL,g_mdc=NULL,g_bufdc=NULL;//全局设备环境句柄
HBITMAP g_hBitmap = NULL;//定义一个位图句柄
DWORD g_tPre = 0, g_tNow = 0;//记录绘图时间
int g_iNum = 0, g_iX = 0, g_iY = 0;//图号和图的横纵坐标
//----------------全局函数声明部分---------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);//窗口过程函数
BOOL Game_Init(HWND hwnd);//在此函数进行资源初始化
VOID Game_Paint(HWND hwnd);//在此函数进行绘图代码的书写
BOOL Game_CleanUp(HWND hwnd);//在此函数进行资源的清理


//--------------------WinMain---------------------------------------
//Windows应用程序的入口函数
//---------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	//[1]窗口创建四部曲之一:开始设计一个完整的窗口类
	WNDCLASSEX  wc = {};//用WNDCLASSEX定义了一个窗口类
	wc.cbSize = sizeof(WNDCLASSEX);//设置结构体的字节数大小
	wc.style = CS_HREDRAW | CS_VREDRAW;//设置窗口的样式
	wc.lpfnWndProc = WndProc;//设置指向窗口过程的指针
	wc.cbClsExtra = 0;//窗口类的附加内存
	wc.cbWndExtra = 0;//窗口的附加内存
	wc.hInstance = hInstance;//制定包含窗口过程的程序的实例句柄
	wc.hIcon = (HICON)::LoadImage(NULL, L"", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);//本地加载自定义图标“”
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);//指定窗口类的光标句柄
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);//指定一个灰色画刷句柄
	wc.lpszClassName = L"WINDOW";//用一个空终止的字符串,指定窗口类的名字
	wc.lpszMenuName = NULL;//用一个空终止的字符串,指定菜单资源的名字

	//[2]窗口的创建四部曲之二:注册窗口类
	if (!RegisterClassEx(&wc))//设计完窗口,需要对窗口类进行注册,这样才能创建该类型的窗口
		return -1;
	//[3]窗口创建四部曲之三:正式创建窗口
	HWND hwnd = CreateWindow(L"WINDOW", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
	//窗口创建四部曲之四:窗口的移动,显示与更新
	MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);//调整窗口显示時的位置位于(250,80)处
	ShowWindow(hwnd, nShowCmd);//调用showwindow来显示窗口
	UpdateWindow(hwnd);//队窗口进行更新
	//游戏资源的初始化,若初始化失败弹出一个消息框并返回FALSE
	if (!Game_Init(hwnd))
	{
		MessageBox(hwnd, L"初始化资源失败", L"消息窗口", 0);//使用MESSASGEBOX创建一个消息窗口
		return FALSE;
	}
	MSG msg = { 0 };//定义并初始化msg
	while (msg.message != WM_QUIT)//使用while循环,如果消息不是wm-quit消息,就继续循环
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))//查看应用程序消息队列,有消息時就将队列中的消息派发出去
		{
			TranslateMessage(&msg);//将虚拟消息转换为字符消息
			DispatchMessage(&msg);//分发一个消息给窗口程序
		}
		else
		{
			g_tNow = GetTickCount();
			if (g_tNow - g_tPre >= 5)
				Game_Paint(hwnd);
			
		}
	}

	//[6]窗口类的注销
	UnregisterClass(L"WINDOW", wc.hInstance);//程序准备结束注销窗口类
	return 0;
}
//-----------------------------WinProc函数-----------------------------------------
//对窗口消息进行处理
//---------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT paintStruct;//定义一个paintstruct来记录绘制信息

	switch (message)//switch程序开始
	{
	case WM_KEYDOWN://键盘按下消息
		if (wParam == VK_ESCAPE)//如果按下esc
			DestroyWindow(hwnd);//销毁窗口并发送wm-destroy消息
		break;
	case WM_DESTROY://若是窗口销毁信息
		Game_CleanUp(hwnd);
		PostQuitMessage(0);//向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
		break;//跳出该switch语句

	default://若上述case条件都不符合,则执行default语句
		return DefWindowProc(hwnd, message, wParam, lParam);//调用默认的窗口过程
	}
	return 0;//正常退出
}
//-------------------------【Game_Init】
BOOL Game_Init(HWND hwnd)
{
	g_hdc = GetDC(hwnd);
	HBITMAP bmp;
	g_hBitmap = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 800, 600, LR_LOADFROMFILE);//位图加载
	g_mdc = CreateCompatibleDC(g_hdc);//和g_ hdc兼容的DC
	g_bufdc = CreateCompatibleDC(g_hdc);//缓冲DC
	bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
	SelectObject(g_mdc, bmp);
	g_iX = 0;
	Game_Paint(hwnd);
	//ReleaseDC(hwnd, g_hdc);//这句话导致不能平移!!!!!!!!!!!!!!!!释放掉了再调用肯定不行啊都根屏幕失去连接了
	return TRUE;
}
//-------------------------【Game_Paint】
VOID Game_Paint(HWND hwnd)
{  
	if (g_iX==800)
	{
		g_iX = 0;
	}
	
	SelectObject(g_bufdc, g_hBitmap);//将位图对象选入到g_mdc内存dc中
	BitBlt(g_mdc, g_iX, 0, WINDOW_WIDTH-g_iX, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY);
	BitBlt(g_mdc, 0, 0, g_iX, WINDOW_HEIGHT, g_bufdc, WINDOW_WIDTH - g_iX, 0, SRCCOPY);
	BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);
	g_tPre = GetTickCount();
	g_iX+= 5;
}
//-----------------------------[Game_CleanUp]
BOOL Game_CleanUp(HWND hwnd)
{
	DeleteObject(g_hBitmap);
	DeleteDC(g_mdc);
	DeleteDC(g_hdc);
	DeleteDC(g_bufdc);
	return TRUE;
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值