XNA / MonoGame - 如何使用Rectangle作为边界框检查列表中每个对象的碰撞

时间:2016-10-12 01:56:36

标签: c# xna monogame

我正在使用MonoGame框架制作一款平台游戏。游戏有一些基本的机制,例如:重力和碰撞检测,它只适用于列表中的最后一个对象。

以下是游戏游戏区域的代码(主要脚本): `

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Survive.Engine;
    using System.Collections.Generic;

    namespace Game
    {
        public class MainGame : Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;

            Player player = new Player();

            List<Box> boxes = new List<Box>();

            public MainGame()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
            }

            protected override void Initialize()
            {
                Box box = new Box();
                box.Init(new Vector2(100, 400), Content.Load<Texture2D>("Player"));

                Box box2 = new Box();
                box2.Init(new Vector2(132, 400), Content.Load<Texture2D>("Player"));

                player.Init(new Vector2(100, 100), Content.Load<Texture2D>("Player"));

                boxes.Add(box);
                boxes.Add(box2);

                base.Initialize();
            }

            protected override void LoadContent()
            {
                spriteBatch = new SpriteBatch(GraphicsDevice);
            }

            protected override void UnloadContent()
            {

            }

            protected override void Update(GameTime gameTime)
            {
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                    Exit();

                for (int i = 0; i < boxes.Count; i++)
                {
                    if (player.Colliding(boxes[i]))
                    {
                        player.falling = false;
                    }

                    if (!player.Colliding(boxes[i]))
                    {
                        player.falling = true;
                    }
                }

                player.Update();
                boxes.ForEach(k => k.Update());

                base.Update(gameTime);
            }

            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);

                spriteBatch.Begin();

                player.Draw(spriteBatch);

                for (int i = 0; i < boxes.Count; i++)
                {
                    boxes[i].Draw(spriteBatch);
                }

                spriteBatch.End();

                base.Draw(gameTime);
            }
        }
    }`

这是对象类(构建的是什么播放器和框):

`

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Game.Engine
{
    public class Object2D
    {
        public int Health = 100;
        public Vector2 Position;
        public Texture2D Texture;
        public Rectangle BoundingBox;

        public bool Colliding(Object2D obj)
        {
            bool col = false;

            if (BoundingBox.Intersects(obj.BoundingBox))
            {
                col = true;
            }

            return col;
        }

        public virtual void Init(Vector2 pos, Texture2D text)
        {
            Position = pos;
            Texture = text;
        }

        public virtual void Update()
        {
            BoundingBox = new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height);
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Texture, Position, Color.White);
        }
    }
}

`

玩家脚本:

`

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Survive.Engine;
using Microsoft.Xna.Framework.Input;

namespace Survive
{
    public class Player : Object2D
    {
        public float vsp = 0;
        public float grav = 0.1f;
        public bool falling = true;
        public bool jmping = false;

        public override void Init(Vector2 pos, Texture2D text)
        {
            base.Init(pos, text);
        }

        public override void Update()
        {
            if (Keyboard.GetState().IsKeyDown(Keys.A))
            {
                Position.X -= 2;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.D))
            {
                Position.X += 2;
            }

            if (falling)
            {
                vsp += grav;
                Position.Y += vsp;
            }

            base.Update();
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            base.Draw(spriteBatch);
        }
    }
}`

该框仅继承自Object2D.cs,未更改任何代码。

但是在MainGame.cs的更新中,我们正在检查碰撞:

`

        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        for (int i = 0; i < boxes.Count; i++)
        {
            if (player.Colliding(boxes[i]))
            {
                player.falling = false;
            }

            if (!player.Colliding(boxes[i]))
            {
                player.falling = true;
            }
        }

        player.Update();
        boxes.ForEach(k => k.Update());`

代码有效,但仅适用于我们列表中的第二个对象,当我移动添加的第一个框时,我只是在应用重力时摔倒。

我不确定为什么它只检查列表框中的最后一个框。

1 个答案:

答案 0 :(得分:2)

一旦发现碰撞,您就不会停止搜索。更改此代码:

    for (int i = 0; i < boxes.Count; i++)
    {
        if (player.Colliding(boxes[i]))
        {
            player.falling = false;
        }

        if (!player.Colliding(boxes[i]))
        {
            player.falling = true;
        }
    }

...类似于:

var isFalling=true;  // assume the worst

for (int i = 0; i < boxes.Count; i++)
    {
        if (player.Colliding(boxes[i]))
        {
            isFalling = false;
            break;
        }
    }

player.falling = isFalling;