XNA 中的 Game 类,是所有神奇事情发生的地方。几乎游戏中所有的事情都由它来操办。
它是项目中的王者,让我们深入窥探一番:
虚方法
Game 本身从众多其它地方继续了许多能力才能完成游戏中的事情。因而它必然会重写一些方法,
以更好地完成任务。我们已经看到了一些:
Initialize ,如你所见,这个方法在Game类自身创建后,调用一次。在这里你可
以执行一些初始化游戏的动作,比如加载游戏的其它组件。
Update ,这个方法,顾名思义,就是用来更新的。你可以在这里执行游戏状态的
更新。比如,处理用户的输入,精灵的状态等等。
Draw ,这个方法,顾名思义一下,当然也是画画的意思,就是将你的精灵往屏幕
上绘制了。
还可以自行重写 BeginDraw 和 EndDraw方法 同时确保调用 base.EndDraw
除了Draw前后的方法外,还可以重写 BeginRun 和 EndRun 。
方法
Game类的大多数方法都是虚方法,没有什么太多要讲的了。
Exit 方法,会闭关游戏。
ResetElapsedTime 方法,会重置游戏流逝的时间。
---少即得。
属性
说完方法,自然就轮到属性了。
InactiveSleepTime 属性,你可以通过它控制游戏失活状态下多久会休息,
而不是持续高速运行。默认值为20毫秒。
IsActive 属性,告诉你游戏的当前状态,这跟事件 Activated 和 Deactivated
相关联。
IsMouseVisible 属性,相信你应该猜到了。
GameTime (核心)
你也许没有注意到,游戏中的许多事情都依赖于时间的变幻。如果你创建了一个
赛车游戏,你的车以60码的速度狂奔,你得知道,特定时间之后,你的车相对
刚刚,它所处的位置。XNA游戏框架通过掌控时间来为你做许多事情。
游戏有两种运行方式:固定时间节拍 和 可变时间节拍 。
前者对应的属性是 IsFixedTimeStep
如果你的游戏在 固定时间节拍 下运行,那么TargetElapsedTime 就是每一
帧画面持续的时间。
项目默认的是 固定时间节拍,每秒60帧画面,即每一帧画面持续显示 1/60 秒。
可变时间节拍,指什么呢。它指的是每帧之间停留的时间不相等。
你的游戏会先调用一次 Update ,然后调用一次 Draw ,然后不断循环这一过程。
这个循环就依据的是时间。如果你注意到,Update方法的参数正是 GameTime 。
GameTime 对象拥有三个你可以使用的属性。
第一:ElapsedGameTime 意思是自上次调用Update方法以来,时间过了多久。
第二:TotalGameTime 意思是自游戏开始运行以来,时间过了多久。
第三:IsRunningSlowly 这个属性在 固定时间节拍模式下比较重要。
下面解释一下:
前面说了,固定节拍模式,就是隔相同的时间 1/60 秒,执行一次 Update 和
Draw。但是当画面上很多东西,或者,而且电脑比较慢 ,或者在Update执行
了非常耗时的操作,那么,当1/60秒时间到了之后,游戏再次来执行的时候,会
发现,上次的任务还没有完成。
那遇到这种情况怎么办呢,它就犹豫了,一犹豫就是 Slowly模式了。
虽然慢了,但游戏还在进行,它是怎么处理的呢?
第一种情况,自上次执行Update方法以来,时间已经过了 1/60秒,但Draw
还没有执行完,等到执行完了,时间已经自上次执行过了 三倍 1/60秒了,也就
是本身应该执行的,每1/60秒 一次的Update没有执行上。也就是说可能有些
精灵的状态(可碰撞等等)已经发生了改变,还没有顾得上去更新,于是游戏为了
追赶落下的时间造成的状态的过时,它首先会将其 IsRunningSlowly 属性设置为
true ,并告诉显卡,不要画那么认真了,随便画画就行了,时间来不及了,之后
它会连续执行三次Update方法,然后再次执行Draw方法。通过这样的方式来赶上
。
第二种情况,如果在Update里面执行了太长时间的计算等等的操作,在下一次
Update执行之前,时间已经过了固定的节拍,如1/60 秒,那么它首先也会将
IsRunningSlowly 设置为true, 催促 计算机不要算那么认真了,快点。如果等
了较长时间,还没有完成,它会估计一下,落下的时间能不能赶上,如果能,则
等等,如果不能,就将计时器归零,重新计算 1/60 秒。
你也可以自行,将经过的时间重置,当你知道,你将要执行一个耗时的操作时,如
加载游戏进度或其它的事情。这告诉游戏,这个操作会耗费一定的时间,不要试图
追赶,从这里开始更新就好了。 在操作的最后,放置 ResetElapsedTime方法。