本系列文章由@二货梦想家张程 所写,转载请注明出处。

本文章链接: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++】游戏编程笔记五配套代码

【Visual C++】游戏编程学习笔记之五:单一背景滚动的更多相关文章

  1. 【Visual C++】游戏编程学习笔记之四:透明动画实现

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...

  2. 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...

  3. 【Visual C++】游戏编程学习笔记之七:键盘输入消息

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...

  4. 【Visual C++】游戏编程学习笔记之六:多背景循环动画

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44264153 作者:ZeeCod ...

  5. DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  6. DirectX 11游戏编程学习笔记之6: 第5章The Rendering Pipeline(渲染管线)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  7. 【Visual C++】游戏编程学习笔记之三:游戏循环的使用

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44208419 作者:Zee ...

  8. 【Visual C++】游戏编程学习笔记之九:回合制游戏demo(剑侠客VS巡游天神)

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.com ...

  9. 【Visual C++】游戏编程学习笔记之二:定时器的使用

    本系列文章由@二货梦想家张程所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44195831 作者:ZeeCode ...

随机推荐

  1. [CSDN_Markdown]Markdown基本语法2

    简介 前文 Markdown基本语法 中介绍了Markdown的基本语法,知道那些基本的语法,实际上已经可以写纯文本的博客了.对我们这群写代码的人或者将要写代码的人来说,貌似这些还不够,我们还希望能插 ...

  2. Android 6.0出现的init: cannot execve(‘XXX’):Permission denied问题:禁止SELINUX的权限设置

    最近在开发MTK的相关项目,需要将一些可执行文件添加到init.rc文件里去,但是开机后发现,这个bin文件没有权限不能执行,于是我就在init.rc中对相应的bin文件增加了权限.后来发现,改了也没 ...

  3. DoesNotExist at /admin/

    DoesNotExist at /admin/ User has no account. Request Method: GET Request URL: http://127.0.0.1:8000/ ...

  4. JAVA面向对象-----局部内部类

    局部内部类 局部内部类概述:包含在外部类的函数中的内部类称之为局部内部类. 访问:可以在包含局部内部类的方法中直接创建局部内部类的对象调用局部内部类的成员. 注意:局部内部类只能访问所在函数的fana ...

  5. ORACLE数据库管理常用查询语句

    /*查看表空间的名称及大小*/ SELECT t.tablespace_name, round(SUM(bytes / (1024 * 1024)), 0) ts_size FROM dba_tabl ...

  6. storm如何部署拓扑

    storm集群搭建 比较简单,参考官方文档即可http://storm.apache.org/releases/1.0.2/Setting-up-a-Storm-cluster.html 启动Nimb ...

  7. Android View框架总结(九)KeyEvent事件分发机制

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52335094 本篇开始分析按键消息事件分发(PS:本篇文章中源码均是 ...

  8. xml的今生今世

    跟随小编学习的脚步,今天小编来简单总结一下xml的今生今世,xml百度百科对她这样诠释到:可扩展标记语言 (ExtensibleMarkup Language, XML),用于标记电子文件使其具有结构 ...

  9. Uva - 1594 - Ducci Sequence

    水题,算出每次的结果,比较是否全0,循环1000次还不是全0则LOOP AC代码: #include <iostream> #include <cstdio> #include ...

  10. (国内)完美下载Android源码Ubuntu版

    今天写的文章莫名奇妙的没了,所以再重新写一篇. 首先,为了方便起见,我已经将系统更换成里Ubuntu,因为官方推荐使用这个Linux发行版.先来一张系统的截图: Ubuntu的版本是16.04(推荐用 ...