4

注: 私は英語のネイティブ スピーカーではありません。文法の間違いはご容赦ください。

左側にシューターがいて、右側から敵が来るシンプルなゲームを開発しました..とてもシンプルです。

プロジェクトはほぼ完成し、完璧に動作しますが、ゲーム ループの管理に疑問を感じています。

スケジューラに間隔を与えて右から出現する敵をスケジュールしましたが、問題はありませんが、単純な ccMoveTo アクションで右から左への敵の移動を管理しました。繰り返しますが、完全に機能します。問題は、この操作をフレームごとに 1 回実行されるスケジュールされたメソッドに委譲する「すべてのフレームでスプライトをレンダリングする」について何かを読んだことです..

より良い: アクションを使用してスプライトを移動するのではなく、1/60 周波数 (fps 周波数) で呼び出されるスケジュールされたメソッドで動きをシミュレートするフレームごとにそれらを再レンダリングすることについて読んだところ、この実装が防止できることを読みました異なるハードウェアシステムでの安定性の違い..

私が尋ねるのは:

  • それは進むべき正しい方法ですか?
  • それは Cocos2D で廃止された古い「デザイン パターン」ですか? (これは、ccMoveTo アクションの使用が完全に完璧であることを意味します)
  • または、両方の実装が同じレベルで正しいですか?

編集:

――アニメーションにも同じ手法を使うべきですか?

4

1 に答える 1

5

まず第一に、それが「完璧に動作」し、ゲームがほぼ完成している場合は、ゲームを変更しないでください。今変更すると、ゲームプレイに微妙な変化が生じるリスクがあり、ゲームが終了するまでに時間がかかり、最終的にプレイヤーは違いに気付かない可能性があります。次回は別のアプローチを試すことができますが、現在のゲームではすべてがうまくいっている限り、そのままにしておいてください。

ゲームプレイ オブジェクトの (複雑な) 移動に CCMoveTo/CCMoveBy を使用しないでください。CCMove アクションは、移動が非常に単純な場合、または A から B へのワンショットであれば問題ありません。しかし、その場合でも、位置を更新する更新ループを実装するのは簡単です。

CCMove アクションの問題は、方向や速度を変更したい場合の動作です。その場合、新しい移動アクションを作成する必要があります。これを頻繁に行うと、必要以上に多くの割り当て/割り当て解除サイクルをゲームに追加することになります。第 2 に、CCMove アクションは、効果が現れるまでに 1 フレームの非アクティブ状態をとります。つまり、フレームごとに新しい CCMove アクションを作成すると、そのゲーム オブジェクトは効果的に動かなくなり、まったく動かなくなります。あまり頻繁に変更しない場合でも、オブジェクトが速度または方向を変更するたびに短い一時停止に気付くでしょう。どちらも望ましくありません。

代替案は、見た目ほど複雑ではありません。はい、次のように、移動するゲーム オブジェクトで更新をスケジュールする必要があります。

[self scheduleUpdate];

次に、ノードの位置を更新する update メソッドを実装します。

-(void) update:(ccTime)delta
{
    self.position = CGPointMake(self.position.x + 1, self.position.y);
}

より柔軟な動きは、通常、動きの速度と方向を決定する速度ベクトル (CGPoint、通常はインスタンス変数) を使用します。

-(void) update:(ccTime)delta
{
    self.position = ccpAdd(self.position, self.velocity);
}

これで、速度を位置に追加する方法と、速度自体を更新する方法で、さらにダンディになることができます。たとえば、速度を制限して、オブジェクトが毎秒 x ピクセルより速く移動しないようにすることができます。フレームごとにvelocity.yを減らすことで、シミュレートされた重力を追加することもできます。そしてもっとたくさん。基本原理は変わりません。

唯一の真に異なる代替手段は、更新間のデルタ時間を考慮に入れることです。これにより、フレームレートに関係なく、ノードが時間の経過とともに同じ距離を移動することが保証されます。つまり、フレームレートが 60 から 20 fps に低下した場合でも、ノードは同じ距離を移動しますが、失われた時間を補うために、フレームごとにさらに数ピクセル移動します。デルタ時間を考慮しないと、ノードはフレームレートが低下するにつれて単純に遅くなります。

デルタ時間の積分は単純な乗算です:

-(void) update:(ccTime)delta
{
    self.position = ccpAdd(self.position, ccpMult(self.velocity, delta));
}

ただし、ほとんどのゲームではタイム デルタを使用しないでください。電子メールや SMS を受信した場合など、デバイスが 10 分の 1 秒以上ビジー状態になると、ゲーム世界のシミュレーションが大幅にジャンプするなど、予測不可能な結果が生じる可能性があります。

ほとんどのゲームは、「失われた」時間を取り戻そうとするよりもむしろスローダウンする必要があります。問題は、その間、プレイヤーは (逆に) より速く反応することができないため、ゲーム ワールド シミュレーションを通常よりも速く進めることはプレイヤーにとって不公平であり、手足や生命の早期喪失につながる可能性があることです。

于 2012-05-26T10:56:23.830 に答える