3
votes

I am using the MonoGame framework to make a platforming game. The game has some basic mechanics like: gravity, and collision detection that only works on the last object in a list.

Here is the code for the game area of the game (main script): `

    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);
            }
        }
    }`

Here is the object class (what player, and box is built off of):

`

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);
        }
    }
}

`

Player script:

`

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);
        }
    }
}`

The box just inherits from Object2D.cs, no code has been changed.

But in the update void of the MainGame.cs, where we are checking for the collision:

`

        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());`

The code works, but only for the second object in our List, when I move over the first box added, I just fall down, as gravity is applied.

I'm not to sure why it's only checking for the last box in the List of Boxes.

1

1 Answers

2
votes

You're not stopping the search once you find a collision. Change this code:

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

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

...to something like:

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;