0
votes

For school I need to make this gameproject in XNA I've chosen to make a game based on mario. However I've been working out my collision detection for days now and I still can't find the problem.

Here is the link to the project: ProjectMario

Oke so this is what it does. enter image description here

This is my code

TileManager

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace mariospeed.ManagerClasses
{
    class TileManager
    {
        int[,] tilemap;
        int tilesize;
        int mapSizeX;
        int mapSizeY;
        int tileindex;
        Texture2D tex;
        List<Texture2D> texlis;
        public List<Rectangle> blocks;
        public List<Rectangle> blocksTop;
        public List<Rectangle> blocksLeft;
        public List<Rectangle> blocksRight;
        public List<Rectangle> tile;
        public int mapX;
        public int MapW;



        public TileManager()
        {
            tilemap = new int[,]
            {
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
            };


            tilesize = 28;
            texlis = new List<Texture2D>();
            mapSizeX = tilemap.GetLength(1);
            mapSizeY = tilemap.GetLength(0);
            blocks = new List<Rectangle>();
            blocksTop = new List<Rectangle>();
            blocksLeft = new List<Rectangle>();
            blocksRight = new List<Rectangle>();
            tile = new List<Rectangle>();
            mapX = 0;



            for (int x = 0; x < mapSizeX; x++)
            {
                for (int y = 0; y < mapSizeY; y++)
                {
                    if (tilemap[y, x] == 1)
                    {
                        blocks.Add(new Rectangle(x * tilesize - mapX, y * tilesize, 28, 30));

                    }
                }
            }

            foreach (Rectangle block in blocks)
            {
                blocksTop.Add(new Rectangle(block.Center.X, block.Top, block.Width, block.Height));
            }
            foreach (Rectangle block in blocks)
            {
                blocksLeft.Add(new Rectangle(block.Left, block.Y, 1, block.Height));
            }
            foreach (Rectangle block in blocks)
            {
                blocksRight.Add(new Rectangle(block.Right, block.Y, block.Width / 2, block.Height));
            }


            for (int x = 0; x < mapSizeX; x++)
            {
                for (int y = 0; y < mapSizeY; y++)
                {
                    tile.Add(new Rectangle(x * tilesize, y * tilesize, 28, 30));
                }
            }

            MapW = tilesize * mapSizeX;


        }
            //

        public void LoadContent(Texture2D tex1, Texture2D tex2)
        {
            texlis.Add(tex1);
            texlis.Add(tex2);

        }

        public void Draw(SpriteBatch sp)
        {

            for (int i = 0; i < mapSizeX; i++)
            {
                for (int j = 0; j < mapSizeY; j++)
                {
                    tileindex = tilemap[j, i];
                    tex = texlis[tileindex];


                    sp.Draw(tex, new Rectangle(i * 28 - mapX, j * 30, 28, 30), Color.White);

                }

            }

        }

    }
}

Mario Class

    using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using mariospeed.GameScenes;


