弾丸を発射するときに発生させたいアニメーションがあるとしましょう。アニメーションの最後に弾丸をどのように表示しますか。私が理解できる唯一のことは、アニメーションの時間の長さを知り、その時間が経過するまで弾丸の位置の設定とアクティブな設定を遅らせることです。これが最善のアプローチかどうか疑問に思っていましたが、他の誰もこれをどのように扱っていますか?
編集:私は質問を適切に表現するのに問題があると思う。
弾丸を発射するときに発生させたいアニメーションがあるとしましょう。アニメーションの最後に弾丸をどのように表示しますか。私が理解できる唯一のことは、アニメーションの時間の長さを知り、その時間が経過するまで弾丸の位置の設定とアクティブな設定を遅らせることです。これが最善のアプローチかどうか疑問に思っていましたが、他の誰もこれをどのように扱っていますか?
編集:私は質問を適切に表現するのに問題があると思う。
回答:
基本的に、あなたは正しい軌道に乗っています-この種のことをするためにアニメーションがどれくらい続くかを知る必要があります。アニメーションは単なるフレームのコレクションではありません。必要な情報は他にもあります。たとえば、フレームの数、アニメーションのループ、再生の速さ(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);
}
}
注意点:
アニメーション内で弾丸を発射する必要はないが、一度終了すると、イベントの概念がなくても、はるかに単純なシステムで逃げることができます。ただし、アニメーションを単独で再生し、その長さを把握し、アニメーションの完了時にゲームコードを呼び出すことができるシステムが必要になります。
何らかの方法で、アニメーションが完了するまで待機し、その時点で弾丸を作成する必要があります。
アニメーションレートが固定されていることが確実な場合は、タイマーを設定するだけで機能します。軽微なバリエーションとして、弾丸の内部にコードがあり、それが表示されて移動する前に目に見えないようにしばらく待つことができます。
開発プラットフォームによっては、アニメーションが目的のポイントに到達した正確な瞬間に応答できるようにする、何らかのアニメーション更新関数またはコールバックがある場合があります。これは、たとえば、Flixelを使用して行う方法です。
addAnimationCallback
メソッドは、発砲エンティティで使用できます。コールバック関数では、発射アニメーションの現在のフレームが弾丸エンティティを作成するフレームであるかどうかを確認できます。その場合は、画面に箇条書きを追加できます。
率直な答え:プレイヤーが「発射」ボタンを押したときに再生したいアニメーションがあり、再生後に弾丸が出てくると仮定します。理想的には、アニメーション時間のハードコーディングを避け、アニメーションの完了時に弾丸を発射する必要があります(プラットフォームに応じてコールバック関数などを使用します)。過度に複雑ではない、これを行う他の方法は考えられません。
別のゲームデザインの答え:そうする理由が本当にない限り、「発射」ボタンを押して弾丸が表示されるのを遅らせないようにします。アニメーションが本当に短く(1つまたは2つのフレーム、最大、基本的に銃口フラッシュ)でない限り、発射ボタンの反応が遅く感じられ、典型的なプレーヤーにとっては迷惑になります。弾丸が出る前にアニメーションを使用することにした場合でも(ターンベースのRPGと戦術ゲームはこれを行うのに受け入れられる理由です)、どこかに「アニメーションをオフにする」オプションを含めて、プレイヤーが望むならより速く動くゲーム。
MrCrankyが言うように。アニメーションとロジックを分離してください。
しかし、最も重要なことは、ロジックがマスター部分のままである必要があります。
ロジックからUIを制御することが、後でロジックを保持、再利用、共有できるようにする唯一の方法であることに注意してください(新しいレンダラー、新しいゲーム、レンダラーのないサーバーバージョン...)
まず、イベントシステム(観測者パターン?)を使用して、コードの一部を分離します。これはアニメーションのためだけではありませんが、確かにそこで適用されます。次に、アニメーションコードは単純にdispatchEvent(event)と言うことができ、コードの他の部分はそのイベントをリッスンします。コードのいずれの部分も互いを知る必要はありません。
ここで、アニメーションコードには実際にイベントディスパッチャーへの参照が必要であり(依存性注入で簡単に実行できます)、実際にアニメーションを定義するXMLまたはJSONが必要です。何かのようなもの:
{
animation: {
name: shoot,
length: 12,
spritesheet: shoot.png
event: {
frame: 4,
name: bulletLeavesGun,
},
},
}
アニメーションを読み込むときにデータを読み取り、再生中にそのフレーム上にあるときにアニメーションコードにイベントをディスパッチさせます。