Tuesday, 28 May 2013

Grid based 3D Line of sight algorithm

Grid based 3D Line of sight algorithm

I'm creating a grid based Tactical RPG game in XNA.
Image below kinda explains the idea. But if you've played Dwarf Fortress before, I'm basically trying to create that 3D line of sight and you can ignore my explanation.
http://i.imgur.com/EhIPglh.png
(Also I don't care about how efficient the algorithm is at this time.)
Currently I am drawing a Bresenham line to each square within a radius, and each square I visit I check in the direction I am headed if I run into any walls.
The code below is my check for if a position is visible. sx, sy, sz is the change in the grid. For instance, if the line is traveling north east, sx = 1, sy = -1, sz = 0. if I'm headed straight up it would be sx=0, sy = 0, sz = 1; etc.
    private bool IsVisible(APoint Cur, int sx, int sy, int sz)
    {
        bool Visible = true;
        if (ValidCoordinates(Cur))
        {
            int newsx = -1;
            int newsy = -1;
            int newsz = -1;
            switch (sx)
            {
                case -1:
                    newsx = 3; //west
                    break;
                case 0:
                    newsx = -1;
                    break;
                case 1:
                    newsx = 1; //east
                    break;
            }

            switch (sy)
            {
                case -1:
                    newsy = 0;// north
                    break;
                case 0:
                    newsy = -1;
                    break;
                case 1:
                    newsy = 2; //south
                    break;
            }

            switch (sz)
            {
                case -1:
                    newsz = 4; // down
                    break;
                case 0:
                    newsz = -1;
                    break;
                case 1:
                    newsz = 5; // up
                    break;
            }
            if (ValidCoordinates(Cur.X + sx, Cur.Y + sy, Cur.Z + sz))
            {
                if (newsx != -1 && newsy == -1 && newsz == -1) // X only.
                {
                    if (TileArray[Cur.X + sx, Cur.Y + sy, Cur.Z + sz].AllowSight(newsx))
                        Visible = true;
                    else
                        Visible = false;
                }

                if (newsx == -1 && newsy != -1 && newsz == -1) // Y only.
                {
                    if (TileArray[Cur.X + sx, Cur.Y + sy, Cur.Z + sz].AllowSight(newsy))
                        Visible = true;
                    else
                        Visible = false;
                }

                if (newsx != -1 && newsy != -1 && newsz == -1) // X and Y only
                {
                    if (Visible && TileArray[Cur.X + sx, Cur.Y + sy, Cur.Z + sz].AllowSight(newsx))
                        Visible = true;
                    else
                        Visible = false;

                    if (Visible && TileArray[Cur.X + sx, Cur.Y + sy, Cur.Z + sz].AllowSight(newsy))
                        Visible = true;
                    else
                        Visible = false;
                }

            }
            return Visible;
        }
        return false;
    }
The Allow

No comments:

Post a Comment