ゲームでタイムストップまたはバレットタイムをコーディングする方法


11

XNA 4.0でシングルプレイヤーRPGプラットフォーマーを開発しています。時間を「停止」または減速させ、プレイヤーキャラクターのみを元の速度で移動させる能力を追加したいと思います(Baldur's GateシリーズのTime Stopスペルに似ています)。正確な実装ではなく、いくつかの一般的なアイデアとデザインパターンを探しています。

編集: 素晴らしい入力をありがとう。私は次の解決策を考え出しました

    public void Update(GameTime gameTime)
        {

            GameTime newGameTime = new GameTime(gameTime.TotalGameTime,
 new TimeSpan(gameTime.ElapsedGameTime.Ticks / DESIRED_TIME_MODIFIER));
            gameTime = newGameTime;

またはこれらの線に沿って何か。このようにして、プレーヤーコンポーネントに別の時間を設定し、残りの時間に別の時間を設定できます。このようなワーピング時間が中心的な要素となるゲームで機能するのに十分なほど普遍的ではありませんが、このケースで機能することを願っています。メインのUpdateループが少し不快であるという事実はちょっと嫌いですが、それは確かにそれを実装する最も簡単な方法です。それは本質的にテッセローデが提案したのと同じだと思いますので、私は彼に緑のダニを与えます:)

回答:


8

これは悪い解決策かもしれませんが、必ずしもそうではありません。デルタ時間を使用している場合は、それを変更して特定の速度を変更できます。

例えば:

player.update(dt)
dt = dt * .5 --half speed
enemy.update(dt)

もちろん、これは、何かを更新するのではなく、いつ敵を更新するのかがわかる場合にのみ機能します。すべてにスピード値を与えて、次のようなこともできます:

x = x + xspeed * dt * speed

最初の部分は完全に理にかなっていて、2番目の部分は明確ではありません
AturSams

2
変更可能な速度変数を移動する各オブジェクトを指定し、(たとえばxの)変換がある場合は、大きさを速度変数で乗算します。
tesselode 2012

今は理にかなっています。:)
AturSams 2012

2番目のアイデアは...オフに聞こえます。「速度」係数で動きをスケーリングするだけでも、物理駆動のオブジェクトでは機能しますが、AIは通常の速度で反応し、動きのみが遅くなったり、損なわれたりします。

AIが通常​​の速度で反応できるとはどういう意味ですか?速度変数を適用できないAIのコードは何ですか?
テッセローデ

3

デルタ時間(最後のフレームから経過したミリ秒)を使用しても、敵を遅くするのに十分ではない場合があります。攻撃率のようなものは、最後の攻撃時間に基づいて実装される場合があります。時間ベースの場合、動きを遅くしますが、攻撃率、スペルキャスト、およびその他の効果(ヘルスの再生、スペルエフェクトの持続時間)などを遅くします。

シングルプレーヤーゲームでゲーム要素の大規模なグループを遅くしたい場合は、各クリーチャーに2つ目の内部クロックを作成できます。クロックは、クリーチャーが表示される現在の時刻から始まります。スロースペルがキャストされると、フレームごとに、実際に経過した時間のx%だけクロックが増分されます。その後、すべてのモンスターの動作は、その内部時計によって決定されます。さまざまなモンスターが低速に対する耐性を持っている場合は、独自のクロックを使用できます。これは基本的に、多くのスペースや計算を必要としない整数です。

スローエフェクトが停止しても、クロックはまだ使用されており、実際に経過した時間の100%ずつ増加します。

これは、速攻呪文でも機能します。

@Sidar:私には2つの選択肢があります。

  1. クリーチャーごとの内部クロック。クリーチャーが再び攻撃する準備ができているかどうかを確認するには、各攻撃が最後に使用された時間と再充電時間を保存し、内部クロックがすでにその時間を経過しているかどうかを確認します。

  2. 攻撃ごとに1つのタイマー:攻撃を再充電するのにかかる時間を知っており、タイマーを設定して、毎ターン*(1-slowdown%)経過した時間を差し引くだけです。

私は個人的には、処理時間と複雑さを節約するために、複数の個別のタイマーとユーザーの1つの内部クロックを差し引くことを避けます。

それは本当に好み次第です(それはパフォーマンスにそれほど影響しません)。


内部クロックの必要はありません。それは単に、(何らかの形で)オブジェクトにリンクできる乗数に帰着します。これは、dt(デルタ時間)の積を増加または減少させます。グループまたは任意の手段でオブジェクトを管理できます。あなたのやり方は少し過剰かもしれません。しかし、もしそれがうまくいけば...それならうまくいきます。
Sidar 2012

@Sidarこれを回避する場合、攻撃のリチャージ、スペルの持続時間などを計るために、攻撃ごとにクロックが必要になるでしょう。少なくともこの方法では、1つのクロックを更新するだけで、プロパティをリセットするための「最後のアクティブ化」時間を保持するだけで済みます。
AturSams 2012

しかし彼の質問は、プレーヤー以外の環境を遅くすることに関するものです。私にとっては、dtに1未満の数を掛けるという最も単純な形のように聞こえます。
Sidar 2012

まあ、環境を遅くすることは、攻撃速度と他の能力(それはrpgであるため)を遅くすることを含み、再充電時間に依存するさまざまな暴徒能力が存在する可能性があります。ヒール、バフ、デバフ、スペルなど。アクティベーション時間は言うまでもありません。
AturSams 2012

2

テッセローデまたはビースト氏によって公開されたもののような単純なソリューションから始めることができます。しかし、複雑なもの、つまりスローダウンスペルが唱えられている間に弾丸の時間混ぜ始めると、行き詰まってしまいます。

クロック階層を実装することをお勧めします:

.
├── Main clock
│   └── UI clock
│   └── 3D clock
│       ├── GFX clock
│       └── Gameplay clock
│           └── Slowdown spell clock 01
│           └── Slowdown spell clock 02

ゲーム内のすべてのものは、クロックの1つからのデルタタイムを使用する必要があります。グラフィックスエフェクトはGFXクロックで実行され、AIとアニメーションはゲームプレイクロックで実行され、スローダウンスペルの影響を受けるクリーチャーは一時的なスローダウンスペルクロックで実行されます。階層のさまざまな部分に影響します。スローダウンスペルはカスタムクロックを作成して影響しますが、バレットタイムは3Dクロック階層全体に影響します。


ありがとう、これは重要な洞察です。ただし、私の特定のケースでは複数のスローダウン効果が同時に発生することは意味がないので、私は単純に考え続けるつもりだと思います。
David Miler、2012年

1

1つではなく2つの異なるクロックが必要です。1つはゲームプレイに関連する時間用で、もう1つは「真の」時間用です。

currentGameTime = 0;
gameSpeed = 1.0f;
[...]
currentApplicationTime = GetTime():
timeDelta = (currentApplicationTime - lastApplicationTime)*gameSpeed;
currentGameTime += timeDelta;
lastApplicationTime = currentApplicationTime;

次に、gameSpeedを変更して、速度を上げる(> 1)または時間を下げる(<1)ことができます。プレイヤーが異なる速度で移動するには、時間が遅くなっているかどうかを確認してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.