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

本文章链接: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. Android开发之手把手教你写ButterKnife框架(一)

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/52662376 本文出自:[余志强的博客] 一.概述 JakeWhar ...

  2. [Python]多个装饰器合并

    django程序,需要写很多api,每个函数都需要几个装饰器,例如 @csrf_exempt @require_POST def foo(request): pass 既然那么多个方法都需要写2个装饰 ...

  3. 自制Linux 终端 锁屏防窃助手

    很多时候我们不能一直守护在自己的电脑旁边,而且有些文件并不想让别人知道.那么这时候来个锁屏,是再合适不过的了.今天分享一个自制的锁屏工具,如下. 准备 操作系统 : 我这里是ElementaryOS虚 ...

  4. Android 在 SElinux下 如何获得对一个内核节点的访问权限

    点击打开链接 Android 5.0下,因为采取了SEAndroid/SElinux的安全机制,即使拥有root权限,或者对某内核节点设置为777的权限,仍然无法在JNI层访问. 本文将以用户自定义的 ...

  5. 21 RadioGroup ListFragment

    结构 MainActivity.java package com.qf.day21_radiogroupfragment_demo3; import java.util.ArrayList; impo ...

  6. Android实现系统下拉栏的消息提示——Notification

    Android实现系统下拉栏的消息提示--Notification 系统默认样式 默认通知(通用) 效果图 按钮 <Button android:layout_width="match ...

  7. GDB调试工具入门

    从windows转到linux下已经有一段时间了,每次刷算法题碰到问题需要调试的时候,就分分钟想关机,切换到windows上调试.于是,花了一点时间来搜索一下linux下常见的调试工具,这不搜不知道, ...

  8. Dynamics CRM2015 非基础语言环境下产品无法新建的问题

    该现象出现在2015版本上,之前从没注意过这个问题不知道以前的版本是否存在. 我的安装包的基础语言是中文,第一张图有添加产品的按钮,切换到英文环境下后就没有了,一开始以为是系统做了隐藏处理,但用工具查 ...

  9. Android项目开发填坑记-Fragment的onBackPressed

    Github版 CSDN版 知识背景 Fragment在当前的Android开发中,有两种引用方式,一个是 Android 3.0 时加入的,一个是supportV4包中的.这里简称为Fragment ...

  10. Java基础---Java---IO流-----BufferedReader、BufferedWriter、缓冲区、装饰设计模式及和继承的区别

    IO流 IO流用来处理设备之间的数据传输 java对数据的操作是过流的方式 流按操作数据分为两种:字节流与字符流 流按流向分为:输入流,输出流. IO流常用基类 字节流的抽象基类:InputStrea ...