Tell me more ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So I'm trying to make an RTS-style line of sight fog of war style engine for my grid based game. Currently I am getting a set of vertices by raycasting in 360 degree. Then I use that list of vertices to do a graphics style polygon scanline fill to get a list of all points within the polygon. The I compare the new list of seen tiles and compare that with the old one and increment or decrement the world vision array as needed.

The polygon scanline function is giving me trouble. I'm mostly following this article.

So far this is my code without cleaning anything up:

var edgeMinX:Vector.<int> = new Vector.<int>;
var edgeMinY:Vector.<int> = new Vector.<int>;
var edgeMaxY:Vector.<int> = new Vector.<int>;
var edgeInvSlope:Vector.<Number> = new Vector.<Number>;
var ilen:int = outvert.length;
var miny:int = -1;
var maxy:int = -1;
for (i = 0; i < ilen; i++)
{
    var curpoint:Point = outvert[i];
    if (i == ilen -1)
    {
        var nextpoint:Point = outvert[0];
    }
    else
    {
        nextpoint = outvert[i + 1];
    }
    if (nextpoint.y == curpoint.y)
    {
        continue;
    }

    if (curpoint.y < nextpoint.y)
    {
        var curslope:Number = ((nextpoint.y - curpoint.y) / (nextpoint.x - curpoint.x));
        edgeMinY.push(curpoint.y);
        edgeMinX.push(curpoint.x);
        edgeMaxY.push(nextpoint.y);
        edgeInvSlope.push(1 / curslope);
        if (curpoint.y < miny || miny == -1)
        {
            miny = curpoint.y;
        }
        if (nextpoint.y > maxy)
        {
            maxy = nextpoint.y;
        }
    }
    else
    {
        curslope = ((curpoint.y - nextpoint.y) / (curpoint.x - nextpoint.x));
        edgeMinY.push(nextpoint.y);
        edgeMinX.push(nextpoint.x);
        edgeMaxY.push(curpoint.y);
        edgeInvSlope.push(1 / curslope);
        if (nextpoint.y < miny || miny == -1)
        {
            miny = curpoint.y;
        }
        if (curpoint.y > maxy)
        {
            maxy = nextpoint.y;
        }
    }

}

var activeMaxY:Vector.<int> = new Vector.<int>;
var activeCurX:Vector.<Number> = new Vector.<Number>;
var activeInvSlope:Vector.<Number> = new Vector.<Number>;

for (var scanline:int = miny; scanline < maxy + 1; scanline++)
{

    ilen = edgeMinY.length;
    for (i = 0; i < ilen; i++)
    {

        if (edgeMinY[i] == scanline)
        {
            activeMaxY.push(edgeMaxY[i]);
            activeCurX.push(edgeMinX[i]);
            activeInvSlope.push(edgeInvSlope[i]);

            //trace("added(" + edgeMinX[i]);
            edgeMaxY.splice(i, 1);
            edgeMinX.splice(i, 1);
            edgeMinY.splice(i, 1);
            edgeInvSlope.splice(i, 1);
            i--;
            ilen--;
        }
    }


    ilen = activeCurX.length;
    for (i = 0; i < ilen - 1; i++)
    {
        for (var j:int = i; j < ilen - 1; j++)
        {
            if (activeCurX[j] > activeCurX[j + 1])
            {
                var tempint:int = activeMaxY[j];
                activeMaxY[j] = activeMaxY[j + 1];
                activeMaxY[j + 1] = tempint;
                var tempnum:Number = activeCurX[j];
                activeCurX[j] = activeCurX[j + 1];
                activeCurX[j + 1] = tempnum;
                tempnum = activeInvSlope[j];
                activeInvSlope[j] = activeInvSlope[j + 1];
                activeInvSlope[j + 1] = tempnum;
            }
        }
    }

    var prevx:int = -1;
    var jlen:int = activeCurX.length;
    for (j = 0; j < jlen; j++)
    {
        if (prevx == -1)
        {
            prevx = activeCurX[j];
        }
        else
        {
            for (var k:int = prevx; k < activeCurX[j]; k++)
            {
                graphics.lineStyle(2, 0x124132);
                graphics.drawCircle(k * 20 + 10, scanline * 20 + 10, 5);

                if (k == prevx || k > activeCurX[j] - 1)
                {
                    graphics.lineStyle(3, 0x004132);
                    graphics.drawCircle(k * 20 + 10, scanline * 20 + 10, 2);
                }
                prevx = -1;
                //tileLightList.push(k, scanline);
            }
        }
    }

    ilen = activeCurX.length;
    for (i = 0; i < ilen; i++)
    {
        if (activeMaxY[i] == scanline + 1)
        {
            activeCurX.splice(i, 1);
            activeMaxY.splice(i, 1);
            activeInvSlope.splice(i, 1);
            i--;
            ilen--;
        }
        else
        {
            activeCurX[i] += activeInvSlope[i];
        }
    }
}

It works in some cases but some of the x intersections are skipped, primarily when there are more than 2 x intersections in one scanline I think.

Is there a way to fix this, or a better way to do what I described? Thanks

share|improve this question
What happened in edit, the code has been changed! GDSE is not codereview. Also, a valid question would be "how to create fog of war, where tile visibility is based on rays (cones) view." – Markus von Broady Oct 24 '12 at 17:56
FTFY, I've no idea why this massive edit happened... – Laurent Couvidou Oct 25 '12 at 18:07
1  
@FrickenHamster It's very unlikely that you will get help with such a massive block of code. Try to focus on a smaller part that would be digestible; I'll vote to close for the moment but I hope you'll get a chance to enhance this question. – Laurent Couvidou Oct 25 '12 at 18:09
Sincere apologies if the code block was damaged; it was an attempt to make it legible without otherwise editing it. – Seth Battin Oct 26 '12 at 2:09

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.