【问题标题】:C# XNA Collision Detection with list of objects带有对象列表的 C# XNA 碰撞检测
【发布时间】:2015-06-16 11:32:20
【问题描述】:

我目前正在学习 C# 和 XNA,但在让我的碰撞检测正常工作方面遇到了一些麻烦。我希望我的玩家在 Enemy 对象相交时消失。

下面显示了我在 Obj 类中的代码

class Obj
{
    public Vector2 position;
    public float rotation = 0.0f;
    public Texture2D spriteIndex;
    public string spriteName;
    public float speed = 0.0f;
    public float scale = 1.0f;
    public bool alive = true;
    public Rectangle area;
    public bool solid = false;


    public Obj(Vector2 pos)
    {
        position = pos;
    }

    private Obj()
    {

    }

    public virtual void Update()
    {
        if (!alive) return;

        UpdateArea();
        pushTo(speed, rotation);
    }

    public virtual void LoadContent(ContentManager content)
    {
        spriteIndex = content.Load<Texture2D>("sprites\\" + spriteName);
        area = new Rectangle(0, 0, spriteIndex.Width, spriteIndex.Height);
    }

    public virtual void Draw(SpriteBatch spriteBatch)
    {
        if (!alive) return;

        Rectangle Size;
        Vector2 center = new Vector2(spriteIndex.Width / 2, spriteIndex.Height / 2);

        spriteBatch.Draw(spriteIndex, position, null, Color.White, MathHelper.ToRadians(rotation), center, scale, SpriteEffects.None, 0);

    }

    public bool Collision(Vector2 pos, Obj obj)
    {
        Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
        newArea.X += (int)pos.X;
        newArea.Y += (int)pos.Y;

        foreach (Obj o in Items.objList)
        {
            if (o.GetType() == obj.GetType() && o.solid)
                if (o.area.Intersects(newArea))
                    return true;
        }
        return false;
    }

    public Obj Collision(Obj obj)
    {
        foreach (Obj o in Items.objList)
        {
            if (o.GetType() == obj.GetType())
                if (o.area.Intersects(area))
                    return o;
        }
        return new Obj();
    }

    public void UpdateArea()
    {
        area.X = (int)position.X - (spriteIndex.Width / 2);
        area.Y = (int)position.Y - (spriteIndex.Height / 2);
    }

    public T CheckCollisionAgainst<T>() where T : Obj
    {
        // If collision detected, returns the colliding object; otherwise null.
        return Items.objList
            .OfType<T>()
            .FirstOrDefault(o => o.solid && o.area.Intersects(area));
    }

    public virtual void pushTo(float pix, float dir)
    {
        float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
        float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
        position.X += pix * (float)newX;
        position.Y += pix * (float)newY;
    }
}

我正在循环遍历我的 objList 中的每个项目,以查看它们是否相互交叉,在这种情况下,如果敌人与它们相交,我希望我的玩家消失,但这没有发生。

这段代码来自我的 Player 类

class Player : Obj
{
    KeyboardState keyboard;
    KeyboardState prevKeyboard;

    float spd;

    public static Player player;

    public Player(Vector2 pos) 
        : base(pos)
    {
        position = pos;
        spd = 4;
        spriteName = "WhiteBall";
        solid = false;
        player = this;
    }

    public override void Update()
    {
        player = this;
        //If the player is NOT alive, end.
        if (!alive) return;

        keyboard = Keyboard.GetState();

        //Keyboard controls for game
        if(keyboard.IsKeyDown(Keys.W) && !Collision(new Vector2(0, -spd), new Enemy(new Vector2(0, 0))))
        {
            position.Y -= spd;
        }
        if (keyboard.IsKeyDown(Keys.A) && !Collision(new Vector2(-spd, 0), new Enemy(new Vector2(0, 0))))
        {
            position.X -= spd;
        }

        if (keyboard.IsKeyDown(Keys.S) && !Collision(new Vector2(0, spd), new Enemy(new Vector2(0, 0))))
        {
            position.Y += spd;
        }

        if (keyboard.IsKeyDown(Keys.D) && !Collision(new Vector2(spd, 0), new Enemy(new Vector2(0, 0))))
        {
            position.X += spd;
        }
        prevKeyboard = keyboard;

        //Collision with enemy
        Enemy enemy = CheckCollisionAgainst<Enemy>();
        if (enemy != null)
        {
            alive = false;
        }

        base.Update();
    }


    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.DrawString(Game1.font, "Pick Up The Crew", new      Vector2(350, 0), Color.White);

        base.Draw(spriteBatch);
    }
}

如果它与敌人相交,它应该会消失,但这似乎并没有发生。

【问题讨论】:

  • 可能与病情有关。当且仅当 o 和 obj 属于同一类型时,您的函数才会返回 o
  • 什么是 Obj.area - 我猜的矩形?另外你分配的敌人区域是什么 - new Enemy(new Vector2(0, 0))
  • @Discosultan Obj.area 确实是一个矩形,Enemy 的大小是从以下位置计算得出的:public void UpdateArea() { area.X = (int)position.X - (spriteIndex.Width / 2); area.Y = (int)position.Y - (spriteIndex.Height / 2); }
  • 但是在碰撞检测的时候Obj o = Collision(new Enemy(new Vector2(0, 0)));,不是因为UpdateArea还没有调用到敌人的区域0吗?
  • @Discosultan 首先使用public Obj Collision(Obj obj) 方法,然后我调用public void UpdateArea() 方法。那我该怎么办?

标签: c# xna collision-detection


【解决方案1】:

根据您提供的 cmets,我在这里试一试并提供可能的解决方案(确保在调用此之前调用 UpdateArea):

public T CheckCollisionAgainst<T>() where T : Obj
{      
    // If collision detected, returns the colliding object; otherwise null.
    return Items.objList
        .OfType<T>()
        .FirstOrDefault(o => o.area.Intersects(area));
}

Enemy enemy = CheckCollisionAgainst<Enemy>();
if (enemy != null)
{
    alive = false;
}

【讨论】:

  • 好的,谢谢,我已经把CheckCollision代码放在​​Obj类的UpdateArea方法后面了,我需要把第二块放在哪里?
  • 无论您在哪里测试碰撞。我认为您在原始帖子中的 Player 类中进行了测试。替换这个://Collision with enemy Obj o = Collision(new Enemy(new Vector2(0, 0))); if (o.GetType() == typeof(Enemy)) { alive = false; }
  • 我收到了一个错误,if (enemy != null) 说在当前上下文中不存在。
  • 我的错,我更新了答案。只需将Enemy o = 更改为Enemy enemy =
  • 啊,谢谢,我已经尝试了您的建议,但它似乎对我不起作用。敌人向玩家移动,但一旦与玩家发生碰撞,玩家不会被移除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
相关资源
最近更新 更多