碰撞检测,带有地图块的播放器

Collision Detection, Player with tiles of the map

我如何用我的播放器与地图上的方块发生碰撞?

动画class:

public class Animation
{

    public float speed = 2.5f;
    protected string currentAnimatie;

    public Texture2D sTexture;
    public Vector2 sPosition;

    private int FrameIndex; 
    private double TimeElapse;
    private double TimeToUpdate;

    public Vector2 sDirection = Vector2.Zero;


    public Rectangle BoxRondCharachter
    {
        get
        {
            return new Rectangle((int)sPosition.X, (int)sPosition.Y, 50, 41);
        }
    }

    public int FramesPerSec
    {
        set { TimeToUpdate = (1f / value); }
    }

    public Animation(Vector2 pos)
    {
        sPosition = pos;
    }

    public void Update(GameTime gametime)
    {
        TimeElapse += gametime.ElapsedGameTime.TotalSeconds;

        if (TimeElapse > TimeToUpdate)
        {
            TimeElapse -= TimeToUpdate;

            if (FrameIndex < sAnimatie[currentAnimatie].Length - 1)
            {
                FrameIndex++;
            }
            else
            {
                FrameIndex = 0;
            }
            TimeElapse = 0;
        }

        sPosition += sDirection;
        sDirection = Vector2.Zero;
    }

    public void AddAnimatie(int frames, double yPos, int xStart, string naam, int width, int height, Vector2 offset)
    {

        Rectangle[] Rectangles = new Rectangle[frames];

        ///neemt de spritesheet en het verdeelt zich
        for (int i = 0; i < frames; i++)
        {
            Rectangles[i] = new Rectangle((i + xStart) * width, (int)yPos, width, height);
        }

        sAnimatie.Add(naam, Rectangles);
    }

    public void Draw(SpriteBatch sprite)
    {
        sprite.Draw(sTexture, sPosition, sAnimatie[currentAnimatie [FrameIndex], Color.White);
    }

    public void AnimatieAfspelen(string animatieNaam)
    {
        if (currentAnimatie != animatieNaam)
        {
            currentAnimatie = animatieNaam;
            FrameIndex = 0;

        }
    }

    public void LaadContent(ContentManager content)
    {
        sTexture = content.Load<Texture2D>("char");
    }
}

地图引擎Class:

class MapEngine
{
    private List<CollisionTiles> collisionTiles = new List<CollisionTiles>();

    public List<CollisionTiles> CollisionTiles
    {
        get { return collisionTiles; }
    }

    private int width, height;
    public int Width
    {
        get { return width; }
    }

    public int Height
    {
        get { return height; }
    }

    public MapEngine()
    {

    }


    public void Generate(int[,] map, int size)
    {
        for (int x = 0; x < map.GetLength(1); x++)
        {
            for (int y = 0; y < map.GetLength(0); y++)
            {
                int number = map[y, x];

                if (number > 0)
                {
                    collisionTiles.Add(new CollisionTiles(number, new Rectangle(x * size, y * size, size, size)));

                    width = (x + 1) * size;
                    height = (y + 1) * size;
                }
            }
        }
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        foreach (CollisionTiles tile in collisionTiles)
        {
            tile.Draw(spriteBatch);
        }
    }
}

地图class:

class Map : MapEngine
{

    public void ShowMap(ContentManager Content)
    {
        Tiles.Content = Content;

        Generate(new int[,]{
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
            {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,},
            {2,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,2,2,},
            {2,2,1,1,1,0,0,0,0,1,1,1,2,2,2,1,0,0,0,0,2,2,},
            {2,2,0,0,0,0,0,0,1,2,2,2,2,2,2,2,1,0,0,0,2,2,},
            {2,0,0,0,0,0,1,1,2,2,2,2,2,2,2,2,2,1,1,1,2,2,},
            {2,0,0,0,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,},
            {2,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,}
        }, 74);
    }
}

英雄class:

public class Hero
{
    private Vector2 position = new Vector2(54, 485);
    public Vector2 Position
    {
        get { return position; }
    }

    public int Width { get; set; }
    public int Height { get; set; }

    private Animation _animation;
    private Inputs inputH = new Inputs();

    public bool LinkseStand = false;

    private Rectangle collisionRectangle;
    public Rectangle CollisionRectangle
    {
        get => collisionRectangle;
        set => collisionRectangle = value;
    }


