5

私のアプリには足のあるキャラクターがいて、画面を上に移動するときに別のCCSpriteの上に立っているように見えるようにしたいと思います(アニメーション)。私が理解できない小さなポジショニングの問題があることを除いて、すべてが正常に機能しています!この問題についてもう少し説明します。キャラクターがCCSpriteの上にある場合、キャラクターが非常に速い間隔で約10ポイント上下に移動しているように見えます。

なぜこれが起こっているのか誰かが知っていますか?

ありがとう!

最終編集:このすべてを手伝ってくれてありがとうございます。まず、投稿が長くなりすぎたため、他のすべての編集を削除しました。何らかの理由で古い編集を参照する必要がある場合は、編集履歴を確認してください。

したがって、約1時間のテストの後、前述の1つの問題に絞り込みました。キャラクターとフロアピースが衝突しているかどうかをチェックするifステートメントは、ゲームループの各反復で呼び出されるべきではありません( UIで見る限り)。

私のcocosGameLoopログは、すべての衝突検出コードの前にありますが、ゲームループ内にあります。f

以下に示すように、NSLogのパターンにも気づきました。

2012-05-27 17:00:54.791 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.811 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.825 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.841 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.858 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.874 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.891 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.908 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.924 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.928 App[2769:707] collisiontwo
2012-05-27 17:00:54.929 App[2769:707] two
2012-05-27 17:00:54.941 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.944 App[2769:707] collisiontwo
2012-05-27 17:00:54.945 App[2769:707] two
2012-05-27 17:00:54.958 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.974 App[2769:707] cocosGameLoop
2012-05-27 17:00:54.991 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.008 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.025 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.043 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.058 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.076 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.078 App[2769:707] collisiontwo
2012-05-27 17:00:55.078 App[2769:707] two
2012-05-27 17:00:55.091 App[2769:707] cocosGameLoop
2012-05-27 17:00:55.094 App[2769:707] collisiontwo

キャラクターのY座標をNSLogしたときにも気付いたのは、いくつかのインタラクションの間(衝突しているはずなので、上記のNSLogのcocosGameLoop呼び出しの束と一致する場合でも)、同じポイントの周りにとどまっていることです。実際に(プログラムで)衝突し、前のY座標から約14ポイント上に移動します。したがって、上下に約14ポイントのジッターがあります。

つまり、衝突コードがすべての反復で呼び出され、約14ポイントのジッターが発生しないようにするには、どうすればよいでしょうか。アンカーポイントを変更すると、アニメーションの配置などが混乱するため、変更したくありません。とにかく、あなたは何をお勧めしますか?また、衝突検出にはBox2Dのみを使用しているため、すべてをCocos2Dコードで保持する必要があることにも注意してください。

最後に、重力が原因でアプリに丸め点エラーがあると思いましたが、重力を整数に変更するなどの値をいじっても、ちらつきは修正されなかったので、100%上記の問題です。

とにかく、これが問題の核心で、私には見えないものが見えると思います!どう考えているか教えてください :)

本当にありがとう!

4

1 に答える 1

3

Some other tag collision checking before最初に奇妙に見えるのは、コメントの直後のタグのチェックです。これはもっと理にかなっています:

else if ((spriteA.tag == 1 && spriteB.tag == 5) || (spriteB.tag == 1 && spriteA.tag == 5))
...
else if ((spriteA.tag == 6 && spriteB.tag == 1) || (spriteB.tag == 6 && spriteA.tag == 1))
...

つまり、これは、テストしている衝突接触が2つのボディをいずれかの順序で与える可能性があることを前提としています。たとえば、2つのオブジェクトが衝突する場合、たとえばキャラクターと地面の場合、接触リスナーは地面をボディAとして、足をボディBとして、または足を上記のステートメントは、順序に関係なく、同じ条件付きブロックを実行することを保証します。実行パスが2つのelse ifブロック間で振動しているため、間違ったブロックに入ったときに間違った位置を設定している可能性はありますか?