namespace mariospeed.GameComponents
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Mario : Microsoft.Xna.Framework.DrawableGameComponent
    {

        Texture2D texture2;
        public Vector2 cameraPosition;
        public Vector2 worldPosition;
        public Rectangle rectangle;
        public Rectangle footBounds;
        public Rectangle leftRec;
        public Rectangle rightRec;
        KeyboardState keystate;
        KeyboardState oldkeys;
        public string facing;
        public string state;
        public bool jump;
        float jumpSpeed;
        public float gravity;

        public float speed;
        float time;
        public string prevstate;
        Point frameSize;
        Point sheetSize;
        Point currentFrame;
        public Rectangle source;
        float interval;
        //
        Texture2D charr;
        Vector2 charPos;
        bool jumping; //Is the character jumping?
        public float startY, jumpspeed = 0; //startY to tell us //where it lands, jumpspeed to see how fast it jumps
        protected Texture2D texture;
        protected Vector2 position = new Vector2();

        protected const int WIDTH = 64;
        protected const int HEIGHT = 80;

        protected Rectangle screenBounds;

        protected List<Rectangle> frames;    // hierin de grenzen v/d frames
        private int activeFrame;
        public Mario(Game game, Texture2D texture)
            : base(game)
        {
            this.texture = texture;
            screenBounds = new Rectangle(0, 0,
               Game.Window.ClientBounds.Width, Game.Window.ClientBounds.Height);

            frames = new List<Rectangle>();

            CreateFrames();
            activeFrame = 0;
            PutInStartPosition();

            charr = texture; //Load image
            charPos = new Vector2(230, 450);//Char loc, X/Y
            startY = charPos.Y;//Starting position
            jumping = false;//Init jumping to false
            jumpspeed = 0;//Default no speed

            //
            cameraPosition = new Vector2(0, 0);
            worldPosition = new Vector2(40, 0);
            startY = worldPosition.Y;
            facing = "right";
            prevstate = state;
            state = "stand";
            jump = false;
            gravity = 0f;
            speed = 5f;
            frameSize = new Point(28, 30);
            sheetSize = new Point(6, 7);
            currentFrame = new Point(0, 0);
            time = 0f;
            interval = 100f;
            //
        }
        public void PutInStartPosition()
        {
            position.X = 10;
            position.Y = (screenBounds.Height - (texture.Height+18));

        }

        public Vector2 marioPosition()
        {
            return position;
        }
        public void CreateFrames()
        {

            frames.Add(new Rectangle(0, 0, WIDTH, HEIGHT));
            frames.Add(new Rectangle(WIDTH, 0, WIDTH, HEIGHT));
            frames.Add(new Rectangle(2*WIDTH, 0, WIDTH, HEIGHT));
           // frames.Add(new Rectangle(3*WIDTH, 0, WIDTH, HEIGHT));

        }




        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            time += (float)gameTime.ElapsedGameTime.TotalSeconds;
            oldkeys = keystate;
            keystate = Keyboard.GetState();
            cameraPosition.Y += gravity;
            worldPosition.Y += gravity;
            if (keystate.IsKeyDown(Keys.Right))
            {
                cameraPosition.X += speed;
                worldPosition.X += speed;

                facing = "right";


            }
            if (keystate.IsKeyDown(Keys.Left))
            {
                cameraPosition.X -= speed;
                worldPosition.X -= speed;

                facing = "left";


            }
            if (oldkeys.IsKeyDown(Keys.Left) && !keystate.IsKeyDown(Keys.Left))
            {
                state = "stand";
            }

            if (oldkeys.IsKeyDown(Keys.Right) && !keystate.IsKeyDown(Keys.Right))
            {
                state = "stand";
            }



            if (state == "stand")
            {

                if (keystate.IsKeyDown(Keys.Left))
                {
                    state = "walk";
                     MoveAnimation(gameTime);
                }
                if (keystate.IsKeyDown(Keys.Right))
                {
                    state = "walk";
                    MoveAnimation(gameTime);
                }
            }

            if (state == "walk")
            {
                activeFrame = (activeFrame + 1) % frames.Count;
                gravity = 5f;

            }
            if (state == "stand")
            {
                activeFrame = 0;
                gravity = 5f;
                 StandAnimation();
            }

            //

            if (jump)
            {
                state = "jump";
                cameraPosition.Y += jumpSpeed;
                worldPosition.Y += jumpSpeed;
                jumpSpeed += 1f;
                if (jumpSpeed == 0)
                {
                    jumpSpeed = 0;
                    jump = false;
                    state = "fall";
                }

            }
            else
            {
                if (worldPosition.Y == startY)
                {
                    if (keystate.IsKeyDown(Keys.Space) && !oldkeys.IsKeyDown(Keys.Space))
                    {
                        jumpSpeed -= 18f;
                        jump = true;
                        gravity = 0f;
                    }
                }
            }

            if (state == "fall")
            {
                gravity = 5f;
                JumpAnimation();
            }
            if (state == "jump")
            {
                JumpAnimation();
            }
            if (worldPosition.Y > startY)
            {
                state = "fall";

            }



            rectangle = new Rectangle((int)worldPosition.X, (int)worldPosition.Y, WIDTH, HEIGHT);
            footBounds = new Rectangle(rectangle.Center.X, rectangle.Center.Y, rectangle.Width, 1);
            rightRec = new Rectangle(rectangle.Center.X, rectangle.Y, rectangle.Width / 2, rectangle.Height);
            leftRec = new Rectangle(rectangle.Left, rectangle.Y, 1, rectangle.Height);



            base.Update(gameTime);

        }
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch sBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            if (facing == "right")
            {
                sBatch.Draw(texture, cameraPosition, frames[activeFrame], Color.White, 0f, new Vector2(rectangle.Width / 2, rectangle.Height / 2), 1.0f, SpriteEffects.None, 0);
                    }

            if (facing == "left")
            {
                sBatch.Draw(texture, cameraPosition, frames[activeFrame], Color.White, 0f, new Vector2(rectangle.Width / 2, rectangle.Height / 2), 1.0f, SpriteEffects.FlipHorizontally, 0);

            }
            //sBatch.Draw(texture, position, frames[activeFrame], Color.White);

            base.Draw(gameTime);
        }

        public void MoveAnimation(GameTime gt)
        {

            time += (float)gt.ElapsedGameTime.TotalMilliseconds;
            currentFrame.Y = 3;

            frameSize = new Point(33, 33);
            if (time > interval)
            {
                currentFrame.X++;
                if (currentFrame.X > 4)
                {
                    currentFrame.X = 1;
                }
                source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * 25, frameSize.X, frameSize.Y);
                time = 0f;
            }
        }

        public void JumpAnimation()
        {

            currentFrame.Y = 5;
            currentFrame.X = 1;
            frameSize = new Point(33, 33);
            source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y);

        }

        public void FallAnimation()
        {
            currentFrame.X = 5;
            currentFrame.X = 2;
            frameSize = new Point(33, 33);
            source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y);
        }
        public void StandAnimation()
        {
            currentFrame.X = 1;
            currentFrame.Y = 2;
            frameSize = new Point(33, 33);
            source = new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * 19, frameSize.X, frameSize.Y);

        }

    }
}

