収集ゲームを作成していますが、タイムスロー/スピードアップのパワーアップを作成したいと思います。Flash / AS3でそれを行う方法について何かアイデアはありますか?
私が考えた1つの方法は、単にフレームレートを変更することでした。フレームレートを遅くすることができます。しかし、フレームレートを60を超えて上げようとすると、Flashは60に制限します。
よろしくお願いします。
収集ゲームを作成していますが、タイムスロー/スピードアップのパワーアップを作成したいと思います。Flash / AS3でそれを行う方法について何かアイデアはありますか?
私が考えた1つの方法は、単にフレームレートを変更することでした。フレームレートを遅くすることができます。しかし、フレームレートを60を超えて上げようとすると、Flashは60に制限します。
よろしくお願いします。
一貫性を高めるために、フレームベースの移動ではなく、時間ベースの移動を行うのが好きです。一般的な概念は、フレーム間で経過した時間と、フレームが交互になる代わりにその上での基本的な動きをチェックすることです(たとえば、60FPSを少しの間持つことができ、その後30FPSに減速します)。たとえば、移動に経過した時間に基づいて簡単な計算を行うことができますplayer.x += player.speed * timeDiff
が、フレーム間の経過時間が非常に長い場合(たとえば、移動しているためにプレーヤーが多くの衝突を見逃してしまう可能性がある場合)、奇妙な状況になる可能性があります1つの大きな動きで彼)。代わりに、ゲームループを使用して、フレーム間で経過した時間に基づいてプレーヤーを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ミリ秒ごとに1回アクションを実行し、残りを次のENTER_FRAMEイベントに渡します。たとえば、最後のENTER_FRAMEから47ミリ秒経過している場合、アクションを2回実行し、残りの7ミリ秒を次のENTER_FRAMEイベントに渡します。
ゲームを一時停止、減速、または高速化するには、speedMultiplierを変更するだけです。speedMultiplierを0に変更すると、ゲームが一時停止します。50はハーフスピード、100は通常スピード、200はダブルスピードなどです。
これを行う一般的な方法は、モデルがゲーム要素(キャラクターの位置/向き、敵、動的マップ要素)のすべてのデータを保持し、コントローラーがモデルを変更するセットアップのような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に設定する必要があります。通常の速度である10で得られるのと同じチェックで1/10の速度を得るには(ここでも問題は、更新ごとに10回計算を行う必要があるためです。この場合、代わりにタイマーを使用することをお勧めします。全体的な計算速度を制御するためのフレームレート)。