    public Hero()
    {
        _animation = new Animation(position);

        _animation.AddAnimatie(4, 0, 0, "RechteIdle", 50, 35, new Vector2(0, 0));
        _animation.AddAnimatie(4, 34, 0, "LinkseIdle", 50, 35, new Vector2(0, 0));
        _animation.AddAnimatie(6, 72, 0, "Right", 50, 34, new Vector2(0, 0));
        _animation.AddAnimatie(6, 107, 0, "Left", 50, 40, new Vector2(0, 0));
        _animation.AddAnimatie(9, 144, 0, "Jump", 46, 41, new Vector2(0, 0));
        _animation.AddAnimatie(4, 220, 0, "Crouch", 50, 32, new Vector2(0, 0));
        _animation.AddAnimatie(7, 255, 0, "FirstAttack", 50, 45, new Vector2(0, 0));
        _animation.AddAnimatie(14, 300, 0, "ComboAttack", 50, 41, new Vector2(0, 0));
        _animation.AddAnimatie(5, 300, 0, "Dood", 50, 41, new Vector2(0, 0));

        _animation.AnimatieAfspelen("RechteIdle");

        _animation.FramesPerSec = 8;
    }

    public void Draw(SpriteBatch spritebatch)
    {
        _animation.Draw(spritebatch);
    }

    public void laadContent(ContentManager content)
    {
        _animation.LaadContent(content);
    }

    public void Update(GameTime gameTime)
    {
        _animation.Update(gameTime);

        position += _animation.sDirection;
        CollisionRectangle = new Rectangle((int)_animation.sPosition.X, (int)_animation.sPosition.Y, 50, 41);


        inputH.update();
        Move(gameTime);

    }

    private void Move(GameTime gameTime)
    {
        if (inputH.Right)
        {
            _animation.AnimatieAfspelen("Right");
            _animation.sDirection.X = _animation.speed;

            LinkseStand = false;
        }
        else if (inputH.Left)
        {
            _animation.AnimatieAfspelen("Left");
            _animation.sDirection.X -= _animation.speed;

            LinkseStand = true;
        }
        else if (inputH.Up)
        {
            _animation.AnimatieAfspelen("Jump");

            _animation.sDirection.Y -= _animation.speed;
        }
        else if (inputH.NormalAttack)
        {
            _animation.AnimatieAfspelen("FirstAttack");
        }
        else if (inputH.ComboAttack)
        {
            _animation.AnimatieAfspelen("ComboAttack");
        }
        else
        {
            if (LinkseStand == true)
                _animation.AnimatieAfspelen("LinkseIdle");
            else
                _animation.AnimatieAfspelen("RechteIdle");
        }
    }
}

碰撞方块class:

class CollisionTiles : Tiles
{
    public CollisionTiles(int i, Rectangle newRect)
    {
        texture = Content.Load<Texture2D>("Tile" + i); //loads the tile (tile1, tile2)
        Rectangle = newRect;
    }
}

游戏 1 class:

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D background;
    Vector2 backPos;

    Animation _ani;
    Hero _hero;

    Map map;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        graphics.PreferredBackBufferWidth = 1000;  // set this value to the desired width of your window
        graphics.PreferredBackBufferHeight = 590;   // set this value to the desired height of your window
        graphics.ApplyChanges();
        Content.RootDirectory = "Content";
    }

    /// <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

        map = new Map();
        _hero = new Hero();
        _ani = new Animation(_hero.Position);
        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);

        background = Content.Load<Texture2D>("background1");
        backPos = new Vector2(0, 0);

        map.ShowMap(Content);

            //_heroTexture = Content.Load<Texture2D>("idleStand");
            _hero.laadContent(Content);
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// game-specific 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)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        _hero.Update(gameTime);

        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.Cyan);

        // TODO: Add your drawing code here
        spriteBatch.Begin();

        spriteBatch.Draw(background, backPos, Color.White);

        map.Draw(spriteBatch);
        _hero.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }
}

可以在Game1的Update方法中将Map实例传给Hero:

    _hero.Update(gameTime, map);

并使用它来遍历 map.CollisionTiles 列表,检查 Hero class:

中的重叠
public void Update(GameTime gameTime, Map map)
{
    _animation.Update(gameTime);

    position += _animation.sDirection;
    CollisionRectangle = new Rectangle((int)_animation.sPosition.X, (int)_animation.sPosition.Y, 50, 41);

    // Check for collision with any of the CollisionTiles:
    foreach(var item in map.CollisionTiles)
        if(item.Rectangle.Intersects(CollisionRectangle))
//              ^^^^^^^^^ needs to be public in the tile class.
        {
            position -= _animation.sDirection; // Collided with a tile undo move
            break;    //prevent moving backwards if colliding with more than one tile
        }

    inputH.update();
    Move(gameTime);

}

在此代码中,Hero 无法移动到任何 CollisionTile。