0

我正在创建一个收集游戏,并且我想创建一个时间慢/加速通电。关于如何在 Flash/AS3 中做到这一点的任何想法?

我想到的一种方法是简单地改变帧速率。我可以减慢帧速率。但是当我尝试将帧速率提高到 60 以上时,Flash 将其限制为 60。

预先感谢您的帮助。

4

2 回答 2

2

我喜欢做基于时间的运动而不是基于帧的运动,以获得更好的一致性。一般概念是检查帧之间经过的时间量,并以此为基础移动,而不是可以交替的帧(例如,您可以有 60FPS 一段时间,然后它会减慢到 30FPS)。例如,您可以根据移动所经过的时间进行简单的计算,player.x += player.speed * timeDiff但是如果帧之间经过的时间恰好非常大,则可能会导致奇怪的情况(例如,由于您正在移动,玩家最终可能会错过很多碰撞他在一个大动作中)。相反,我喜欢使用游戏循环根据帧之间经过的时间量移动玩家 X 次,确保正确检查碰撞和任何其他游戏循环事件。

这也有一个优点,就是容易调整速度。

这是基本概念:

private var speedMultiplier:int = 100;//100 normal speed, 0 paused
private var currRealTime:int = getTimer();
private var currGameTime:int = currRealTime;
private var globalLastTime:int = currRealTime;      
private var totalTimeDiffRemainder:int = 0;
private var loopTime:int = 20;//every 20 ms run our actions

public function getGameTimer():int
{           
    return currGameTime;
}       

private function updateGameTime():void
{
    var realTime:int = getTimer();
    currGameTime = currGameTime + speedMultiplier/100*(realTime - currRealTime);
    currRealTime = realTime;
}

private function runEvents(event:Event):void
{//ENTER_FRAME event
    var totalTimeDiff:int = getGameTimer() - globalLastTime + totalTimeDiffRemainder;
    globalLastTime = getGameTimer();
    while (totalTimeDiff > loopTime)
    {//every 20 ms run all our actions          
        totalTimeDiff -= loopTime;
        //run all your game loop events here, such as collision checks
    }
    totalTimeDiffRemainder = totalTimeDiff;
    updateGameTime();
}

因此,每次 ENTER_FRAME 事件触发时,我们将检查自上次 ENTER_FRAME 事件以来经过的时间,然后每 20 毫秒运行一次我们的操作,并将剩余时间传递给下一个 ENTER_FRAME 事件。例如,如果自上次 ENTER_FRAME 以来已经 47 毫秒,我们将运行我们的操作两次并将剩余的 7 毫秒传递给下一个 ENTER_FRAME 事件。

为了暂停、减慢或加速游戏,您所要做的就是修改 speedMultiplier。将 speedMultiplier 更改为 0 会暂停游戏,50 是半速,100 是正常速度,200 是双速,等等。

于 2012-07-01T18:00:19.113 回答
1

我相信执行此操作的一般方法是使用类似 MVC 的设置,其中您的模型保存游戏元素的所有数据(角色位置/方向、敌人、动态地图元素),然后控制器正在修改模型。通过控制器以这种方式修改模型,您可以将乘数添加到模型中,并在控制器更新模型以获取“物理”或其他修改游戏中的动态元素时使用乘数。

大致:

模型

public var speedMultiplier:Number=1;
public var playerXSpeed:Number;
public var playerYSpeed:Number;

控制器(我假设您创建了一个控制器类并将视图传递给构造函数,并正在监听来自控制器中视图的事件)。

private function enterFrame_handler(event:Event):void
{
    var playerSprite:Sprite = mainView.playerSprite;
    playerSprite.x += playerXSpeed*speedMultiplier; //only problem I can see here is your player skipping past certain elements, to avoid this you could use a loop to make each motion and do checks but it's more CPU intensive
    //var enemySprites:Vector<EnemySprite>;
    //other game physics here, reduce speed due to drag, fix any invalid values etc.
}

编辑

实际上,在考虑这一点时,虽然我通常喜欢自己使用 MVC 设置,因为它允许一个单独的精灵来完成所有的绘图;您也可以使用此处显示的 speedMultiplier 的相同概念,而不必更改任何软件模式。如果您最终需要使用循环来执行此操作,因为您需要它检查它在对象移动时会碰到的每个点,您可能需要将默认 speedMultiplier 设置为 10 这样您可以将其设置为 1通过所有相同的检查来获得 1/10 的速度,因为它会在 10 是正常速度时获得(这里再次唯一的问题是它必须为每次更新执行 10 次任何计算,在这种情况下,您可能想要使用计时器而不是帧速率来控制整体计算速度)。

于 2012-07-01T14:12:13.500 回答