3D游戏让玩家在游戏中回归到真实的世界,通过操作空间中的三维对象,体会身临其境的感觉。既然是模拟真实世界,那么最重要的就是一套优秀的物理模拟系统,比如各种加速度、各种外力,以及遵循各种物理定理,比如动量定理、动量守恒、牛顿第一定律等。但是,完全精确的模拟这套物理系统复杂度比较高,除非是在某些对物理系统要求非常精确的游戏(比如极品飞车),否则在游戏中也未必能够表现出效果,因为游戏毕竟是游戏,有些因素可以忽略不计,只要是能够容忍的,就可以了。所以,在设计游戏物理系统的时候,先根据游戏的定位,考虑游戏中玩家控制的物体可以忽略哪些物理因素,然后确定一套物理变量,以及相应的计算函数。
在《空袭日本》的飞机物理系统设计中,我完全忽略了飞机发动机推力的变化,将其视为恒力,即飞机的加速度是恒定的,所以飞机始终是在做匀加速或者匀减速运动。其次,当飞机左右变化方向的时候会产生角速度,这里我也使用了恒定的角加速度。这样一来,飞机引擎的爆发力我们就无法感受到了,但是如果将恒定的加速度取一个比较合适的比较大的值后,在测试中,完全可以感受到飞机逼真动力效果,这在本游戏中已经足够了,因为我们不是在做《微软模拟飞行》。
为了增加飞机的真实感,在飞机提升、俯冲、侧拉的时候,机身都会发生相应的倾斜,让玩家感受到理所当然的延续效果,在计算这些倾斜角度的时候,我完全没有使用飞机的速度这些值,但是如果在物理考试中,这些数值肯定是有关系的。倾斜角度是根据反复测试后的经验,取一个最大值,然后定义一个倾斜加速度,用来产生相应的惯性,如果要表达各种不同的倾斜效果,可以为提升、俯冲、侧拉分别定义自己的倾斜角加速度。
以上是一些基本的物理因素,实际设计中,由于需要用键盘或者手柄控制,所以各种参数的变化都是在操作按键的触发函数中进行,在获得各项参数后,最后进行物理函数计算,将结果用到3D对象的变换矩阵中。
另外,还存在一些交叉影响的因素,比如在飞机做左旋转的时候,玩家再加上一些左侧翻,这样对角速度会有一些辅助加强。还有一些细节的数值矫正,用来逼近真实物理系统,我们可能只是枚举几个范围中有代表性的数值。

飞机引擎测试数值截图
TerminateThread作为终止一个线程的最后一招,微软不建议大家使用,同时也列出了一些使用后可能引发的问题,在API的介绍中有这么一段:
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
- If the target thread owns a critical section, the critical section will not be released.
- If the target thread is allocating memory from the heap, the heap lock will not be released.
- If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread’s process could be inconsistent.
- If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread.
很显然,除非你非常清楚你的线程在干什么,并且能够通过代码使线程在TerminateThread的时候既然保持优雅的结束,那么你可以大胆的使用TerminateThread。
使用TerminateThread可能发生的问题在API描述中已经很清楚了。我曾试图去TerminateThread一个拥有临界区的线程,结果导致程序无法正常工作,因为那个线程在被终止的时候正好处于临界区的lock状态,被终止掉后形成死锁。试想,一个拥有10个线程、3个临界区、3个事件触发器的程序中,很难保证开发者能清楚线程在任何时刻都在干什么,所以我建议能够养成好的习惯,尽量不使用TerminateThread这种杀伤力比较大的武器。相反,如果是对于一个线程内计算比较简单,线程同步较少的应用来说,就更没有必要使用TerminateThread了,所以无论如何,线程都应该选择自己退出,同时注意线程如果采用不自动销毁方式的话,应该delete线程指针或者关闭线程句柄。
但是,TerminateThread的存在难道就是多余的了吗?其实,只要你不在乎你的程序带来不可预料的后果,或者你不太想了解那个线程被TerminateThread的时候是什么心情,那么可以使用。
最近评论