XNA C #: объекты-снаряды в списке класса Player, НЕ распознаваемые классом Enemy - PullRequest
0 голосов
/ 02 декабря 2018

Хорошо, поэтому у меня есть CollisionManager для обновления моих коллизий.У меня есть класс «Снаряд», класс «Игрок» и класс «Враг».В классе Player я создал список снарядов (Projectile objs), который обновляет класс Player, чтобы увеличивать или уменьшать их количество.Пока все работает отлично.

Теперь проблема, при проверке на столкновение объекта Player, распознается объектом Enemy.Тем не менее, объект «Снаряд» НЕ распознается противником, ЕСЛИ Я не перебираю весь список снарядов и вручную проверяю их коллайдеры на предмет пересечения.На самом деле кажется, что снаряд коллайдера и не существует, если специально не проверено.

Код указан ниже:

Код столкновения игрока (РАБОТАЕТ):

public override void OnCollision(Collidable obj)
{
    Enemies enemy = obj as Enemies;
    if (enemy != null)
      {
        health -= enemy.dmg; //if player collides with enemy, take dmg damage  
      }
}

Код столкновения снаряда (РАБОТАЕТ):

public override void OnCollision(Collidable obj)
    {
        Enemies enemy = obj as Enemies;
        if (enemy != null)
        {
            exists = false;
            if (!exists) FlaggedForRemoval = true;
        }                               
    }

Врагкод столкновения (ТОЛЬКО РАБОТАЕТ ДЛЯ ИГРОКА)

 public override void OnCollision(Collidable obj)
    {
        //Check collision with player
        Player pl = obj as Player;
        if (pl != null)
        {
           exists = false;
           ScoreManager.UpdateScore(pointsWorth);
        }

        //Check collision with projectile
        Projectile pr = obj as Projectile;
        if (pr != null)
        {
            health -= dmgReceived;
            if (health <= 0)
            {
                ScoreManager.UpdateScore(pointsWorth);
                exists = false;
                FlaggedForRemoval = true;
            }
        }

    }

