弾丸リリースと発射アニメーションを結び付ける方法


15

弾丸を発射するときに発生させたいアニメーションがあるとしましょう。アニメーションの最後に弾丸をどのように表示しますか。私が理解できる唯一のことは、アニメーションの時間の長さを知り、その時間が経過するまで弾丸の位置の設定とアクティブな設定を遅らせることです。これが最善のアプローチかどうか疑問に思っていましたが、他の誰もこれをどのように扱っていますか?

編集:私は質問を適切に表現するのに問題があると思う。

私の質問


ありがとう!皆さんからのたくさんの良いアイデア、私はコールバックを使うアイデアが好きです。私はそれを試して実装すると思いますが、実際には時間追跡に依存したくありませんでした。
tp0w3rn

回答:


8

基本的に、あなたは正しい軌道に乗っています-この種のことをするためにアニメーションがどれくらい続くかを知る必要があります。アニメーションは単なるフレームのコレクションではありません。必要な情報は他にもあります。たとえば、フレームの数、アニメーションのループ、再生の速さ(1秒あたり10アニメーションフレーム、25、60など)。すべてのアニメーションは、いくつかの一般的なアニメーションコードで確認および再生できるいくつかのデータの観点から定義できます。アニメーション部分を独自のコードでカプセル化する必要があります。これらのコードでは、これらのアニメーション定義と個々の画像フレームの表示方法以外は何も認識していません。つまり、ロード、再生の開始、再生の停止、および画面上の特定の場所でのレンダリングを指示できるアニメーションオブジェクトを用意します。

柔軟なアプローチは、一種のアニメーション定義を使用してこの種の情報をカプセル化することです。したがって、「アニメーションXはこれらすべてのフレームであり、単にフレームを再生するだけ」と言うのではなく、もう少し複雑なものになります。

たとえば、ある種のモックアップされたデータ形式

アニメーション=
{
  {name = "walk"、files = "walk * .png"、frameCount = "12"、loop = "true"}、
  {name = "fire" files = "fire * .png" frameCount = "6"、
       イベント= {
           {name = "bulletLeavesGun"、frame = "4"、param1 = "43"、param2 = "30"}
       }
  }
}

あなたのコードは次のようなものを言っています:

currentAnimation = animations.Get("fire");
currentAnimation.Play();

イベントを検出する方法は、コールバックするアニメーションコード(つまり、アニメーションが特定のフレームで再生されたために新しいイベントを検出したとき、ゲームコードを呼び出して新しいイベントについて通知する)、またはそのようなアニメーション:

List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
    if (event.name == "bulletLeavesGun")
    {
        Vector2 bulletPosition = new Vector2(event.param1, event.param2);
        Vector2 actualBulletPosition = new Vector2(
                 character.x + bulletPosition.x, 
                 character.y + bulletPosition.y);
        CreateBulletAt(actualBulletPosition);
    }
}

注意点:

  • アニメーションコードは、ゲームコードとは別に存在する必要があります。ゲームプレイのコードをアニメーション再生の要点に強く結び付けたくはありません。
  • アニメーションコードは、アニメーション定義に基づいてループするかどうかを知っています
  • アニメーションコードは、アニメーションがいつ終了するかを知っており、「ほら、「火」と呼ばれるアニメーションがちょうど終わったので、今何をしたいのか」と言うために他のコードにコールバックできます。
  • アニメーションコードは、名前とそれに関連付けられた任意のデータ(param1およびparam2)があること以外、イベントについて何も知りません。
  • アニメーションコードは、現在どのフレームにあるかを認識しており、新しいフレームに変わると、「ああ、今フレーム4にいます」と言うことができます。つまり、「火事」と呼ばれるこのイベントが発生しました。私の最近のイベントのリストは、それについて尋ねる誰にも伝えることができます」。

アニメーション内で弾丸を発射する必要はないが、一度終了すると、イベントの概念がなくても、はるかに単純なシステムで逃げることができます。ただし、アニメーションを単独で再生し、その長さを把握し、アニメーションの完了時にゲームコードを呼び出すことができるシステムが必要になります。


私はロジックを意識したアニメーションを維持することに同意しません(フレーム4では、このイベントは「ファイア」と呼ばれるイベントがちょうど発生したことを意味します)。アニメーションは目が見えなくて愚かでなければなりません。サーバーサイドのロジックを実行する必要があり、ゲームからアニメーションとUIを引き裂くのはもうやりたくないことです。非常に短く、セグメント化されたアニメーションを使用することをお勧めします。ロジックと並行して再生し、ロジックがロジックで定義された速度でアニメーションシーケンスをトリガーできるようにします。アニメーションのステータスをロジックでテストしないでください。
コヨーテ

アニメーションを断片に分割することは、かなり不要なようです。私はアニメーションのステータスをポーリングしないことに同意しますが、それでも彼の最初の推奨事項は残されています。アニメーションコードをゲームの他の部分から切り離すために別のイベントシステムを意味したのかどうかはわかりません(観察者パターンですか?)。あなたが言った「ロジック」のどちらもアニメーションコードについて知っているべきではなく、逆もまた同様です。
11