さて、これらの条件がすべて正しいと仮定すると(タグがどのボディを参照しているか、連絡先リスナーがどのように設定されているかなどがわからないため、それがわかりません)、振動は次の原因で発生する必要があります物理シミュレーション。Box2Dを使用してCocos2dでCCSpriteの位置を設定するとどうなりますか?スプライトの位置を設定すると、物理ボディの位置も変更されますか、それとも2つは別々ですか(スプライトは通常、物理ボディの位置にレンダリングされます)?Cocos2dを使ってからしばらく経ちますが、初期の頃から大きく変わっているので、最新バージョンを開いて見てみないとわかりません。CCSpriteの位置を変更すると、物理ボディの位置も変更される場合は、その場合、これは悪いことです。すべての動きは物理シミュレーションによって制御する必要があります(したがって、物理ボディを動かしたい場合は、位置を直接設定するのではなく、力またはインパルスを適用する必要があります)。物理学の外側で体の位置を変更すると、物理学シミュレーションの次のステップが実行されるときに、振動または不正確なインパルスが体に適用される可能性があります。物理シミュレーションを混乱させずにスプライトの位置を変更する場合は、位置を直接設定するすべての時間で、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除し、後で再度追加することを検討してください。物理学の下で動作させたい場合。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。位置を直接設定するのではなく、力または衝撃を加える必要があります)。物理学の外側で体の位置を変更すると、物理学シミュレーションの次のステップが実行されるときに、振動または不正確なインパルスが体に適用される可能性があります。物理シミュレーションを混乱させずにスプライトの位置を変更する場合は、位置を直接設定するすべての時間で、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除し、後で再度追加することを検討してください。物理学の下で動作させたい場合。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。位置を直接設定するのではなく、力または衝撃を加える必要があります)。物理学の外側で体の位置を変更すると、物理学シミュレーションの次のステップが実行されるときに、振動または不正確なインパルスが体に適用される可能性があります。物理シミュレーションを混乱させずにスプライトの位置を変更する場合は、位置を直接設定するすべての時間で、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除し、後で再度追加することを検討してください。物理学の下で動作させたい場合。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。物理学の外側で体の位置を変更すると、物理学シミュレーションの次のステップが実行されるときに、振動または不正確なインパルスが体に適用される可能性があります。物理シミュレーションを混乱させずにスプライトの位置を変更する場合は、位置を直接設定するすべての時間で、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除し、後で再度追加することを検討してください。物理学の下で動作させたい場合。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。物理学の外側で体の位置を変更すると、物理学シミュレーションの次のステップが実行されるときに、振動または不正確なインパルスが体に適用される可能性があります。物理シミュレーションを混乱させずにスプライトの位置を変更する場合は、位置を直接設定するすべての時間で、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除し、後で再度追加することを検討してください。物理学の下で動作させたい場合。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。次に、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除して、位置を直接設定することを検討します。物理の下で動作させる場合は、後で再度追加します。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。次に、そのスプライトに関連付けられている物理ボディを物理シミュレーションから削除して、位置を直接設定することを検討します。物理の下で動作させる場合は、後で再度追加します。これは、物理学の世界からそれを追加/削除するクリーンな方法がない場合、物理学の本体を削除し、後でそれを再作成することを意味する場合があります。

別の解決策は、一緒に移動したいボディ間にジョイントを作成することです。距離結合または溶接接合が最も適切です。これにより、それらが接続されるため、一方を移動すると、もう一方も移動し、2つのボディ間の距離が同じに保たれます。この場合、両方とも物理シミュレーションの下で動作します。

実際、キャラクターとその上に立っているCCSpriteの両方の物理ボディの位置を変更しているのではないかと思いました。この場合、物理シミュレーションが制御されていないため、これは悪いだけでなく、位置計算によって2つのボディがわずかに重なる可能性があるため、次に物理シミュレーションを実行すると、両方のボディに大きな力が適用されます。それらを強制的に離しますが、次に位置を元に戻して再びオーバーラップするようにすると、次の更新で再び大きな力が発生します。

CCSpriteの位置を変更しても、実際には物理ボディの位置が変更されておらず、基本的に、プレーヤーのレンダリング位置を物理ボディが世界にある場所とは異なる位置に設定しているだけの場合は、物理体に何が起こっているかを考慮する必要があります。それは転がり回ったり、世界から落ちたり、他のオブジェクトや他の何かの間で振動したりしていますか?あなたのゲームについてもっと知らずに、何が起こっているのかを判断するのは難しいです。しかし、それに何が起こっているかはあなたの位置計算に影響を及ぼしているかもしれません。スプライトを物理シミュレーションの対象とせずに移動したい場合は、物理オブジェクトを物理ワールドから削除することを検討してください。物理体を扱う場合、ある種のデバッグ描画を行うことは非常に重要です。そのため、自分のスプライトや他のアートワークに関係なく、各ボディの正確な形状と位置、およびそれが相互作用しているものを確認できます。Cocos2D / Box2Dコンボがこれを箱から出して提供するかどうかはわかりませんが、そうでない場合は、オン/オフを簡単に切り替える方法で実装することを強く検討してください。

考慮すべきもう1つのことは、2つのステートメントです。

if (spriteA.position.x - spriteA.boundingBox.size.height*.5 <= spriteB.position.x + spriteB.boundingBox.size.height*.5)

if (spriteB.position.x - spriteB.boundingBox.size.height*.5 <= spriteA.position.x + spriteA.boundingBox.size.height*.5)

