monster movement.. strange problem

Started by
5 comments, last by rakoon2 19 years, 7 months ago
Hello guys! I have some problems with my monster movement code! :3 The monsters shake their sprite all the time ( up, down, up down, up, down if it moves right! ( it should draw the right sprite) Here is my code:

bool CMonster::think( 
                       SDL_Surface* screen, boost::shared_ptr<CMap> map_col,
                       const int scroll_x, const int scroll_y,
                       const float dTime, const float player_x, const float player_y,
                       const int player_w, const int player_h
                    )
{
    
    
    velx = 0.0f;
    vely = 0.0f;
    int tilecoord;

    // found the player?
    if( foundPlayerX( player_x ) == true )
    {
        if( player_x > x )
        {
           velx =  (dTime*m_speed);
           face = Right;
        }      
        else if( player_x < x )
        {
           velx = -(dTime*m_speed);
           face = Left;
        }      
        else
           velx = 0.0f;
        
        if(velx > 0)
        {
            // test collision..
        }   			 
        else if(velx < 0)
        {
    		// test collision.. 	
     	}      
    }
    
    // found the player? 
    if( foundPlayerY( player_y ) == true )
    {     
        if( player_y > y )
        {
          vely =  (dTime*m_speed);
          face = Down;
        }      
        else if( player_y < y )
        {
          vely = -(dTime*m_speed);
          face = Up;
        }      
        else
        {
          vely = 0.0f;
        }      
         
        if(vely < 0)
        {
    		// test collision..
    	}		 
	else if( vely > 0 )
        {		
    		// test collision..   
        }       
    }  
        
    draw( screen, scroll_x, scroll_y );
    return false;
}    



// found functions:

bool CMonster::foundPlayerX( const float player_x )
{     
      const int seeRange( 100 );    
      if( ( player_x >= x ) && ( player_x <= (x + seeRange)) )
      { 
          return true;
      }
      else if( ( x >= player_x ) && ( x <= (player_x + seeRange)) )
      {
          return true;
      } 
      return false;                    
}

bool CMonster::foundPlayerY( const float player_y )
{     
      const int seeRange( 100 );    
      if( ( player_y >= y ) && ( player_y <= (y + seeRange)) )
      { 
          return true;
      }
      else if( ( y >= player_y ) && ( y <= (player_y + seeRange)) )
      {
          return true;
      } 
      return false;                    
}



draw

void CMonster::draw( 
                        SDL_Surface* screen,
                        const int scroll_x, const int scroll_y
         )
{
  if( face == Left )
     m_sprite[0]->draw( x - scroll_x, y - scroll_y, screen );
  else if( face == Right )
     m_sprite[1]->draw( x - scroll_x, y - scroll_y, screen );
  else if( face == Up )
     m_sprite[2]->draw( x - scroll_x, y - scroll_y, screen ); 
  else if( face == Down )
     m_sprite[3]->draw( x - scroll_x, y - scroll_y, screen );
  else
     LOG << "Wrong monster face: " << face << ENDL;     
}  



Any ideas? :3 :D Thank you very much..! :)
Advertisement
You're comparing floats with ==.

If you ever touch a float +,-,*,/ it will most likely not be exact the value you expect it to. This is due to float's inability to express certain values.

Don't check if x > and x < but check with a certain epsilon; like 0.001.

If your monsters x > player_x + 0.0001f move left,
else if your monsters x < player_x - 0.0001f move right,
else
do not move horizontally

You could also use fabsf to simplify the ifs to one:

if fabsf( monster_x - player_x ) < 0.0001f then move

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

The monster isn't exactly moving right. It's moving diagonally up-right and up-down, changing direction rapidly.

It first checks if it sees the player horizontally, and adjusts the face accordingly. Then it checks vertical sight, and because that is also in range, it adjusts the face again. The latter face is the one drawn, and it must be either up or down. To get a rightwards face, it'd need to be on the exact same y coordinate as the player, and that will almost never happen, as the coordinates aren't integers but floats. It then zigzags towards the player, looking up and down.

