bilal ali8
bilal ali8

Reputation: 1

Isometric collision detection error in Monogame

So, I have this problem where the collision does not work properly. I tried many techniques. The red tiles were supposed to show the collision with the green tile. The problem is when I try to convert the isometric coordinates into normal coordinates, something goes wrong. The public Vector2 Rematrixlogic converts isometric logic to normal axis. The void checkCollision checks if a tile is colliding with the player. To achieve this, I use a rectangle to check; However, it used the diamond check method but it fails. I don't know if I used the wrong formula or wrong method. When a tile collides with the player (which is a green tile), the tiles should turn red. However, most tiles turn red even though they are not colliding. Click this link to see the results when I run the program.

This is my code:

public class Game1 : Game
{
    private GraphicsDeviceManager _graphics;
    private SpriteBatch _spriteBatch;

    List<Tile> tiles = new List<Tile>();

    Texture2D TestImage;
    SpriteFont Defaultext;
    Texture2D Image1;
    Texture2D Image2;
    Texture2D Image3;
    string message = "None";
    int MoveX = 0;
    int Movey = 0;
    float Scale = 0;
    Player player;
    Tile testtile;

    public Game1()
    {
        _graphics = new GraphicsDeviceManager(this);
        _graphics.PreferredBackBufferWidth = 1200;
        _graphics.PreferredBackBufferHeight = 700;
        Content.RootDirectory = "Content";

        IsMouseVisible = true;
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        _spriteBatch = new SpriteBatch(GraphicsDevice);
        TestImage = Content.Load<Texture2D>("spritesheet");
        Image1 = Content.Load<Texture2D>("tile_000");
        Defaultext = Content.Load<SpriteFont>("File");
        Image2 = Content.Load<Texture2D>("tile_101");
        Image3 = Content.Load<Texture2D>("tile_022");
        ReadMap("..\\..\\..\\TestNotcsv.txt", 1);

        testtile = new Tile(Image1, MatrixLofic(1, 1, 50, -50), 1);
        player = new Player(Image1, new Vector2(20, 20), new Vector2(0, 0), 1);

        ReadMap("..\\..\\..\\1.txt", 2);
        tiles.Add(testtile);
        testtile.tilecole = Color.Blue;
    }

    protected override void Update(GameTime gameTime)
    {
        ArrowFunction();
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        for (int i = 0; i < tiles.Count; i++)
        {
            tiles[i].update(MoveX, Movey);
            Checkcollsion(tiles[i]._pos, tiles[i]);
        }

        player.Update();
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        _spriteBatch.Begin();

        drawoder();
        _spriteBatch.DrawString(Defaultext, message, new Vector2(0, 0), Color.Red);
        _spriteBatch.End();

        base.Draw(gameTime);
    }

    public Vector2 MatrixLofic(float w, float h, float _x, float _y)
    {
        float x = ((float)_x * (0.5f * (float)w)) + ((float)_y * (-0.5f * (float)w));
        float y = ((float)_x * (0.25f * (float)h)) + ((float)_y * (0.25f * (float)h));
        x += 128f * 1.5f;

        Vector2 final = new Vector2(x, y);
        return final;
    }

    public Vector2 Rematrixlogic(float tileWidth, float tileHeight, float cartX, float cartY)
    {
        cartX = (cartX - cartY) * 0.5f * tileWidth;
        cartY = (cartX + cartY) * 0.25f * tileHeight;
        cartX = 128f * 1.5f;
        return new Vector2(cartX, cartY);
    }

    public Vector2 MatricLogic2(int x, int y)
    {
        var _x = (x * 32 / 2) - (x * 32 / 2);
        var _y = (y * 16 / 2) + (y * 16 / 2);
        Vector2 n = new Vector2(_x, _y);
        return n;
    }

