Thread: Problems with vision cone

  1. #1
    Registered User
    Join Date
    Oct 2007
    Location
    Norway
    Posts
    16

    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.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    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. )
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Volume of a Cone Equation always equals 0
    By Devolution in forum C Programming
    Replies: 11
    Last Post: 01-28-2009, 03:13 AM
  2. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  3. C Pointers Problems
    By mhelal in forum C Programming
    Replies: 8
    Last Post: 01-10-2007, 06:35 AM
  4. contest problems on my site
    By DavidP in forum Contests Board
    Replies: 4
    Last Post: 01-10-2004, 09:19 PM
  5. DJGPP problems
    By stormswift in forum C Programming
    Replies: 2
    Last Post: 02-26-2002, 04:35 PM