6 Replies - 1469 Views - Last Post: 07 December 2013 - 03:23 PM

#1 Gmichael  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 25
  • Joined: 05-September 12

xna collision detection stop player movement

Posted 07 December 2013 - 09:03 AM

Hello so i have been working on recreating the game lolo for nes just for fun. No i have used a tile engine to create the level and i have also created my player my detection now for collision with the player works but im not to sure on how to just stop the player from moving at the position of collision and then move again once the key is pressed? any help would be appreciated here is my code for player, collision manager
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;


namespace TileEngine
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Player : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private SpriteBatch spritebatch;
        private Texture2D texture;
        private Vector2 position;

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }
        private Vector2 speed;

        public Vector2 Speed
        {
            get { return speed; }
            set { speed = value; }
        }
        private Vector2 frameDimension;

        public Vector2 FrameDimension
        {
            get { return frameDimension; }
            set { frameDimension = value; }
        }
        private List<Rectangle> frames;
        private int frameIndex = 0;
        private int faceState = 0;
        private int delay;
        private int delayCounter;
        private Vector2 stage;
       

        public Vector2 Stage
        {
            get { return stage; }
            set { stage = value; }
        }
       

        private int frameMod = 0;
        public int FrameMod
        {
            get { return frameMod; }
            set { frameMod = value; }
        }
        private int animationMod = 0;
        public int AnimationMod
        {
            get { return animationMod; }
            set { animationMod = value; }
        }

        public Player(Game game, SpriteBatch spritebatch, Texture2D texture, Vector2 position, int delay, Vector2 stage)
            : base(game)
        {
            // TODO: Construct any child components here
            this.spritebatch = spritebatch;
            this.texture = texture;
            this.position = position;
            this.delay = delay;
            this.stage = stage;
            speed = Vector2.One * 4;
            frameDimension = new Vector2(20, 20);
            
            createFrames();

        }

        private void createFrames()
        {
            frames = new List<Rectangle>();
             
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    int x = j * (int)frameDimension.X;
                    int y = i * (int)frameDimension.Y;
                    Rectangle r = new Rectangle(x, y, (int)frameDimension.X, (int)frameDimension.Y);
                    frames.Add(r);
                }
            }
        }

        /// <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)
        {
            // TODO: Add your update code here
            delayCounter++;
            if (delayCounter > delay)
            {
                frameIndex++;                
                if (frameIndex >= frameMod)
                {
                    switch (animationMod)
                    {
                        case 0:
                            frameIndex = faceState;
                            frameMod = 0;
                            break;
                        case 1:
                            frameIndex = 0;
                            frameMod = 7;
                            faceState = frameIndex;
                            break;
                        case 2:
                            frameIndex = 8;
                            frameMod = 15;
                            faceState = frameIndex;
                            break;
                        case 3:
                            frameIndex = 16;
                            frameMod = 23;
                            faceState = frameIndex;
                            break;
                        case 4:
                            frameIndex = 24;
                            frameMod = 31;
                            faceState = frameIndex;
                            break;
                    }
                }
                delayCounter = 0;
            }

            switch (animationMod)
            {
                case 0:
                    //speed = Vector2.Zero;
                    break;
                case 1:
                    position.Y += speed.Y;
                    break;
                case 2:
                    position.X += speed.X;
                    break;
                case 3:
                    position.X -= speed.X;
                    break;
                case 4:
                    position.Y -= speed.Y;
                    break;
            }

            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            spritebatch.Begin();
            spritebatch.Draw(texture, position, frames.ElementAt<Rectangle>(frameIndex), Color.White, 0f, new Vector2(0,0), 2f, SpriteEffects.None, 0f);
            spritebatch.End();
            base.Draw(gameTime);
        }
        public Rectangle getBoundaries()
        {
            return new Rectangle((int)position.X, (int)position.Y, texture.Width / 4, texture.Height / 3);
        }
    }
}


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;


