本系列文章由@二货梦想家张程 所写,转载请注明出处。
本文章链接:http://blog.csdn.net/terence1212/article/details/44224963
作者:ZeeCoder 微博链接:http://weibo.com/zc463717263
我的邮箱:michealfloyd@126.com 欢迎大家发邮件来和我交流编程心得
you are what you read!与大家共勉!
-----------------------------------------------------------分割线:ZeeCoder--------------------------------------------------------
一、本笔记要实现利用键盘响应来控制单一背景滚动
首先单一背景滚动的方法是:准备一张相当大的背景图,当游戏进行时,随着画面中人物的移动,背景的显示区域也跟着移动,相信玩过LOL的都知道,游戏中画面移动的方式有两种(1)跟随人物移动(2)鼠标移动到边界来控制背景滚动。
要制作单一背景滚动的方法很简单,看下图:
图中矩形框为我们要显示的背景区域,(x,y)为矩形框左上角坐标。那么我们不难发现,在每次利用BitBlt进行贴图的时候只需要改变x,y的值就可以实现单一背景滚动。
在消息队列中加入WM_KEYDOWN代表了按下键盘的处理,在此处更新x,y的值即可。
二、程序代码:
相信大家如果看了前几篇笔记会发现博主在写代码的时候相当凌乱,所以今天特意将代码理了理,以便日后复习起来能够更加方便,也方便读者阅读。
#include "stdafx.h" #include "RunBg.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name HDC hdc,mdc; HWND hWnd; HBITMAP bg; DWORD tNow , tPre; int x = 0 , y = 0 ; // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); void MyPaint(HDC hdc); /***************************主函数**********************************/ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_RUNBG, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } // Main message loop: GetMessage(&msg , NULL , NULL , NULL); while (msg.message != WM_QUIT) { if ( PeekMessage( &msg , NULL ,0 ,0 ,PM_REMOVE))//PM_REMOVE消息从队列里除掉 { TranslateMessage( &msg); DispatchMessage(&msg); } else { tNow = GetTickCount();//实现游戏循环 if (tNow - tPre >= 100) { MyPaint(hdc); } } } return (int) msg.wParam; } /***************************窗口类函数函数**********************************/ ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RUNBG)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_RUNBG); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } /***************************初始化函数**********************************/ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(_T("RunBg"), _T("背景滚动"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } MoveWindow(hWnd , 10 , 10 , 640 ,360 ,true ); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); hdc = GetDC(hWnd); mdc = CreateCompatibleDC(hdc); bg = (HBITMAP)LoadImage(NULL , _T("res.bmp") , IMAGE_BITMAP , 900 , 506 , LR_LOADFROMFILE);//加载背景图 MyPaint(hdc); return TRUE; } //***************************消息响应函数********************************** //按下【↑】【↓】【←】【→】使背景滚动 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_KEYDOWN: switch (wParam) { case VK_LEFT: //响应【←】按键 x -= 20; if (x <0) { x = 0; } break; case VK_RIGHT://响应【→】按键 x += 20; if (x > 900) { x = 900; } break; case VK_UP://响应【↑】按键 y -= 20 ; if (y < 0) { y = 0; } break;//响应【↓】按键 case VK_DOWN: y += 20; if (y >= 506) { y = 506; } break; } break; case WM_DESTROY: DeleteDC(mdc); DeleteObject(bg); ReleaseDC(hWnd , hdc); PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //***************************自定义绘图函数********************************* //按照x,y来实现背景图的剪裁贴图 void MyPaint(HDC hdc) { SelectObject(mdc , bg); BitBlt(hdc , 0 , 0 ,640 , 360 , mdc , x , y , SRCCOPY);//x,y代表背景图的左上角坐标 tPre = GetTickCount(); }
三、实现效果
哈哈,特意在背景中p上一个人物让背景移动更直观。
笔记五就写到这了。今天最大的感悟就是:在书上看到这些程序,往往只是看看,而不去动手实现的话,你就永远只是知其然而不知其所以然。特别是在最开始学习的时候,必须每个小程序都要自己亲自码代码,跑程序,要重视这一过程,相信只有这样才能学到更多,学得更扎实。
还是那句老话,希望大家在看了我的笔记能留下宝贵的意见,也欢迎志同道合之人给我发邮件讨论游戏编程,互助才能学得更快。
---end!
本笔记配套使用代码已上传,欢迎下载查阅:【Visual C++】游戏编程笔记五配套代码