SDL Input not behaving as expected.

Started by
2 comments, last by Euden 7 years, 10 months ago

I'm currently developing a game using SDL and at the moment I have a character on the screen who's expected behaviour is:

1. to accelerate to the left when pressing left and slow down when left has been let go until he stops.

2. accelerate to the right when right is pressed and slow down when right has been let go until he stops.

3. if left and right are being pressed do nothing.

He does 1 and 2 partially, in the sense that he does not stop when the button is released and after pressing right after left, the buttons become reversed (left now moves him right and right now moves him left) he then behaves as expected (with the reversed buttons).

This says to me that something isn't being initialized correctly and once mapped the buttons work as expected.

(apologies for the bad explanation, it's hard to describe).

Game.cpp: http://pastebin.com/Ckj6sNaN

Player.cpp: http://pastebin.com/upv1BZNR

Input.cpp: http://pastebin.com/j9if5b0m

Any help clearing this up would be most appreciated, It's been bugging me for hours -_-

Advertisement

As far as I understand it, it looks like you've swapped the bodies of keyUpEvent and keyDownEvent.

Yes, as Kercyn says, your keyUpEvent and keyDownEvent are indeed swapped.

Also, just as an example, I'll post a different way you could do it.


void Player::update(int elapsed_time_ms)
{
    sprite->update(elapsed_time_ms);

    //OK, this 2 variables don't exist in your code (user_pressed_left and user_pressed_right), but they are
    //simply bools that are set, if the left or right keys are pressed.
      
      //EDIT: Here, there's no 'else' in the second 'if', because if the user is pressing both directional keys,
      //      the acceleration gained from both will cancel each other, and will behave as if no key is pressed.
      //Update acceleration based on user input
      if(user_pressed_left)
      acceleration_x_ -= kWalkingAcceleration * elapsed_time_ms;
      if(user_pressed_right)
      acceleration_x_ += kWalkingAcceleration * elapsed_time_ms;

      //Make sure that the acceleration doesn't exceed the maximum speed
      if(acceleration_x_ > kMaxSpeedX)
      acceleration_x_ = kMaxSpeedX;
      //Same goes for negative acceleration (moving left)
      //EDIT: Added 'else' here, because acceleration can only be either max positive or max negative
      else if(acceleration_x_ < -kMaxSpeedX)
      acceleration_x_ = -kMaxSpeedX;

    //Update player's position
    x_ += acceleration_x_;

      //Now, you can apply kSlowdownFactor (AKA friction).
      //The simplest way, is to check if the player has not pressed any direction buttons (or both),
      //and apply friction if so.
      if((!user_pressed_left && !user_pressed_right) ||  //No keys pressed
         ( user_pressed_left &&  user_pressed_left )   ) //Both keys pressed
      {

        //EDIT: If the acceleration is 0.0f, then the player is already stopped, so don't apply friction
        //      By the way, be careful with equal comparison of floating point numbers.
        if(acceleration_x_ == 0.0f)
        break;

        //If acceleration is negative, apply friction to get it closer to 0.0f
        if(acceleration_x_ < 0.0f)
        {
          //EDIT: If acceleration is bigger than friction, then just apply it
          if(acceleration_x_ < -kSlowdownFactor)
          acceleration_x_ += kSlowdownFactor;
          //EDIT: But if acceleration would become positive, then just set it to 0.0
          else
          acceleration = 0.0f;
        }

        //Same goes for positive acceleration
        //EDIT: Also added 'else' here.
        else if(acceleration_x_ > 0.0f)
        {
          //EDIT: If acceleration is bigger than friction, then just apply it
          if(acceleration_x_ > kSlowdownFactor)
          acceleration_x_ -= kSlowdownFactor;
          //EDIT: But if acceleration would become negative, then just set it to 0.0
          else
          acceleration = 0.0f;
?        }

      }
 
      //Keep player within screen bounds
      if(x_ < 0)
      x_ = 0;
      else if(x_ > 640)
      x_ = 600;
}

void Player::startMovingLeft()
{
    user_pressed_left = true;
}
 
void Player::startMovingRight()
{
    user_pressed_right = true;
}

void Player::stopMoving()
{
    //Do nothing
    return;
}

Note that you don't need the velocity variable this way

This code is untested, so sorry if there're any errors.

I hope the explanation is concise, but if it's not (or you have any doubt) hit me up, and I'll try to explain better,

Hope it helps.

EDIT: I forgot one thing, and that is to stop applying friction when the acceleration would become 0.0. The way it is now, the player would "wiggle" in place, due to the fact that acceleration keeps jumping from positive to negative.

Also added a few "else" to make the code a bit more efficient.

Sorry for the mistake.

Thank you both for your input on this! it solved it!

I really appreciate you taking the time to look at my question :)

Euden

This topic is closed to new replies.

Advertisement