实现游戏速度函数以可靠地加速或暂停游戏的最佳方法是什么?
在深入探讨这个问题之前,我希望找到理想的方法,因为它是一个非常不可或缺的一部分,或者说是其他游戏元素的实现方式。
我会说使用一个输入帧侦听器,它将有一个内部循环来多次调用主更新函数。如果您想放慢游戏节奏,也可以使用stage.frameRate
财产进行游戏。或者,您可以创建一个"时间增量"属性,该属性将传递到主更新函数中,这样所有内容都将像不是整个帧一样,但只有一部分已经过去了,从而产生实时全局慢动作效果。
它的典型组织如下:
public var cyclesPerFrame:int;
addEventListener(Event.ENTER_FRAME,mainUpdate);
function mainUpdate(e:Event):void {
for (var i:int=cyclesPerFrame;i>0;i--) internalUpdate();
// it's the function that handles all your game ^
// if you need to update visuals regardless of pause, use this:
// updateVisuals();
}
这将使每帧进行多次内部更新。此外,这将允许您将cyclesPerFrame
设置为零,从而进行有效的暂停。
通过测量帧之间经过的时间并以此为基础进行速度计算,您将获得最佳结果。
有一个内部速度变量,您可以根据需要进行更改,然后通过计算经过的"滴答声"(游戏速度除以自上一帧以来经过的时间)来更新每一帧的游戏状态。这为您提供了流畅的游戏速度控制,并保持稳定的帧速率(这对于流畅的印象至关重要)。
不过要小心游戏暂停。如果将游戏速度设置为 0,则不会发生时钟周期,但所有补间、计时器和类似对象将继续运行,因此您必须单独管理它们。
这是一个示例,无论帧速率如何,都将以相同的速率移动圆。它使用显示列表,但相同的技术适用于椋鸟:
包
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.getTimer;
public class Main extends Sprite
{
private var lastFrame:int = 0;
private var thisFrame:int;
private var pixelsPerSecond:Number = 200;
private var circle:Shape
private var percentToMove:Number;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
circle = new Shape();
circle.graphics.beginFill(0xFF0000);
circle.graphics.drawCircle(0, 0, 25);
circle.x = 50;
addChild(circle);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
// Get the miliseconds since the last frame
thisFrame = getTimer();
percentToMove = (thisFrame - lastFrame) / 1000;
// Save the value for next frame.
lastFrame = thisFrame;
// Update your system based on time, not frames.
circle.x += pixelsPerSecond * percentToMove;
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}
}
}
这有助于确保您的屏幕更新是适当的。有些事件需要更频繁地发生,而不是与刷新率挂钩(AI、物理步骤)。您可以使用计时器处理这些情况,也可以根据 EnterFrame 中的 deltaTime 迭代适当数量的步骤。