これらの2つのステートメントを削除して、数フレームにわたって位置にエラーが発生するのを待つのではなく、フレームごとに新しい位置を設定しようとしましたか?一方のオブジェクトを動かしていて、もう一方のオブジェクトをしっかりと取り付けられているかのように動かしたい場合は、フレームごとに位置を更新する必要があります。この条件付き、たとえば30フレームごとに10フレームしか渡していない可能性があるため、30 fpsと仮定すると、必要なスムーズな動きとは対照的に、非常に目に見えるぎくしゃくした動きになります。

上記の何かがあなたの問題を解決するか、少なくともどこから探し始めるかについてのより良いアイデアをあなたに与えることを願っています。あなたの質問でより多くの情報を提供すること-おそらく私が言及したいくつかの仮定/未知数に答えること-は私たちがあなたの問題の根底に到達するのを助けるはずです:)

編集1

余分な詳細を記入していただきありがとうございます-それは物事をはるかに明確にします。Box2Dとの衝突検出のみを行っていることがわかったので、あなたが行っていることは完全に理にかなっています。

問題を解決するにforは、連絡先を確認し、連絡先が作成されたことを検出するループで、この時点でキャラクターの位置を変更するのではなく、フラグを設定する必要があります。たとえば、次のBOOL characterOnPlatformように設定します。YES接触が検出されたとき。そのループの外側for(ただし、必ずしも同じメソッドではありません-すべてのフレームと呼ばれる場所であればどこでも、最も意味のある場所であればどこでも)、そのフラグをチェックし、場合characterOnPlatfom == YESは、文字の位置を現在の位置計算に設定します現在、連絡先リスナーforループで実行しています。つまり、他の場所で参照する状態を変更する以外forは、連絡先リスナーループで何もしないでください。

この変更により、キャラクターはプラットフォームに合わせて正確に動きます。それでもキャラクターがプラットフォームから飛び降りることができるようにしたいNO場合は、プレイヤーがジャンプなどの入力を行った場合にそのフラグを戻す必要があります。そうしないと、キャラクターを上の位置に強制することで、目的の動きが上書きされます。プラットフォーム。

編集2

新しいコードで何が起こっているのかを正確に確認することは実際には不可能です。たとえば、あなたのresetgravityメソッドで何が起こっているのですか?どのようにNOに設定hasCollidedしますか(つまり、キャラクターがプラットフォーム上に存在しなくなったことをどのように検出しますか)?あなたのキャラクターはまだ上下の動きで揺れていますか、それともあなたが言及したちらつきは以前とは異なりますか?

あなたがまだ上下の動きをしていると仮定すると、これはあなたが投稿したコードがすべてのフレームで呼び出されていないか、他のポジショニングコードと戦っている(たとえば、どこに移動しても)ことが原因であると私は予想しますプレイヤーの入力に応じて周りのキャラクター、重力などを適用します)。

キャラクターをプラットフォーム上に保持するコードが位置を高く設定しすぎて、キャラクターがプラットフォーム上にないものとして検出されないようにしてください。そうすると、次の悪循環に陥ります。

  • キャラクターがプラットフォームと衝突する
  • キャラクターの位置はプラットフォームの真上に設定されています
  • キャラクターがプラットフォームと衝突しなくなったため、プラットフォーム上でキャラクターを再配置するためのポジショニングコードは実行されません
  • 重力の影響によりキャラクターが下に落ちる(またはこれをシミュレートする)
  • キャラクターがプラットフォームと衝突する
  • ..。

その場合は、キャラクターがプラットフォームと衝突していないときの検出を改善するか、キャラクターがプラットフォームとわずかに交差したままになるようにポジショニングコードをオフセットする必要があります(これが視覚的に悪い場合は、スプライトをBox2Dシェイプからわずかにオフセットして、物理ボディがプラットフォームとわずかに交差するようにしますが、キャラクターの足はプラットフォーム上に正確にあるように見えます。

編集3

ジッターの原因となる可能性のある多くのことを除外したようです。私は別のゲーム開発者に尋ねました、そして彼はあなたの問題がおそらく世界空間からスクリーン空間への変換によって引き起こされるかもしれないと提案しました。したがって、キャラクターのワールド位置と、それがレンダリングされる画面位置をログアウトしてみることができます(これは、この変換が行われるCocos2Dのコードを変更することを意味する場合があります)。少なくともログアウトされた値を確認すると、ジッター/振動している値を絞り込むのに役立つ場合があります。また、浮動小数点の精度を整数に切り捨てるなど、発生する可能性のある丸め点エラーを探すこともできます。ジッタが+1ピクセルまたは-1ピクセルの領域にあるように見える場合は、ワールド位置と画面位置を比較する価値があります。

于 2012-05-20T13:33:24.577 に答える