RTS style fog of war woes
Posted
by
Fricken Hamster
on Game Development
See other posts from Game Development
or by Fricken Hamster
Published on 2012-10-23T23:31:32Z
Indexed on
2012/10/24
5:28 UTC
Read the original article
Hit count: 240
So I'm trying to make a 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 http://www.cs.uic.edu/~jbell/CourseNotes/ComputerGraphics/PolygonFilling.html
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
© Game Development or respective owner