namespace TileEngine
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class CollisionManager : Microsoft.Xna.Framework.GameComponent
    {
        Player player;
        Tile tile;

        public CollisionManager(Game game, Player player, Tile tile)
            : base(game)
        {
            this.player = player;
            this.tile = tile;
        }

        /// <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)
        {
            Rectangle playerRectangle = player.getBoundaries(); 
            List<Rectangle> tileRectangle = tile.getBoundaries();
            
            for (int i = 0; i < tileRectangle.Count; i++)
            {
                if (playerRectangle.Intersects(tileRectangle.ElementAt<Rectangle>(i)))
                {
                    player.Speed = Vector2.Zero;
                }
            }

            base.Update(gameTime);
        }
    }
}



Is This A Good Question/Topic? 0
  • +

Replies To: xna collision detection stop player movement

#2 Rhino1111  Icon User is offline

  • D.I.C Head

Reputation: 96
  • View blog
  • Posts: 216
  • Joined: 28-August 13

Re: xna collision detection stop player movement

Posted 07 December 2013 - 09:23 AM

I'm not sure I understand your question entirely, but basically any type of movement should just be a request. For example -->

Player presses right key
You ask if a movement to the right is possible (i,e no collision, not end of the map, etc)
If a movement is possible you shift the player position accordingly
If a movement isn't possible, don't shift the player position

What exact problems are you having with your collisions?
Was This Post Helpful? 0
  • +
  • -

#3 Gmichael  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 25
  • Joined: 05-September 12

Re: xna collision detection stop player movement

Posted 07 December 2013 - 09:35 AM

View PostRhino1111, on 07 December 2013 - 09:23 AM, said:

I'm not sure I understand your question entirely, but basically any type of movement should just be a request. For example -->

Player presses right key
You ask if a movement to the right is possible (i,e no collision, not end of the map, etc)
If a movement is possible you shift the player position accordingly
If a movement isn't possible, don't shift the player position

What exact problems are you having with your collisions?


My issue is when i collide with one of the tile i need to make him stop. everything i've tried so far has made him either skip, or slide across the tile. I'm having a hard time wrapping my brain around the logic im new to xna. the colission is working correctly when it collides with player ive tested it with just setting him to a Vector.Zero. What I want is to just have him stop and not sure how to go about it.
Was This Post Helpful? 0
  • +
  • -

#4 Rhino1111  Icon User is offline

  • D.I.C Head

Reputation: 96
  • View blog
  • Posts: 216
  • Joined: 28-August 13

Re: xna collision detection stop player movement

Posted 07 December 2013 - 09:57 AM

I dont have the time at the moment to read over the code and see where the actual problem is, but I can try to help with the concepts.

Before I continue, how is your movement set up? Usually in a tile based system, 1 keypress = 1 movement cycle to move an entire tile. (the movement cycle is usually done in several frames to make the transition from tile to tile smoother, and not just 1 large jump). Since movement is from tile to tile, and tiles hold collision information, this makes implementing collision detection much simpler.

Collision detection becomes slightly more complex if you've implemented free movement (i,e. Players move by pixels and aren't bound to tile by tile movement)

But basically, it sounds like you need to implement partial movement requests in your collision manager. Lets say your player is at 10,0. They press the right key which is a request to move 10 pixels to the right. But at 16,0 there is a collision. The collision manager would basically say "Hey, you requested to move 10 pixels to the right, but there's this thing here stopping you from moving that entire distance. I'll let you move 5 pixels to the right instead."

Then in your movement cycle, instead of moving 10 pixels, you would move 5 pixels. Hope that atleast makes some sense.
Was This Post Helpful? 0
  • +
  • -

#5 Gmichael  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 25
  • Joined: 05-September 12

Re: xna collision detection stop player movement

Posted 07 December 2013 - 12:10 PM

View PostRhino1111, on 07 December 2013 - 09:57 AM, said:

I dont have the time at the moment to read over the code and see where the actual problem is, but I can try to help with the concepts.

