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

本文章链接:http://blog.csdn.net/terence1212/article/details/44208419

作者:ZeeCoder  微博链接:http://weibo.com/zc463717263

我的邮箱:michealfloyd@126.com   欢迎大家发邮件来和我交流编程心得

you are what you read!与大家共勉!

-------------------------------------------------------分割线:ZeeCoder-----------------------------------------------

上一个学习笔记中写了用定时器来实现简易动画,但是在实际游戏编程开发中,往往需要游戏画面在一秒之内更新至少25次以上,这一秒钟内程序还必须进行消息的处理和大量数学运算甚至音效的输出等操作。如此看来,定时器往往满足不了这一需求。所以提出了游戏循环的概念,其基本思想是:判断其中的内容是否有当前要处理的消息,如果有则处理,否则按照设定的时间间隔来重绘画面。其代码如下:

<span style="font-size:12px;">//gamecircle
GetMessage(&msg,NULL,NULL,NULL);//MSG初始化,如果没有初始化会报错
while ( msg.message != WM_QUIT)//如果窗口消息不是WM_QUIT,则继续运行循环
{
	//BOOL PeekMessage(		//函数原型
	//	LPMSG IpMsg,	//接受消息用的MSG指针
	//	HWND hWnd,	//某消息被检查的窗口句柄
	//	UINT wMSGfilterMin, //指定被检查的消息范围里的第一个消息
	//	UINT wMsgFilterMax,	//指定被检查的消息范围里的最后一个消息
	//	UINT wRemoveMsg		//确定消息如何被处理
	//	);
	if ( PeekMessage( &msg , NULL ,0 ,0 ,PM_REMOVE))//PM_REMOVE消息从队列里除掉
	{
		TranslateMessage( &msg);
		DispatchMessage(&msg);
	}
	else
	{
		tNow = GetTickCount();
		if (tNow - tPre >= 100)   //相差0.1秒时在进行重绘操作
			MyPaint(hdc);
	}
}</span>

上述代码理解后就可以进行游戏循环的编程了。来看具体代码

1、声明全局变量

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
HBITMAP walker[16];
HDC hdc , mdc ;
HWND hwnd;
DWORD tPre , tNow ,tCheck; //tPre记录上一次的绘图时间,tNow记录此次准备绘图的时间,tCheck记录每秒开始的时间
int num ,frame ,fps;//num记录图号,frame用来累加每次画面更新的次数,fps记录每秒画面更新的次数

2、主函数

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_GAMECIRCLE, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}
	////gamecircle
	GetMessage(&msg,NULL,NULL,NULL);//MSG初始化,如果没有初始化会报错
	while ( msg.message != WM_QUIT)
	{
		//BOOL PeekMessage(
		//	LPMSG IpMsg,	//接受消息用的MSG指针
		//	HWND hWnd,		//某消息被检查的窗口句柄
		//	UINT wMSGfilterMin, //指定被检查的消息范围里的第一个消息
		//	UINT wMsgFilterMax,	//指定被检查的消息范围里的最后一个消息
		//	UINT wRemoveMsg		//确定消息如何被处理
		//	);
		if ( PeekMessage( &msg , NULL ,0 ,0 ,PM_REMOVE))//PM_REMOVE消息从队列里除掉
		{
			TranslateMessage( &msg);
			DispatchMessage(&msg);
		}
		else
		{
			tNow = GetTickCount();
			if (tNow - tPre >= 100)   //相差0.1秒时在进行重绘操作
				MyPaint(hdc);
		}
	}

3、自定义绘图函数

void MyPaint(HDC hdc)
{
	TCHAR str[40];

	if (num == 15)
		num =0;
	frame++;		//更新次数加1
	if (tNow - tCheck  >= 1000)
	{
		fps = frame;
		frame = 0 ;
		tCheck = tNow;
	}
	SelectObject(mdc , walker[num]);
	_stprintf_s(str , TEXT("每秒显示%d个画面") ,fps );
	TextOut(mdc , 0 ,0 , str , _tcslen(str));
	BitBlt(hdc , 0 ,0 ,600 ,450 , mdc , 0 , 0 ,SRCCOPY);
	tPre = GetTickCount(); //记录此次绘图时间
	num++;
}

