Hi,

I am writing an FPS game in C++ using OpenGL. I am trying to write the crouch system but I want to make the crouch more smooth. At the moment you press the crouch key the character immediatly moves down. Here is the code:

Crouch Down:

entity[0].crouching = true;
entity[0].centre_height = PLAYER_HEIGHT / 5.0;
entity[0].height = PLAYER_HEIGHT / 2.5;
entity[0].gun_position.x = 0.0;
entity[0].gun_position.y = entity[0].height - 1.0;
entity[0].gun_position.z = 0.0;

Stand back up again:

entity[0].crouching = false;
entity[0].centre_height = PLAYER_HEIGHT / 2.0;
entity[0].height = PLAYER_HEIGHT;
entity[0].gun_position.x = 0.0;
entity[0].gun_position.y = entity[0].height - 1.0;
entity[0].gun_position.z = 0.0;

How can I make the crouch more gradual?

James

Recommended Answers

All 7 Replies

This question should be in games dev, but heres what i think ok.

Make a crouch animation function maybe something like this

void animateCrouch(double dt, bool crouchDir, entityType entity, entityIndexType entID ..other vars)
{
  if( true == crouchDir )//moving down is true
  { 
    /* calculate how far the entiy should have moved down in the 
       given time period and adjust thier position
     */
    entity[entID].centre_height -= (PLAYER_CROUCH_SPEED_SEC * dt);
    /* check we havent gone to far */
    if( (entity[entID].height/4) > entity[entID].centre_height ) 
    {
      /* they crouch to 1/2 height so center should be 1/4 height */
      entity[entID].centre_height = entity[entID].height/4;
    }
  }/* end if ( true == crouchDir ) */
  else /* player is moving up, do the opposite of crounching down */
  {
    /* code that mirrors moving down here */
  }
}

I just made this code up on the spot so it prob isnt just right but it should give you an idea i hope.

Good luck

If you are writing an FPS game, you are going to need some way of executing animations (i.e. things that move as a function of real-time), like for bullets, clouds, non-static objects, etc.. Once you integrate a means to do that, it shouldn't be a problem to implement a smooth crouching and standing (like a linear interpolation between the starting height (at starting time) to final height (at starting time + time for the animation), you can always make it more fancy, but this should do).

To integrate animations, I found that a very easy way to do it is to pass the current time (or delta-time) to the update() or render() functions of your visible objects (which I presume your first-person camera is, as it should be). You could have some interface or base-class to represent animations and some special code to deal with them, but I find that just passing a time parameter is the easiest (and more maintainable too). Static objects can just be rendered by ignoring this time parameter with minimal overhead, dynamic objects can be driven by the time parameter to create either animations or physical simulated motion, and user-controlled objects can use it when needed for some smooth transition animations.

Just interpolate between the starting height and the ending height. And you will get a smooth function. Afterwards, apply verlet integration for smooth transitioning. In short, just animate it crouching. But realize that crouching shouldn't take much cpu. So another suggestion is to have something like this :

void display(){
 //...
 if( KEY_DOWN_PRESSED && canCrouch){
    int steps  = 2;
    const int END_X_POS = 5;
    for(int i = 0; i < steps; ++i){
        crouch( END_X_POS/float(steps) );
        redisplayPlayer();
     }
 }
}
void crouch(const int delta){
 entity[0].crouching = true;
entity[0].centre_height = PLAYER_HEIGHT / delta;
entity[0].height = PLAYER_HEIGHT / (delta/2);
entity[0].gun_position.x = 0.0;
entity[0].gun_position.y = entity[0].height - 1.0;
entity[0].gun_position.z = 0.0;
}

so the idea in above is to have multiple crouch in between starting(0) and ending(5) and display its position. This is cheaper than original suggestion and probably shows decent result.

@First person, im curious about your code, surely your code prevents other animations and events during the animation which in a fps cant be allowed, as anything can happen at any moment the code im talking about is this

void display(){
//...
if( KEY_DOWN_PRESSED && canCrouch){
   int steps = 2;
   const int END_X_POS = 5;
   for(int i = 0; i < steps; ++i){ /* this animates the whole crouch in one go*/
      crouch( END_X_POS/float(steps) );
      redisplayPlayer();
   }
}

So during the crouch animation no other display elements will be drawn and the program is spinning in this loop, this is why i had suggested a function that does a little change per display fn call based on time (so varying display rates does not affect the look )

Am i wrong? or would that be a correct analysis, im not trying to be cheeky or rude or insulting im honestly curious.

Thanks
Kano

>>Am i wrong?

You are totally right. firstPerson's solution is not at all scalable. If you had more than one animation there would have to be a bunch of cases for each combination of simultaneous animations, or only one animation would run at a given time.

The only scalable solution is to reverse firstPerson's pattern, as you and I have suggested in our previous posts. In a simple object oriented design for a computer game, the rendering loop would look something like this:

void Game::Render() {
  double dt = /* calculate time since last frame */;

  ClearScreen(); //e.g. glClear(GL_COLOR_BUFFER | GL_DEPTH_BUFFER);

  //update the motion of camera and apply model-view and projection matrices. 
  mCamera->Render( dt ); 

  //iterate through visible objects and render them:
  for(std::vector<VisibleObject*>::iterator it = mObjList.begin(); it != mObjList.end(); ++it) 
    (*it)->Render( dt );

  SwapBuffer(hDC); //or similar.   
};

The above lets each object take care of tracking its own animation frames, this is scalable and decoupled, and thus, is the preferred option, instead of trying to manage all animations is some sort of centralized fashion, like firstPerson implied by his suggestion.

Sorry, I miswrote it then. I was suggesting what Kanosia said -- "change animation a in a stepwise manner each update call". Didn't mean to make it look like the way it did.

Hi,

In the end this is what I did:

In the sub of the game loop that checks for keypresses, when the crouch key is pressed entity is crouching and vice versa. Then once every frame crouch_check() is called. crouch_check() looks like this:

float frames = 0, frames2 = 0, frames3 = 0;


void crouch_check()
{
	 
	 

		if (entity[0].crouching)
		{  
			frames = frames + 0.5;
			frames2 = frames / 2;
			frames3 = frames / 5;

			if (frames < 5)
			{

				entity[0].centre_height = PLAYER_HEIGHT - frames;
				entity[0].height = PLAYER_HEIGHT - frames2;
				entity[0].gun_position.x = 0.0;
				entity[0].gun_position.y = entity[0].height - frames3;
				entity[0].gun_position.z = 0.0;
			}

		}
		else
		{
			frames = 0, frames2 = 0, frames3 = 0;

			frames = frames + 0.5;
			frames2 = frames / 2;
			frames3 = frames / 5;
			if (frames < 5 && entity[0].height < PLAYER_HEIGHT)
			{
	
			entity[0].centre_height = PLAYER_HEIGHT + frames;
			entity[0].height = entity[0].height + frames2;
			entity[0].gun_position.x = 0.0;
			entity[0].gun_position.y = entity[0].height + frames;
			entity[0].gun_position.z = 0.0;
			frames = 0, frames2 = 0, frames3 = 0;
	
			
			}
	}
}

I know it's not the best code but it does the trick.

Thanks,

James

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.