# Problems with vision cone

• 07-02-2008
Waterbottle
Problems with vision cone
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.
• 07-02-2008
dwks
I didn't really have a very close look at your code, but it seems to me that these two blocks aren't doing the same thing. One uses 16-x, the other, x.
Code:

```        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;         }```
I'm sure I'm just missing something about it . . . .

Other thoughts:
• floatmod() looks rather similar to fmod(), a standard C and C++ function.
• Code:

`sqrt( dx*dx + dy*dy )`
Consider the C99 and C++ function hypot(). It has less of a chance of overflowing.
• floatmod(), float_equal(): consider using consistent naming schemes (i.e., always have underscores between words) to prevent yourself from becoming too confused. (I never adhere to this myself. :p)