最近在学习《3D 游戏编程大师技巧》第 2 章,摘抄一些我认为重要的信息,并添加上自己的一些思考。
Windows 是一个多任务多线程操作系统,也是一个事件驱动型操作系统。与大多数 DOS 程序不同,大多数 Windows 程序都等待用户做一些事情(从而引发事件),然后 Windows 响应该事件并采取行动,如图 2.1 所示。图 2.1 显示了很多应用程序窗口,它们分别发送事件或消息给 Windows 进行处理。Windows 处理一些消息或事件,但大多数消息或事件都传回应用程序进行处理。
对于图 2.1,我的疑问:怎么判断系统事件应该分发到哪个应用程序的本地事件队列?
所有 Windows 程序都从执行一个名为 WinMain() 的函数开始。
对于 WinMain() 函数,必须使用 WINAPI,否则,启动代码将不能正确地将参数递归给它。
配的目标是编写在 Windows 平台上运行的 3D 游戏,所以无需知道很多有关 Windows 编程的知识。实际上,需要的只是一个框架 Windows 程序,它打开窗口,处理消息并调用主游戏循环,仅此而已。
事件处理程序是一个回调函数,Windows 在窗口中发生需要处理的事件时,在主事件循环中调用该函数。
事件处理程序是由您编写的,因此可处理任何想处理的事件;其它的事件可传递给 Windows 进行处理。当然,应用程序处理的事件和消息越多,其功能越强。
我的疑问:如果多个应用程序都想处理同一个事件,怎么办?
WM_PAINT 消息非常重要。窗口需要重新绘制时发送该消息,这意味着大多数时候您需要执行重绘操作。对于 DirectX 游戏,这无关紧要,因为我们将以 30~60 帧/秒的速度重绘屏幕,但对于普通 Windows 程序而言,这就很重要了。然而,对于 DirectX 应用程序,我们不希望 Windows 认为屏幕没有被重新绘制,所以需要让 Windows 知道我们已经对 WM_PAINT 消息进行处理了。
接下来我们编写一个完整的 Windows 程序,创建一个窗口,并等待用户关闭它。代码跟《DirectX 11 编程:初始化 Windows 窗口》很基本一样。
|
|
效果如下图:
因为 WinMain 里调用的 GetMessage 函数会一直等待消息队列,直到有消息可获取,才分发该消息。
在 GetMessage 等待时消息时,主事件循环实际上被阻断。我们必须想办法解决这个问题,因为我们需要连续地执行游戏处理,并在 Windows 发生时及时处理它。
我们使用 PeekMessage 代替 GetMessage,PeekMessage 检测消息队列中是否有消息,有则处理消息,没有则继续处理其它游戏逻辑并重复循环。
更新后的 WinMain 如下:
|
|
函数调用 Game_Main() 在生成一个动画帧或执行游戏逻辑后必须返回;否则,主窗口事件循环将无法处理消息。
DirectX 是一种非常前卫的设计,它假定高级功能由硬件来实现。但是,如果硬件不支持某种功能,将发生什么事情呢?这就是双模式(HAL 和 HEL)设计的基础。
如果您请求 DirectX 做某项工作,并且由 HAL(Hardware Abstraction Layer)直接完成,硬件将完成该工作;否则,则通过 HEL(Hardware Emulation Layer),调用软件仿真完成该工作。
COM 对象可以被改变而不需要重新编译原来的程序,这一特点是非常有用的。
COM 规定规定您创建的所有接口都必须从一个名为 IUnknown 的特殊基类接口派生得到。
介绍这些内容(略)旨在说明一个原则,无论何时使用 DirectX 接口,务必使用最新版本的接口。
我的疑问:DirectX 跟 COM 有什么关系?