Sign in to follow this  
rakoon2

monster movement.. strange problem

Recommended Posts

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..! :)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.. :3
const 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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this