【问题标题】:XNA 4.0 Collision Detection From a ListXNA 4.0 列表中的碰撞检测
【发布时间】:2015-07-16 14:39:27
【问题描述】:

我正在开发一个简单的小游戏,只是为了在设计过程中让我的脚湿透。我在尝试对列表中的项目进行碰撞检测时遇到了问题。我有一个敌人等级,一次会产生三个敌人,然后这些船每艘都有能力一次发射三颗子弹。我遇到的问题是我的碰撞检测正在跟踪船,而不是每个单独的子弹,即使碰撞矩形正在获取子弹位置。在拍摄子弹方法中,我分配了一个 Vector2 来复制子弹位置(很确定我必须通过传入索引来做一些事情,但我不知道从哪里开始)。任何帮助/指导将不胜感激!

SpriteManager.cs

 for (int j = 0; j < enemies.Count; j++)
            {
                Enemies e = enemies[j];

                //Update Sprite
                e.Update(Game.GraphicsDevice, gameTime);

                //Check for Collision
                if (e.collisionRect.Intersects(player.collisionRect))
                {
                    lives -= 1;
                }
            }

Enemies.cs

public void ShootBullets()
    {
        Bullets newBullet = new Bullets(bulletTexture);
        newBullet.velocity.X = velocity.X - 3f;
        newBullet.position = new Vector2(position.X + newBullet.velocity.X, 
            position.Y + (texture.Height / 2) - (bulletTexture.Height / 2));

        //Test
        bulletPos = newBullet.position;

        newBullet.isVisible = true;
        if (bullets.Count() < 3)
            bullets.Add(newBullet);
    }

    public Rectangle collisionRect
    {
        get
        {
            return new Rectangle(
                (int)bulletPos.X + collisionOffset,
                (int)bulletPos.Y + collisionOffset,
                bulletTexture.Width - (collisionOffset * 2),
                bulletTexture.Height - (collisionOffset * 2));
        }
    }

编辑以添加子弹类:

    public class Bullets
    {
        // Variables
        public Texture2D texture;

        public Vector2 position;
        public Vector2 velocity;

        public bool isVisible;

        //public Rectangle boundingBox;
        //public Vector2 origin;
        //public float speed;

        // Methods

        // Constructor
        public Bullets(Texture2D newTexture)
        {
           // speed = 10;
            texture = newTexture;
            isVisible = false;
        }

        // Draw
        public void draw(SpriteBatch spritebatch)
        {
            spritebatch.Draw(texture, position, Color.White);
        }

    }
}

【问题讨论】:

    标签: c# list xna collision-detection xna-4.0


    【解决方案1】:

    不仅要循环穿过敌人,还需要循环穿过敌人的每个子弹。

    对您的代码进行最简单的修改类似于

     for (int j = 0; j < enemies.Count; j++)
                {
                    Enemies e = enemies[j];
    
                    //Update Sprite
                    e.Update(Game.GraphicsDevice, gameTime);
    
                    for (int u = 0; u < e.bullets.count; u++) {
                       Bullet b = e.bullets[u];
                       //Check for Collision
                       if (b.collisionRect.Intersects(player.collisionRect))
                       {
                           lives -= 1;
                       }
                    }
                }
    

    但是,请注意有几件事通常不建议您在此处进行。

    首先,不是每个敌人都有自己的子弹列表,而是应该有一个所有子弹的全局列表,每个敌人在“发射”他们的子弹时都会添加到这个列表中。

    那么您只能搜索那个列表,而不是查找每个敌人,然后再次查找该敌人的每个子弹。

    其次,不要像你这样写出自定义的 for 循环

    for (int j = 0; j < enemies.Count; j++) {
    Enemies e = enemies[j];
    

    考虑简单地做

    //same thing
    foreach (var e in enemies) {
    

    另外,请确保在对这些子弹执行更新逻辑时删除任何超出范围或击中其他对象的子弹。 有很多方法可以优化何时可以销毁对象以及需要检查哪些对象是否发生碰撞。 碰撞检查通常应该针对尽可能少的物体执行,因为它们是您在游戏中需要做的较慢的事情之一。 Althoguh 简单的矩形交叉点非常快,所以可能还不需要担心优化该部分。

    【讨论】:

    • 关于您对循环的评论的注释:据我所知,就性能而言,使用 for 循环优于 foreach 循环,在这种情况下,性能是关键。来源:stackoverflow.com/questions/365615/…
    • 优化到 for 循环而不是数组上的 foreach 是对游戏进行编码时最重要的事情之一。如果你需要那种速度来让你的游戏不会受到性能的影响,那么你在其他地方做的事情就更错误了。 foreach 更清晰,更易于维护。如前所述,诸如碰撞检查和物理等综合绘图和计算之类的事情是您需要小心的地方。用计数器变量膨胀代码只是为了从第二行的数组中加载一个实例,真的,真的没有必要。
    • @irreal 鉴于您所做的修改,我看到了两个问题。一个是列表项目符号不是公开的,因此无法在课堂外访问。我解决了这个问题并将其公开,没什么大不了的。第二件事是子弹没有碰撞矩形功能,并且射击子弹不接受参数来穿过每个子弹。所以这只是有点混乱。我明白你在说什么
    • 如前所述,考虑不要将子弹存放在敌人级别,而是更高。例如,与存储敌人数组的位置相同。其次,子弹需要它自己的 x 和 y 位置(或可能的向量 2)以及它的宽度和高度,因此很容易创建一个碰撞 tectangle 供它使用。你根本没有展示子弹类,如果你卡住了你也可以给我看那个类,我可以帮你修改。
    • @irreal Taegost 对于foreachfor 是正确的。 foreach 通常涉及为游戏的每一帧的每个循环创建一个枚举器对象。通常,您希望尽量减少临时对象的内存分配,因为它导致您的游戏在garbage collection (GC) 期间明显的随机暂停,尤其是在功率不足的设备上。 不是关于使循环更快;而是最小化 GC。一般可以控制计算时间;但是,无法预测 GC 何时会发生。一款好的游戏会在关卡开始时分配所有内存
    猜你喜欢
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多