You should calculate the angle from the monster to the player, and choose a face depending on it. With only 4 possible faces, you don't even have to check the actual angle, just comparing delta_x and delta_y and their signs should give you the correct face.
Quote:Original post by Endurion
You're comparing floats with ==.


Where? :o You mean the >= ? So you think that is the problem?


Let me upload the game, so you guys can see what is wrong with my monsters.
http://members.chello.at/ennemoser/tloz%20the%20tower%204.01.627.rar
(newest build! I had to remake it!- so some old features are gone atm )

here is a screenshot:
http://members.chello.at/ennemoser/consolv4.jpg

Here is it! :) If you guys get strange errors, then please tell me what's in the logfile! :)



delta_x and delta_y

// this way ? 0o.. :3const float delta_x = player_x - monster_x;const float delta_y = player_y - monster_y;if( delta_x > 0 ){   face = Right;}else if( delta_x < 0 ){   face = Left;}if( delta_y > 0 ){   face = Down;}else if( delta_y < 0 ){   face = Up;}// HMM.. :)


it works fine if the monster moves up or down.. but still the same bug if it moves right or left! :/ well.. :p


when should I compare delta_x and y? help please!


same bug:
bool CMonster::think(                        SDL_Surface* screen, boost::shared_ptr<CMap> map_col,                       const int scroll_x, const int scroll_y,                       const float dTime, const float player_x, const float player_y,                       const int player_w, const int player_h                    ){            velx = 0.0f;    vely = 0.0f;    int tilecoord;               if( foundPlayerX( player_x ) == true )    {        if( player_x > x )        {          velx =  (dTime*m_speed);        }              else if( player_x < x )        {          velx = -(dTime*m_speed);        }              else          velx = 0.0000f;                if(velx > 0)        {            if( collision_ver(x+w, y, tilecoord, velx, map_col))            {    			 x = tilecoord*21 -w-1;		            }                 else            {    			 x += velx;            }  			         }   			         else if(velx < 0)        {    		if(collision_ver(x+velx, y, tilecoord, velx, map_col))    		{    			x = (tilecoord+1)*21 +1;            }    		    		else    		{    			x += velx;            }  			     	}       const float delta_x = player_x - x;      if( delta_x > 0 )      {         face = Right;      }      else if( delta_x < 0 )      {         face = Left;      }                    }    if( foundPlayerY( player_y ) == true )    {             if( player_y > y )        {          vely =  (dTime*m_speed);        }              else if( player_y < y )        {          vely = -(dTime*m_speed);        }              else        {          vely = 0.0000f;        }                       if(vely < 0)        {    		if( collision_hor( x, y+vely, tilecoord, map_col ))            {    				y = (tilecoord+1)*21 +1;            }    		else            {    		      y += vely;    		}    	}		 	    else if( vely > 0 )        {		    		if( collision_hor(x, y+vely+h, tilecoord, map_col) )            {                  y = tilecoord*21 -h-1;    		}    		else            {	    			   y += vely;    		}	    }                // change face        const float delta_y = player_y - y;             if( delta_y > 0 )        {           face = Down;        }        else if( delta_y < 0 )        {           face = Up;        }               }                                                     draw( screen, scroll_x, scroll_y );    return false;}             


[Edited by - rakoon2 on September 2, 2004 9:22:53 AM]
Ah, and i forgot the second reason:

Whenever you add vely to your monster position and the monster is just a tiny little bit below your player you are getting on the other side.

When the step of vely is BIGGER than the actual distance of to the player the monster gets set on the "other" side of the player. If its below first and vely is bigger then the distance it gets set above the player. In the next frame its vely will move the monster down and it'll be below the player again.

You need to work with some targetx and targety, and check if your current movement will move the monster over the targets position. If it will be moved too far, just set it back to the target pos.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Thank you! It works fine now! :)
here the newest build: http://members.chello.at/ennemoser/tloz%20the%20tower%204.01.627.rar

:)

This topic is closed to new replies.

Advertisement