0
votes

My collision detection seems to be working, all be it some of the collisions it is detecting are odd as in it'll say that the collision was on the bottom of the platform when it isn't. However that isn't the main problem.

When the player collides with the platform, instead of moving to the surface of the platform he moves above it and with my gravity in place it looks like he is constantly bouncing. I can't figure out why.

If you guys could help it would be much appreciated. It could be something very simple I'm missing since I'm new to XNA and C#.

I will list my Game1, Player and Platoform classes below. (My collision detection is in the player class)

Thanks

Game1 Class

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Texture2D background;
    Movement character;
    Platform[] platforms;
    //private Vector2 SnapePosition = Vector2.Zero;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferHeight = 440;
        graphics.PreferredBackBufferWidth = 782;

    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        platforms = new Platform[15];


        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);


        for (int i = 0; i < platforms.Length; i++)
        {
            platforms[i] = new Platform(
                Content.Load<Texture2D>("Platforms/lvl2_platform"), new Rectangle(i*100, 410, 100, 30));
        }
        character = new Movement(Content.Load<Texture2D>("snape"), new Rectangle(0, 360, 50, 50), platforms);

        // TODO: use this.Content to load your game content here
        background = Content.Load<Texture2D>("Backgrounds/lvl2_background");
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        //Allows the player to move
        character.Update();

        // TODO: Add your update logic here


        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here

        spriteBatch.Begin();
        spriteBatch.Draw(background, Vector2.Zero, Color.White);
        character.Draw(spriteBatch);

        foreach (Platform platform in platforms)
        {
            platform.Draw(spriteBatch);
        }
        spriteBatch.End();

        base.Draw(gameTime);
    }
}

Player Class

class Player
{
    public Texture2D Snape;
    public Rectangle SnapePosition;

    public enum CollisionPosition { None, Top, Bottom, Left, Right };
    public CollisionPosition collisionType;
    public bool inCollision;
    public int collisionDepth;
    public Platform[] plat;
    public int num;

    public virtual void Update()
    {

    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Snape, SnapePosition, Color.White);
    }
}

class Movement : Player
{
        public Movement(Texture2D newSnape, Rectangle newSnapePosition, Platform[] a)
    {
        Snape = newSnape;
        SnapePosition = newSnapePosition;
        plat = a; 
    }

        public override void Update()
        {
            // Check for collision
            Collisions();

            // Determine collision type
            //DetermineCollisionType();

            // Separate snape
            //SeparateSnape();

            KeyboardState keyBoard = Keyboard.GetState();

            if (keyBoard.IsKeyDown(Keys.A))
            {
                SnapePosition.X -= 5;
            }
            if (keyBoard.IsKeyDown(Keys.D))
            {
                SnapePosition.X += 5;
            }
            if (keyBoard.IsKeyDown(Keys.W))
            {
                SnapePosition.Y -= 5;
            }
            //if (keyBoard.IsKeyDown(Keys.S))
            //{
                SnapePosition.Y += 5;
           // }



          //  if (SnapePosition.X < 0)
          //      SnapePosition.X = 0;
          //  if (SnapePosition.Y < 0)
          //      SnapePosition.Y = 0;
          //  if (SnapePosition.X > GraphicsDevice.Viewport.Width - Snape.Width)
          //      SnapePosition.X = GraphicsDevice.Viewport.Width - Snape.Width;
          //  if (SnapePosition.Y > GraphicsDevice.Viewport.Height - Snape.Height)
          //      SnapePosition.Y = GraphicsDevice.Viewport.Height - Snape.Height;

        }


        public void Collisions()
        {
            for (int i = 0; i < plat.Length; i++)
            {
                if (plat[i].rectangle.Intersects(SnapePosition))
                {
                    inCollision = true;
                    num = i;
                    DetermineCollisionType();
                }

            }

        }

        public void DetermineCollisionType()
        {
            if (inCollision == false)
            {
                collisionType = CollisionPosition.None;
                collisionDepth = 0;
            }
            else
            {
                // Determine the side of *least intersection* for snape
                int minColDepth = int.MaxValue;

                // Check the top side                    
                int tColDepth = (plat[num].rectangle.Y + plat[num].texture.Height / 2) - (SnapePosition.Y - Snape.Height / 2);

                if (tColDepth > 0 && tColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Top;
                    minColDepth = tColDepth;
                }

                // Check the bottom side            
                int bColDepth = (SnapePosition.Y + Snape.Height / 2) - (plat[num].rectangle.Y - plat[num].texture.Height / 2);

                if (bColDepth > 0 && bColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Bottom;
                    minColDepth = bColDepth;
                }

                // Check the right overlap
                int rColDepth = (SnapePosition.X + Snape.Width / 2) - (plat[num].rectangle.X - plat[num].texture.Width / 2);

                if (rColDepth > 0 && rColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Right;
                    minColDepth = rColDepth;
                }

                // Check the left overlap
                int lColDepth = (plat[num].rectangle.X + plat[num].texture.Width / 2) - (SnapePosition.X - Snape.Width / 2);

                if (lColDepth > 0 && lColDepth < minColDepth)
                {
                    collisionType = CollisionPosition.Left;
                    minColDepth = lColDepth;
                }

                // Update the collision depth
                collisionDepth = minColDepth;
                SeparateSnape();
            }
        }



        public void SeparateSnape()
        {
            switch (collisionType)
            {
                case CollisionPosition.None:
                    break;

                case CollisionPosition.Top:
                    SnapePosition.Y += (collisionDepth);
                    break;

                case CollisionPosition.Bottom:
                    SnapePosition.Y -= collisionDepth;
                    break;

                case CollisionPosition.Right:
                    SnapePosition.X -= collisionDepth;
                    break;

                case CollisionPosition.Left:
                    SnapePosition.X += collisionDepth;
                    break;
            }
        }
}

Platform Class

class Platform
{
    public Texture2D texture;
    public Rectangle rectangle;

    public Platform(Texture2D newTexture, Rectangle newRectangle)
    {
        texture = newTexture;
        rectangle = newRectangle;
    }

    public void Update()
    {

    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, rectangle, Color.White);
    }


}
1

1 Answers

0
votes

I fixed up your collision.

All of your depth calculations were incorrect. You were doing them based upon the center of the entity (player/platform) and using their texture sizes instead of their rectangle sizes.

You may have been thinking that everything draws from the middle, but by default it draws from the top left in XNA.

Here are the new depth calculations located in your "Movement" class under the "DetermineCollisionType()" function.

The top depth needs to work on the top of the platform (Y), and on the bottom of snape (Y + Height).

int tColDepth = 
    (SnapePosition.Y + SnapePosition.Height) - (plat[num].rectangle.Y);

The bottom depth needs to work on the bottom of the playform (Y + Height) and on the top of snape (Y).

int bColDepth = 
    (plat[num].rectangle.Y + plat[num].rectangle.Height) - (SnapePosition.Y);

The right depth needs to work on the left of the platform (X) and the right of snape (X + Width).

int rColDepth = 
    (SnapePosition.X + SnapePosition.Width) - (plat[num].rectangle.X);

The left depth needs to work on the right of the platform (X + Width) and on the left of Snape (X).

int lColDepth = 
    (plat[num].rectangle.X + plat[num].rectangle.Width) - (SnapePosition.X);

This will work from now on in. However you may want to use lists for your platform. Lists are easier for when/if you do a level editor as you don't have to say "I want 15 platforms".