Столкновение Враг против Снаряда (для вражеского объекта - как работает proj) работает только в том случае, если во время Main.Update (), если я перебираю весь списокснарядов и вручную проверяйте на столкновение с врагом

 foreach (Enemies e in enemyList)
                    {
                        e.Update(gameTime);
                        e.dmgReceived = player.dmg;


                        for (int i = 0; i < player.projList.Count; i++)
                        {
                            if (player.projList[i].collider.Intersects(e.BoundingRectangle))
                            {

                               //Some code
                            }
                        }

Так в чем проблема?Мне кажется, что по какой-то причине во вражеском коде столкновения тип obj не распознается как Снаряд, может быть, потому что он находится в Списке?

Первый раз здесь пишу, так что надеюсь, что все сделал правильно.Спасибо за помощь!

ОБНОВЛЕНИЕ, ЧТОБЫ ВКЛЮЧИТЬ КОД столкновения

    public class Collidable
{
    protected Rectangle boundingRectangle = new Rectangle();
    public bool FlaggedForRemoval { get; protected set; }

    //Constructor
    public Collidable()
    {
        FlaggedForRemoval = false;
    }

    public Rectangle BoundingRectangle
    {
        get { return boundingRectangle; }
    }


    public virtual bool CollisionTest(Collidable obj)
    {
        return false;
    }

    public virtual void OnCollision(Collidable obj)
    {
    }
}

Класс столкновений:

public class CollisionComparer : IEqualityComparer<Collision>
{
    public bool Equals(Collision a, Collision b)
    {
        if ((a == null) || (b == null))
        {
            return false;
        }

        return a.Equals(b);
    }

    public int GetHashCode(Collision a)
    {
        return a.GetHashCode();
    }
}

public class Collision
{
    public Collidable A;
    public Collidable B;

    public Collision(Collidable a, Collidable b)
    {
        A = a;
        B = b;
    }

    public bool Equals(Collision other)
    {
        if (other == null) return false;
        if ((this.A.Equals(other.A) && this.B.Equals(other.B))) return true;
        return false;
    }

    public void Resolve()
    {
        this.A.OnCollision(this.B);
    }
}

СтолкновениеКласс диспетчера:

 public class CollisionManager
{

    //List of classes inheriting from Collidables
    private List<Collidable> m_Collidables = new List<Collidable>(); 

    //Hashset to collect all collisions in a single update
    private HashSet<Collision> m_Collisions = new HashSet<Collision>(new CollisionComparer()); 

    public void AddCollidable(Collidable c)
    {
        m_Collidables.Add(c);
    }

    public void RemoveCollidable(Collidable c)
    {
        m_Collidables.Remove(c);
    }

    public void Update()
    {
        UpdateCollisions();
        ResolveCollisions();
    }

    //Check Collisions hashset

    private void UpdateCollisions()
    {
        if (m_Collisions.Count > 0) m_Collisions.Clear();

        //Iterate thgouh collidable objects to check for collisions
        for(int i =0; i<m_Collidables.Count; i++)
        {
            for (int j = 0; j < m_Collidables.Count; j++)
            {
                Collidable collidable1 = m_Collidables[i];
                Collidable collidable2 = m_Collidables[j];

                //Ensure we are not checking object with itself
                if (!collidable1.Equals(collidable2))
                {
                    //if two objects colliding then add them to the set
                    if (collidable1.CollisionTest(collidable2))
                    {
                        m_Collisions.Add(new Collision(collidable1, collidable2));
                    }
                }
            }
        }
    }

    private void ResolveCollisions()
    {
        foreach (Collision c in m_Collisions)
        {
            c.Resolve();
        }
    }

}

На основании приведенного выше кода обнаружение столкновений для этих трех классов (Player, Enemy, Projectile):

   //Collision Detection
    public override bool CollisionTest(Collidable obj)
    {
        if (obj != null)
        {
            return collider.Intersects(obj.BoundingRectangle);
        }
        else
            return false;
    }

Я обновляю все столкновения с помощью collisionManager.Обновление () в основной части игры. Обновление ().

Прошу прощения за длинный код!

ОБНОВЛЕНИЕ 2 ПОКАЗЫВАЕТ ПРОЕКТЫ, ДОБАВЛЕННЫЕ В СПИСОК

оба приведенных ниже относятся к классу Player, а UpdateProjectile является частью player.Update ();

 public void PlayerShoots()
    {
        //Fire only if projectile delay resets
        if (projDelay >= 0)
            projDelay--;

        // if projectile delay is at 0 then create a new projectile(add to list)
        if(projDelay <=0)
        {

            Projectile newProj = new Projectile(projTexture);
            collisionManager.AddCollidable(newProj);
            newProj.position = new Vector2(position.X + 100 - newProj.texture.Width / 2, position.Y ); //+ newProj.texture.Height/10
            newProj.collider = new Rectangle((int)newProj.position.X, (int)newProj.position.Y, newProj.texture.Width, newProj.texture.Height);
            newProj.exists = true;


            if (projList.Count() < 80)
            {
                projList.Add(newProj);

            }
        }

        //reset projectile delay
        if (projDelay == 0)
            projDelay = 50;
    }

и

// update projectile functioN
    public void UpdateProjectile()
    {
        // for each projectile in the list update its position and remove it if it reaches right screen boundary
        foreach(Projectile p in projList)
        {
            //Update collider for every projectile in our list
            p.collider = new Rectangle((int)p.position.X, (int)p.position.Y, p.texture.Width, p.texture.Height);
           //Projectile motion
            p.position.X = p.position.X + p.speed+1;
            if (p.position.X >= 1118)
                p.exists = false;
        }

        for(int i = 0; i<projList.Count; i++)
        {
            if(!projList[i].exists)
            {
                projList.RemoveAt(i);
                i--;
            }
        }
...