どのようにすれば、攻撃者は攻撃者だけを攻撃し、攻撃者は攻撃者を攻撃するだけですか?


11

私のゲームには、さまざまなタイプの善人とさまざまなタイプの悪者がいます。それらはすべてお互いに発射体を発射しますが、どちらのアラインメントでも偶発的な付随的な損傷が発生することは望ましくありません。そのため、悪者は他の悪者を打ったりダメージを与えたりしてはならず、善人は他の善人を打ったりダメージを与えたりすべきではありません。

私がこれを解決することを考えている方法は、Unitインスタンス(これはjavascript、btw)がまたはのalignmentいずれかのプロパティを持つようにすることです。そして、衝突が起きるのは、goodbad

class Attack

    boolean didAttackCollideWithTarget(target)
        return attack.source.alignment != target.alignment and collisionDetected(attack.source, target)

もちろん、これは疑似コードです。

しかし、私がこの質問をしているのは、Unitクラスにさらに別のプロパティを追加する以外に、これを設計するはるかにエレガントな方法があるかもしれないという感覚を得ているからです。


5
フィルタリングはここでの典型的なアプローチです。基本的にそれはあなたが説明したことです。レイヤーもあります。2つの層、悪い層と良い層。悪い男の発射体は良い層に発射され、その逆も同様です。
MichaelHouse

@ Byte56この「レイヤー」の概念について詳しく説明していただけますか?または少なくともそれについて何かにリンクしていますか?聞いたことがない。
Daniel Kaplan

基本的に、それらは異なる「世界」です。レイヤー内のすべてのオブジェクトは互いに相互作用しますが、他のレイヤーとは相互作用しません。これは、タグを使用して(フィルタリングなど)、またはレイヤーごとにまったく異なるデータセットを使用して行うことができます。
MichaelHouse

3
つまり、グループ化です。良い弾丸をグループ化し、悪者との衝突のみをチェックします。Flixelにはこのようなコンセプトがあります。
ashes999 2013年

3
ちょっとしたデザインノート:「友好的な火」のショットをヒットさせたいがダメージは与えないか、それとも味方を完全に無視して、代わりにそれらを通過して敵を攻撃するか?
Steven Stadnicki 2013年

回答:


6

衝突フィルタリング

多くのレイヤーに拡張されるより堅牢な状況は、フィルタリングを使用することです。これは、グループ化と同じではありません。

これは、すべてのオブジェクトに2つのビットマスクを与えることで最も効果的に機能します。

Category
Mask

そして、以下が真の場合にのみ衝突を引き起こします。

(filterA.maskBits & filterB.categoryBits) != 0 &&
(filterA.categoryBits & filterB.maskBits) != 0;

マスクを0xFFFFにデフォルト設定するのが最も簡単で、すべてと衝突します。また、カテゴリのデフォルトは0x0001です。オブジェクトが他のマスクのカテゴリと衝突すると、衝突が発生します。

それを考えるもう1つの方法は、各オブジェクトがタイプを持ち、衝突可能なすべてのタイプのリストを持っているということです。2つのオブジェクトの両方が互いのタイプと衝突した場合にのみ、衝突が発生します。マスクの代わりに列挙型のリストを使用して同じ動作をすることもできますが、マスクは桁違いに高速です。

あなたが説明するシナリオ

私はこの状況で列挙型を利用したいです。

だから私たちは持っていると言います。

enum Categories {
    GoodGuy =           0x0001,
    BadGuy =            0x0002,
    Bullet =            0x0004,
    GlassWall =         0x0008,
    Lazer =             0x0010,
    All =               0xFFFF
};

いい男が弾丸を撃った

 Category = Bullet
 Mask = BadGuy | GlassWall

グッド・ガイ

 Category = GoodGuy
 Mask = All

悪い男

 Category = BadGuy
 Mask = All

良い男が発射した弾丸が別の良い男に当たったとき、その結果は以下になります。

(All & GoodGuy) != 0 && <-- Passes
(GoodGuy & (BadGuy | GlassWall)) != 0; <-- This would fail

しかし、それは悪者を襲います。

(All & BadGuy) != 0 && <- Passes
(BadGuy & (BadGuy | GlassWall)) != 0; <-- Passes

ビット演算の低レベルの詳細で説明するのではなく、これを概念的に説明していただけませんか?
Daniel Kaplan 2013年

@tieTYTは5分後にもう一度確認してください
ClassicThunder

2

現在のプロジェクト(Java)でも同じ問題が発生しました。数回試した後、4つのリストを作成して解決します。このソリューションはJavaおよび2Dゲーム用に作成されますが、JavaScriptでも同様に機能するはずです。

public static main (String [] args)
{
    private List<Bullets> bullets_GoodGuys = new LinkedList <Bullet>(); //List of all bullets fired by good guys
    private List<Bullets> bullets_BadGuys  = new LinkedList <Bullet>(); //List of all bullets fired by bad guys
    private List<Guys> goodGuys  = new LinkedList <Guys>(); //List of all good guys
    private List<Guys> badGuys  = new LinkedList <Guys>();  //List of all good guys

    init();
    ...
    while(game_is_running)
    {
        ... 
        for(int i=0;i>=goodGuys.length;i++)
        {
            for(int j=0;j>=bullets_BadGuys.length;i++)
            {
                if(goodGuys.get(i).getBounding().interacts(bullets_BadGuys.get(i).getBounding()))
                {// If a good guy was hit by a bullet from a bad guy
                    goodGuys.get(i).getDamage();
                    bullets_BadGuys.remove((bullets_BadGuys.get(i));
         }   }   }
       for(...) //same for the bad guys
       {...}
}

疑似コード

class Guys
{
   private float xkoordinate;
   private float ykoordinate;
   private BufferedImage look;
   private Rectangle bounding = new Rectangle(xkoordinate,ykoordinate,look.getWith(),look.getHight())
   ...
}

クラスBulletsと同じ擬似コード

これは最善または最速のソリューションではない可能性がありますが、現時点で役立ちます。JavaScriptで解決策を提供できないのは残念ですが、私があなたを助けることができれば幸いです

ちなみに私の英語は上手ではありませんが、私の説明に従ってください。

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