本系列文章由@二货梦想家张程 所写,转载请注明出处。
本文章链接: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 instanceTCHAR szTitle[MAX_LOADSTRING];// The title bar textTCHAR szWindowClass[MAX_LOADSTRING];// the main window class nameHDC hdc,mdc;HWND hWnd;HBITMAP bg;DWORD tNow , tPre;int x = 0 , y = 0 ;// Forward declarations of functions included in this code module:ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);voidMyPaint(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 stringsLoadString(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++】游戏编程笔记五配套代码