[MonoGame][3.8.1][Aether.Physics2D]キャラクターが地面に設置しているかの判別

キャラクターが地面に設置しているかの判別方法に苦労したのメモしておきます。

/// <summary>
/// 地面に接触しているかを判定する
/// </summary>
/// <param name="rootContactEdge">判定対象のBodyオブジェクトのContactList<param>
/// <returns>true:接地している, false:接地していない</returns>
private bool isTouchGround(ContactEdge rootContactEdge)
{
    bool isTouchGround = false;
    ContactEdge contactEdge = rootContactEdge;

    while (contactEdge != null)
    {
        Contact contact = contactEdge.Contact;
        while (contact != null)
        {
            for (;;)
            {
                //接地しているかを確認する
                if (!contact.IsTouching) break;

                //FixtureBが自機であることを確認する(FixtureBに引数で指定したContactListのBodyが入っていると推測される)
                if (contact.FixtureB == null) break;
                if (contact.FixtureB.Body == null) break;
                if (!(contact.FixtureB.Body.Tag is Sprite)) break;

                Sprite spriteB = (Sprite)contact.FixtureB.Body.Tag;
                if (spriteB.spriteType != SpriteType.player) break;

                //FixtureAが地面であることを確認する
                //このコード場合は、Bodyのタグに文字列で"ground"が入っているオブジェクトを地面として定義しています。
                if (!(contact.FixtureA.Body.Tag is string) || !((string)contact.FixtureA.Body.Tag == "ground")) break;


                if (contact.Manifold.Type == tainicom.Aether.Physics2D.Collision.ManifoldType.FaceA && contact.Manifold.LocalNormal.Y > 0f)
                {
                    //地面の場合は上向きの面のなら地面
                    isTouchGround = true;
                }
                else if (contact.Manifold.Type == tainicom.Aether.Physics2D.Collision.ManifoldType.FaceB && contact.Manifold.LocalNormal.Y < 0f)
                {
                    //キャラの場合は下向きの面のなら地面
                    isTouchGround = true;
                }

                break;
            }

            if (isTouchGround) break;

            contact = contact.Next;
            if (contact == contactEdge.Contact) break;
        }
        if (isTouchGround) break;

        contactEdge = contactEdge.Next;
        if (contactEdge == rootContactEdge) break;
    }

    return isTouchGround;
}

以下のように使用します。

if(isTouchGround(playerBody.ContactList){
    //設置しているときの処理
}

0 件のコメント :

コメントを投稿