    public void MoveTiles()
    {
        KeyboardState key = Keyboard.GetState();
        if (Keyboard.GetState().IsKeyDown(Keys.W))
        {
            Movey = 1;
        }
        else if (Keyboard.GetState().IsKeyDown(Keys.S))
        {
            Movey = -1;
        }
        else
        {
            Movey = 0;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.D))
        {
            MoveX = -1;
        }
        else if (Keyboard.GetState().IsKeyDown(Keys.A))
        {
            MoveX = 1;
        }
        else
        {
            MoveX = 0;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.R))
        {
            MoveX = 0;
            Movey = 0;
            DeletaAlltile();
            ReadMap("..\\..\\..\\TestNotcsv.txt", 1);
            ReadMap("..\\..\\..\\1.txt", 2);
        }
    }
    public void DeletaAlltile()
    {
        for (int i = 0; i < tiles.Count; i++)
        {
            tiles.Remove(tiles[i]);
        }
    }

    void drawoder()
    {
        bool once = true;
        for (int i = 0; i < tiles.Count; i++)
        {
            if (tiles[i].depth <= player.depth)
            {
                tiles[i].draw(_spriteBatch);
            }

            else if (tiles[i].depth > player.depth && once == true)
            {
                player.draw(_spriteBatch);
                once = false;
            }

            else if (tiles[i].depth > player.depth && once == false)
            {
                tiles[i].draw(_spriteBatch);
            }
        }
    }

    bool IsPointInDiamond(Vector2 point, Vector2 center, float halfWidth, float halfHeight)
    {
        // Calculate the diamond's boundaries based on its center and size
        return (Math.Abs(point.X - center.X) / halfWidth + Math.Abs(point.Y - center.Y) / halfHeight) <= 1;
    }

    void Checkcollsion(Vector2 pos, Tile tile1)
    {
        Vector2 tiles1 = Rematrixlogic(1, 1, pos.X, pos.Y);
        Vector2 playercheck = Rematrixlogic(1, 1, player.Position.X, player.Position.Y);

        if (IsPointInDiamond(playercheck, new Vector2(tiles1.X, tiles1.Y), 32, 32))
        {
            tile1.tilecole = Color.Red;
        }
        else
        {
            tile1.tilecole = Color.White;
        }
    }
    public void ArrowFunction()
    {
        if (Keyboard.GetState().IsKeyDown(Keys.Up))
        {
            Scale = 1;
        }
        else if (Keyboard.GetState().IsKeyDown(Keys.Down))
        {
            Scale = -1.2f;
        }
        else
        {
            Scale = 0;
        }
    }

    public void ReadMap(string Path, int depth)
    {
        StreamReader reader = new StreamReader(File.OpenRead(Path));
        List<string> listA = new List<string>();
        int x = 0;
        int y = 0;

        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var values = line.Split(',');
            foreach (var item in values)
            {
                if (item == "1")
                {
                    tiles.Add(new Tile(Image1, MatrixLofic(1, 1, x, y), depth));
                }

                if (item == "2")
                {
                    tiles.Add(new Tile(Image2, MatrixLofic(1, 1, x, y), depth));
                }

                if (item == "3")
                {
                    tiles.Add(new Tile(Image3, MatrixLofic(1, 1, x, y), depth));
                }

                x += 32;
            }

            x = 0;
            y += 32;
        }
    }
}

And this is my player code. The matrix logic converts axis in the isometric axis (grid). IsPointInDiamond is a technique where I tried to detect if the player (green tile) is colliding with tiles.

internal class Player
{
    Texture2D texture;
    public Vector2 Position;
    Vector2 Rotation;
    float pos_x;
    float pos_y;
    Vector2 loadpos;
    float speed = 3f;
    public int depth;
    public Player(Texture2D _texture, Vector2 _pos, Vector2 _rotation, int _depth)
    {
        texture = _texture;
        Position = _pos;
        _rotation = Rotation;

        pos_x = _pos.X;
        pos_y = _pos.Y;
        loadpos = new Vector2(_pos.X, _pos.Y);
        depth = _depth;
    }

    public void draw(SpriteBatch sp)
    {
        sp.Draw(texture, Position, null, Color.Green, 0, Rotation, 1, SpriteEffects.None, 0);
    }

    public Vector2 MatrixLofic(float w, float h, float _x, float _y)
    {
        float x = ((float)_x * (0.5f * (float)w)) + ((float)_y * (-0.5f * (float)w));
        float y = ((float)_x * (0.25f * (float)h)) + ((float)_y * (0.25f * (float)h));
        x += 128f * 1.5f;

        Vector2 final = new Vector2(x, y);
        return final;
    }

    public void Move()
    {
        if (Keyboard.GetState().IsKeyDown(Keys.W))
        {
            loadpos += new Vector2(-1, -1) * speed;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.S))
        {
            loadpos += new Vector2(1, 1) * speed;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.D))
        {
            loadpos += new Vector2(1, -1) * speed;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.A))
        {
            loadpos += new Vector2(-1, 1) * speed;
        }
    }

    public void Update()
    {
        Move();
        Position = loadpos;
        Position = MatrixLofic(1, 1, loadpos.X, loadpos.Y);
    }
}

Please, I need help.

I tried many collision techniques, however, all of them were not working properly. I tried correct isometric grid calculation but nothing worked.

Upvotes: 0

Views: 30

Answers (0)

Related Questions