Before I continue, how is your movement set up? Usually in a tile based system, 1 keypress = 1 movement cycle to move an entire tile. (the movement cycle is usually done in several frames to make the transition from tile to tile smoother, and not just 1 large jump). Since movement is from tile to tile, and tiles hold collision information, this makes implementing collision detection much simpler.

Collision detection becomes slightly more complex if you've implemented free movement (i,e. Players move by pixels and aren't bound to tile by tile movement)

But basically, it sounds like you need to implement partial movement requests in your collision manager. Lets say your player is at 10,0. They press the right key which is a request to move 10 pixels to the right. But at 16,0 there is a collision. The collision manager would basically say "Hey, you requested to move 10 pixels to the right, but there's this thing here stopping you from moving that entire distance. I'll let you move 5 pixels to the right instead."

Then in your movement cycle, instead of moving 10 pixels, you would move 5 pixels. Hope that atleast makes some sense.

No actually kinda confused me I have an idea to explain better. There is a player that can walk around the screen. on key press he animates and moves in the desired direction. There is a frame around him of tiles each tile is 17x17. x's are the tiles and p is the player. when p moves to one of the x's i want him to stop and be able to walk the other way if that key is pressed. the collision manager handles the intersection. but not too sure on how to make him stop and wait for key press of next direction.
xxxxxxxxxxxxxxxxxx
x x
x x
x<-------p x
x x
x x
xxxxxxxxxxxxxxxxxx
Was This Post Helpful? 0
  • +
  • -

#6 Rhino1111  Icon User is offline

  • D.I.C Head

Reputation: 96
  • View blog
  • Posts: 216
  • Joined: 28-August 13

Re: xna collision detection stop player movement

Posted 07 December 2013 - 02:18 PM

Ok let me try to re-explain the concept.

Think about how you move a player. You basically shift their "position" values to simulate movement. Each key press moves the player a certain amount, in the desired direction.

I also assume you have a way to determine if a collision will occur or not(maybe collision data in your tile map). Now you just need to foreshadow. Each time there's a keypress, you make a request to the collision manager. The collision manager checks to see if you can make a full movement, a partial movement, or no movement at all (it will need to have access to whatever data you use to determine collisions, your players position, and however many pixels you move per keypress).

This way, you only ever move your player into map segments that are passable, and they "stop" / can't move into collision points.

It really isn't that complicated. If they hit the right arrow key, and you move 10 pixels every keypress, your collision manager just needs to check if all 10 pixels to the right of your players X position are passable. If they are all passable it grants you a full movement. If one of those locations has a collision, it grants you a partial movement. If your right beside a collision point, it grants no movement.

If you do a full tile movement every keypress, all you need to do is check if the tile in that direction is passable or not.
Was This Post Helpful? 1
  • +
  • -

#7 Gmichael  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 25
  • Joined: 05-September 12

Re: xna collision detection stop player movement

Posted 07 December 2013 - 03:23 PM

View PostRhino1111, on 07 December 2013 - 02:18 PM, said:

Ok let me try to re-explain the concept.

Think about how you move a player. You basically shift their "position" values to simulate movement. Each key press moves the player a certain amount, in the desired direction.

I also assume you have a way to determine if a collision will occur or not(maybe collision data in your tile map). Now you just need to foreshadow. Each time there's a keypress, you make a request to the collision manager. The collision manager checks to see if you can make a full movement, a partial movement, or no movement at all (it will need to have access to whatever data you use to determine collisions, your players position, and however many pixels you move per keypress).

This way, you only ever move your player into map segments that are passable, and they "stop" / can't move into collision points.

It really isn't that complicated. If they hit the right arrow key, and you move 10 pixels every keypress, your collision manager just needs to check if all 10 pixels to the right of your players X position are passable. If they are all passable it grants you a full movement. If one of those locations has a collision, it grants you a partial movement. If your right beside a collision point, it grants no movement.

If you do a full tile movement every keypress, all you need to do is check if the tile in that direction is passable or not.


sounds good i think that solved my idea. Thank you very much
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1