void System::Run()
{
Start(); /// 初始化定时器
while (mRunning) // 帧循环
{
Step(); // 一步tick
}
LOG_DEBUG("System: Exiting...");
exitCallback(); // 退出,清理资源
LOG_DEBUG("System: Done Exiting.");
}
void System::Step()
{
static bool first = true;
if (first)
{
InitVars(); // 初始化
first = false;
}
SystemStep();
}
void SystemImpl::SystemStep()
{
const Timer_t lastClockTime = mTickClockTime;
mTickClockTime = mClock.Tick();
const double realDT = mClock.DeltaSec(lastClockTime, mTickClockTime);
// update real time variable(s)
mRealClockTime += Timer_t(realDT * 1000000);
if (mPaused)
{
mTotalFrameTime = 0.0; // reset frame timer for stats
mWasPaused = true;
EventTraversal(0.0, realDT);
PostEventTraversal(0.0, realDT);
Pause(realDT);
CameraSynch(0.0, realDT);
FrameSynch(0.0, realDT);
Frame(0.0, realDT);
}
else
{
if (!mUseFixedTimeStep)
{
mTotalFrameTime = 0.0; // reset frame timer for stats
mWasPaused = false;
// update simulation time variable(s)
const double simDT = realDT * mTimeScale;
mSimulationTime += simDT;
mSimTimeSinceStartup += simDT;
mSimulationClockTime += Timer_t(simDT * 1000000);
EventTraversal(simDT, realDT); // 先处理事件
PostEventTraversal(simDT, realDT);
PreFrame(simDT, realDT); // 主要是物理模拟等
CameraSynch(simDT, realDT); // 摄像机
FrameSynch(simDT, realDT);
Frame(simDT, realDT); // 画一帧
PostFrame(simDT, realDT);
}
else
{
SystemStepFixed(realDT);
}
}
FinishFrameStats();
}
1、游戏不仅有游戏中的状态,还有很多其他的状态,比如登陆服务器、设置操作界面、查看装备属性等,可以利用state来封装一种状态,state之间的切换构成了最上层的层次结构,state具体的切换细节可以用有限状态机来描述。
2、具体一个state中的基本逻辑
总结:一帧里面的基本操作包括:
1、事件处理,即从上一帧到这一帧之间缓存的事件需要一一进行处理。这些事件包括本地的键盘鼠标操作,server传过来的message等。
这些事件的处理逻辑主要包括:
1》角色移动、转向等(内部是更改mesh的matrix4等属性、以及摄像机的操作等)
2》跳跃、走动 ----切换动画数据
3》切换人物 -----改变摄像机的target
4》拉近视角、拉远视角 --------摄像机操作
5》自动寻路 --------寻找关键点、播放走路动画
6》攻击、发技能 --------播放特定粒子效果、动画等
7》触发某个界面元素 --------进行相应逻辑处理、向server发相应请求等
8》拾取物品 --------2d ----3d ----3d object(即顺着摄像机方向创建射线、之后找出相交的object,向server发拾取的请求)
2、物理模拟
1》碰撞检测(求交点等),可以实现人物贴着地面行走、摄像机不会掉到地面以下、人物不会跑出地图边界,人物在坡上时不会悬空等效果
2》反向动力学模拟, 可以实现ragdoll 效果,
3》流体力学等复杂的物理模拟, 基本上牛顿经典力学所涉及的速度、加速度、质量,运动学等都可以做到(如人物走时会受摩擦力影响、人物跳下时会有重力加速度效果),牛X的游戏可以模拟出流体力学(这样就会体现出空气阻力、游泳时的浮力、阻力,水流动时的表面张力等)等更逼真的效果
3、preframe
1》计算骨骼动画的当前transform矩阵(之前先是在物理引擎中计算)、顶点动画的当前数据,摄像机移动的当前位置等动画相关数据
2》计算粒子系统当前的状态
3》计算音效、背景音乐等当前的数据
4、update场景
1》计算摄像机新的变换矩阵
2》根据摄像机matrix4更新modelView matrix、 projection matrix等(之所以使用matrix4x4是因为显卡支持4阶矩阵并行计算,注意不是并发是真正的并行,这是GPU的特点)
3》根据新的视锥体进行场景剔除(cull),一般室外场景是八叉树裁剪、室内场景是二叉树裁剪
4》更新每个node的orientation,position、scale等属性(主要是要将父节点的数据传递给子节点)
5、渲染场景
1》依次渲染renderQueue中的mesh,(这里面可以根据shader等来分组进行渲染、进而提高效率,GPU的特点是并行计算快,但是切换状态时很费时间)
1.1》为GPU绑定顶点数据、
1.2》设置vertixshader和pixelshader的参数
1.3》执行shader程序(这里面可以作一些特效)
2》post effect特效
6、播放一帧音效、音乐
六、静态结构
client端的代码基本上可以包括以下组件:
GUI(游戏内的悬浮button等)、渲染、场景管理、动画、粒子、物理模拟、AI、网络、窗口界面(qt等)、音效、脚本、IO事件、game框架、摄像机管理、player封装等