4、初始化函数

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   TCHAR filename[20] ;
   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }
   MoveWindow(hWnd , 10 ,10 ,600 ,450 ,true);
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   hdc = GetDC(hWnd);
   mdc = CreateCompatibleDC(hdc);
   int i;
   //载入各个人物位图
   for ( i = 0 ; i <= 15 ;i++)
   {
	   _stprintf_s(filename , TEXT("%d.bmp") , i);
	   walker[i] = (HBITMAP)LoadImage(NULL , filename , IMAGE_BITMAP , 121 ,129, LR_LOADFROMFILE);
   }
   num = 0 ;
   frame = 0 ;
   MyPaint(hdc);
   return TRUE;
}

5、实现效果:

我们设定的画面更新时间是0.1秒,那么每秒中最多更新10次。

笔记三就写到这里了,还是那句话,欢迎大家发邮件和我交流学习~也请继续关注我的学习笔记~

学习游戏编程的路还很长,我还没有入门,望继续坚持下去,自我勉励~

end~

												

【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. Bash脚本编程学习笔记07:循环结构体

    本篇中涉及到算术运算,使用了$[]这种我未在官方手册中见到的用法,但是确实可用的,在此前的博文<Bash脚本编程学习笔记03:算术运算>中我有说明不要使用,不过自己忘记了.大家还是尽量使用 ...

  8. 【Visual C++】游戏编程学习笔记之五:单一背景滚动

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

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

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

随机推荐

  1. Android新特性Instant Run详解

    关于 Instant Run Android Studio 2.0 中引入的 Instant Run 是 Run 和 Debug 命令的行为,可以大幅缩短应用更新的时间.尽管首次构建可能需要花费较长的 ...

  2. FORM开发之说明性弹性域开发

    1.注册使用弹性域的表,字段 注册表语法:ad_dd.register_table('所有者','表名','T自动扩展/S非自动扩展','下一区','自由','已使用') AD_DD.REGISTER ...

  3. Android简易实战教程--第二十七话《自定义View入门案例之开关按钮详细分析》

    转载此博客请注明出处点击打开链接       http://blog.csdn.net/qq_32059827/article/details/52444145 对于自定义view,可能是一个比较大的 ...

  4. Android-MVVM架构-Data Binding的使用

    项目整体效果: Awesome-Android-MVVM 什么是MVVM, 为什么需要 MVVM? 如何在Android中使用Data Binding实现MVVM架构? 什么是MVVM , 为什么需要 ...

  5. 【Netty源码分析】发送数据过程

    前面两篇博客[Netty源码分析]Netty服务端bind端口过程和[Netty源码分析]客户端connect服务端过程中我们分别介绍了服务端绑定端口和客户端连接到服务端的过程,接下来我们分析一下数据 ...

  6. Java基础---集合框架---迭代器、ListIterator、Vector中枚举、LinkedList、ArrayList、HashSet、TreeSet、二叉树、Comparator

    为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 数组和集合类同是容器,有何不同? 数组虽然也可以存储对 ...

  7. Python爬虫! 单爬,批量爬,这都不是事!

    昨天做了一个煎蛋网妹子图的爬虫,个人感觉效果不错.但是每次都得重复的敲辣么多的代码(相比于Java或者其他语言的爬虫实现,Python的代码量可谓是相当的少了),就封装了一下!可以实现对批量网址以及单 ...

  8. MySQL输入密码后闪退,这里有解

    不知道怎么的,我的MySQL就像抽风了一样,可能是不想理我了吧.只要我输入密码,它就会闪退.而且使用其他的数据库管理工具也是链接不成功的.于是下决心,调教调教它,于是有了下面的这些解决方案. 解决方法 ...

  9. 最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)

    ===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...

  10. Linux_Oracle命令大全

     一,启动 1.#su - oracle              切换到oracle用户且切换到它的环境 2.$lsnrctl status           查看监听及数据库状态 3.$ls ...