And The Collision Detection Method

    public void Collision()
        {


            foreach (Rectangle top in map.blocksTop)
            {
                if (top.Intersects(mario.footBounds))
                {
                    mario.gravity = 0f;
                    mario.state = "stand";
                    mario.startY = mario.worldPosition.Y;
                }
            }

            foreach (Rectangle left in map.blocksLeft)
            {
                if (left.Intersects(mario.rightRec))
                {
                    if (mario.footBounds.Y >= left.Y)
                    {

                        mario.worldPosition.X -= 5f;
                        mario.cameraPosition.X -= 5f;
                    }
                }
            }

            foreach (Rectangle right in map.blocksRight)
            {
                if (right.Intersects(mario.leftRec))
                {
                    if (mario.footBounds.Y >= right.Y)
                    {
                        mario.worldPosition.X += 5f;
                        mario.cameraPosition.X += 5f;
                    }
                }
            }

        }

Can someone tell me what I'm doing wrong?

Kind regards Trustos

2
you can't expect people to have time to download and read through your complete project. give more details or provide code on what part of your collision detection is the problemcppanda
Please include only the code you think has problems and explain what those problems might be, what you expect that code to do and what it actually does. Because there is very little chance anyone is going to download that.user1306322

2 Answers

0
votes

You can use a build in collision function which is basically for square objects in your game or build a bool function which return true if your object is on the same location of other object or trying to move through it. Or try youtube for collission tutorial or some physics as well :).

0
votes

Here is a simple way to do tile collisions for a side scrolling. This won't work if the character goes really fast. It's assuming your game runs at 60 fps for a better result.

Separate the test on both axis. Start with Y. If the tile at the destination is occupied, clamp the Y at the top or bottom.

Then do X in the same fashion. Its very basic, but works well for this situation.

Tile tileY = GetTileAt(Position.X, Position.Y + Velocity.Y);

if (tileY.IsOccupied)
{
    if (Velocity.Y >= 0) // Player is falling down
    {
        // Set position (feet) on top of the tile
        Position.Y = tileY.Y;
    }
    else
    {
        // Set position bellow the tile
        Position.Y = tileY.Y + TILE_HEIGHT + CHARACTER_HEIGHT;
    }
}

// Similar for X, but use the update Y position to fetch the tile
Tile tileX = GetTileAt(Position.X + Velocity.X, Position.Y);
if (tileX.IsOccupied)
{
    if (Velocity.X >= 0) // Player is going right
    {
        Position.X = tileX.X - (CHARACTER_WIDTH / 2);
    }
    else
    {
        Position.X = tileX.X + TILE_WIDTH + (CHARACTER_WIDTH / 2);
    }
}