I'm making a game where the enemies' vision is represented by a circle segment. I decided to split up the circle segment in line segments and then check if the lines collide with any walls and rebuild the circle segment using that info. That way he should be unable to look through walls.
However the code I have now doesn't fully work, and he sometimes looks through walls. I've looked through it countless times now and I just can't find the error.
Here is an image showing the problem.
And the code I have now:
Code:
float floatmod( float x, float y )
{
return x - (int(x / y) * y);
}
/* x1 and y1 is the start point of the line segment
x2 and y2 is the end point of the line segment
returns the length of the new line segment
the function is supposed to find how far away it is from the next tile and then move there,
and see if there's a wall there. It repeats this until it
1) finds a wall,
2) reaches the end of the line segment
3) leaves the map.
*/
float lineMapCollision( float x1, float y1, float x2, float y2 )
{
float dx = x2-x1 + 0.000001, // length of the line on x axis, with some division by 0 protection
dy = y2-y1 + 0.000001,
length = sqrt( dx*dx + dy*dy ), // length of the line
curlength = 0,
solvex, // stores how far away from the next tile we are on the x axis
solvey,
tx,
ty;
while( curlength < length )
{
if( dx > 0 ) // If the line moves left to right
{
// floatmod(x1,16) is how far into the tile we are,
// we subtract this from the tile size (16) to find how much further we need to move
solvex = (16 - (floatmod(x1,16)));
if( float_equal( solvex, 0 ) )
solvex = 16;
}
else
{
solvex = -(floatmod(x1,16));
if( float_equal( solvex, 0 ) )
solvex = -16;
}
if( dy > 0 )
{
solvey = (16 - (floatmod(y1,16)));
if( float_equal( solvey, 0 ) )
solvey = 16;
}
else
{
solvey = -(floatmod(y1,16));
if( float_equal( solvey, 0 ) )
solvey = -16;
}
tx = solvex/dx; // How far it needs to move divided by how far it moves
ty = solvey/dy;
if( fabs(tx) < fabs(ty) ) // the axis with the smallest value will reach a new tile first
{
x1 += tx*dx;
y1 += tx*dy;
curlength += sqrt( tx*tx*(dx*dx + dy*dy) ); // sqrt( pow( tx*dx, 2 ) + pow( tx*dy, 2 ) )
}
else
{
x1 += ty*dx;
y1 += ty*dy;
curlength += sqrt( ty*ty*(dx*dx + dy*dy) );
}
// If we are outside the map; stop
if( UINT(x1/16) < 0 || UINT(x1/16) >= MAP_WIDTH )
break;
if( UINT(y1/16) < 0 || UINT(y1/16) >= MAP_HEIGHT )
break;
//if there is a wall here
if( mapdata[UINT(x1/16)+UINT(y1/16)*MAP_WIDTH] == false )
{
if( fabs(tx) < fabs(ty) )
{
if( dx < 0 ) // if we were moving right to left, we are at the wrong side of the tile
curlength -= sqrt( tx*tx*(dx*dx + dy*dy) );
}
else
{
if( dy < 0 )
curlength -= sqrt( ty*ty*(dx*dx + dy*dy) );
}
return curlength;
}
}
return length;
}
And the function that draws the cone using the info it gets from the previous function, however I don't think the error is here.
Code:
void visionCone( float x, float y, float r, float rot, float susp )
{
float lengths[21], xd[21], yd[21];
glBindTexture( GL_TEXTURE_2D, whitetex );
glEnable( GL_BLEND );
glBegin( GL_TRIANGLES );
for( UINT i = 0; i < 21; i++ )
{
xd[i] = cos(float(i)*M_PI/60+rot);
yd[i] = sin(float(i)*M_PI/60+rot);
lengths[i] = lineMapCollision( x, y, x+xd[i]*r, y+yd[i]*r );
}
for( UINT i = 0; i < 20; i++ )
{
glColor4f( susp/50, 2-susp/50, 0, 1 );
glTexCoord2f( 0, 0 ); glVertex2f( x+xd[i]*lengths[i], y+yd[i]*lengths[i] );
glTexCoord2f( 1, 0 ); glVertex2f( x+xd[i+1]*lengths[i+1], y+yd[i+1]*lengths[i+1] );
glTexCoord2f( 0, 1 ); glVertex2f( x, y );
}
glEnd();
glDisable( GL_BLEND );
}
Any help would be appreciated.