@Coyoteそこには、2つの異なるものが混在していると思います。はい、サーバー側のロジックは常にビジュアルから独立している必要があります(弾丸が発射されるタイミングを把握するためだけにアニメーションシステムを実行する必要はありません)が、それはクライアントでアニメーションシステムを構築するのに役立ちません。クライアントでは、ビジュアルがひどくサーバーに従属することは絶対に望まないでしょう。なぜなら、それはひどく見えるからです-ゲームとサーバーの間にラグスパイクがあったため、弾丸が奇数回出現し、キャラクターと同期しなくなります。両方を持てない理由はありません(続き...)
MrCranky

@Coyote(続き...)、ゲームプレイはビジュアルから切り離されたサーバーによって駆動できます。そのため、サーバー上で時間Xに弾丸が発射され、クライアントは弾丸のゲームプレイシミュレーションの背後にある数フレーム遅れて発射する弾丸の発射アニメーションをすぐに開始することにより、そのアクションをミラーリングします。視覚的な忠実性とゲームプレイシミュレーションの間で、あらゆる種類の妥協を行う必要があります。そのため、「アニメーションは盲目で愚かでなければならない」と言うのは単純です。イベントをアニメーションフレームに結び付ける必要がある場合があります。これは、他の方法ではイベントを適切に表示または音声化できないためです。
MrCranky

@Coyote実際に私はそれについて考えます、弾丸発射はこのための恐ろしい例です、主に以下のthedaianからの答えのために。発射はすぐに行われます。より良い例は、キャラクターが着陸したときにダストVFXが発火することです。サーバーとクライアントは、キャラクターがジャンプを開始するタイミングについて同期しますが、視覚的な表示はクライアントに任されます。そして、アニメーションが足が地面に当たる右フレームに達すると、VFXイベントが発生します。同様に、特定のアニメーションフレームで別のアニメーションに分岐するかどうかを決定する必要がある場合は、イベントが必要です。
MrCranky

3

何らかの方法で、アニメーションが完了するまで待機し、その時点で弾丸を作成する必要があります。

アニメーションレートが固定されていることが確実な場合は、タイマーを設定するだけで機能します。軽微なバリエーションとして、弾丸の内部にコードがあり、それが表示されて移動する前に目に見えないようにしばらく待つことができます。

開発プラットフォームによっては、アニメーションが目的のポイントに到達した正確な瞬間に応答できるようにする、何らかのアニメーション更新関数またはコールバックがある場合があります。これは、たとえば、Flixelを使用して行う方法です。


1
FlixelのaddAnimationCallbackメソッドは、発砲エンティティで使用できます。コールバック関数では、発射アニメーションの現在のフレームが弾丸エンティティを作成するフレームであるかどうかを確認できます。その場合は、画面に箇条書きを追加できます。
スノーブラインド

2

率直な答え:プレイヤーが「発射」ボタンを押したときに再生したいアニメーションがあり、再生後に弾丸が出てくると仮定します。理想的には、アニメーション時間のハードコーディングを避け、アニメーションの完了時に弾丸を発射する必要があります(プラットフォームに応じてコールバック関数などを使用します)。過度に複雑ではない、これを行う他の方法は考えられません。

別のゲームデザインの答え:そうする理由が本当にない限り、「発射」ボタンを押して弾丸が表示されるのを遅らせないようにします。アニメーションが本当に短く(1つまたは2つのフレーム、最大、基本的に銃口フラッシュ)でない限り、発射ボタンの反応が遅く感じられ、典型的なプレーヤーにとっては迷惑になります。弾丸が出る前にアニメーションを使用することにした場合でも(ターンベースのRPGと戦術ゲームはこれを行うのに受け入れられる理由です)、どこかに「アニメーションをオフにする」オプションを含めて、プレイヤーが望むならより速く動くゲーム。


うん、火をゆっくり反応させないでください。これは、ジャンプに関する一般的な問題と同じです。アニメーターは大きなワインドアップを行いますが、プレイヤーはボタンをタップするとすぐに空中にいることを期待します。
11

2

MrCrankyが言うように。アニメーションとロジックを分離してください。

しかし、最も重要なことは、ロジックがマスター部分のままである必要があります。

  • 発射ボタンが押されたら、キャラクターの状態(ロジック)で描画「アクション」をトリガーする必要があります。
  • このアクションは、すべてのパラメーター(存続時間など)で描画アニメーションをトリガーする必要があります。
  • 描画アクションが終了すると、発射アクションをトリガーできます(武器に応じて1回以上発射できます)
  • このアクションは、弾丸を生成し、火災アニメーションをトリガーできます。

ロジックからUIを制御することが、後でロジックを保持、再利用、共有できるようにする唯一の方法であることに注意してください(新しいレンダラー、新しいゲーム、レンダラーのないサーバーバージョン...)


1

まず、イベントシステム(観測者パターン?)を使用して、コードの一部を分離します。これはアニメーションのためだけではありませんが、確かにそこで適用されます。次に、アニメーションコードは単純にdispatchEvent(event)と言うことができ、コードの他の部分はそのイベントをリッスンします。コードのいずれの部分も互いを知る必要はありません。

ここで、アニメーションコードには実際にイベントディスパッチャーへの参照が必要であり(依存性注入で簡単に実行できます)、実際にアニメーションを定義するXMLまたはJSONが必要です。何かのようなもの:

{
  animation: {
    name: shoot,
    length: 12,
    spritesheet: shoot.png
    event: {
      frame: 4,
      name: bulletLeavesGun,
    },
  },
}

アニメーションを読み込むときにデータを読み取り、再生中にそのフレーム上にあるときにアニメーションコードにイベントをディスパッチさせます。

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