2
\$\begingroup\$

I want my character to move smooth not instant stopping etc. I want it to decrease velocity slower not instant. I tried with keystates but that doesn't work for 2 keys at once. I tried using key.keysym.sym in switch to set bools: left, right, up, down if key is held but that does not work too when 2 keys are held. Now I am using this

void CharProp::handleEvent(SDL_Event e)
{
    if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
    {
        switch (e.key.keysym.sym)
        {
        //case SDLK_w:
        case SDLK_UP:
            cVelY -= CharVel;
            break;
        //case SDLK_s:
        case SDLK_DOWN:
            cVelY += CharVel;
            break;
        //case SDLK_a:
        case SDLK_LEFT:
            cVelX -= CharVel;
            break;
        //case SDLK_d:
        case SDLK_RIGHT:
            cVelX += CharVel;
            break;
        }
    }
    else if (e.type == SDL_KEYUP && e.key.repeat == 0)
    {
        switch (e.key.keysym.sym)
        {
            //case SDLK_w:
        case SDLK_UP:

            cVelY = 0;
            break;
            //case SDLK_s:
        case SDLK_DOWN:

            cVelY = 0;
            break;
            //case SDLK_a:
        case SDLK_LEFT:

            cVelX = 0;
            break;
            //case SDLK_d:
        case SDLK_RIGHT:

            cVelX = 0;
            break;
        }
    }
}

This works with multiple keys but I cannot figure out how to make increasing/decreasing velocity. Do you have any tips how to make it using SDL2?

EDIT: Code for decelerating looks like this

if (!accelerationX)
{
    if (cVelX > 0)cVelX -= 0.5;
    if (cVelX < 0)cVelX += 0.5;
}

Now when character is decelerating it can move through walls because I am subtracting 0.5. I want it to decelerate slow so I don't know what to do( If I changed it to subtract 1 it would work good)Any ideas how to do it?

\$\endgroup\$
7
\$\begingroup\$

To create smooth movement you need 4 things:

  • The position of the character
  • The velocity of the character
  • The acceleration of the character
  • The max speed of the character

When the user presses the movement keys you need to set the acceleration of the player to the movement acceleration.

When the user releases the key you need to set the acceleration to 0.

When you update the character you need to add the acceleration to the velocity and then add the velocity to the position of the character.

Also, everytime you update you need to check if the velocity is bigger than the max speed of the character and if it is, then set it back.

\$\endgroup\$
  • \$\begingroup\$ Should I add acceleration or multiply acceleration? \$\endgroup\$ – Arek Żyłkowski Aug 9 '16 at 19:07
  • \$\begingroup\$ At which part do you mean? \$\endgroup\$ – Bálint Aug 9 '16 at 19:07
  • \$\begingroup\$ When user is holding key should it look like this? velocityX += acceleration \$\endgroup\$ – Arek Żyłkowski Aug 9 '16 at 19:12
  • 2
    \$\begingroup\$ You'll also need deceleration to simulate friction when the user releases the key, otherwise the character will never stop. \$\endgroup\$ – BeanBag Aug 9 '16 at 19:45
  • 2
    \$\begingroup\$ @Bálint In your answer you set the acceleration to 0, which would mean the velocity would remain constant. And in the above comment you would just lower acceleration meaning the character will keep on accelerating. When the user isn't holding down the key you must lower the velocity over time by reducing its magnitude each tick, such that velocity eventually becomes 0. \$\endgroup\$ – BeanBag Aug 9 '16 at 20:06
0
\$\begingroup\$
/** I think directly changing the velocity inside the key-listener is 
  * not a good idea. You can store which key is pressed inside variables. 
  */
var game = {
    leftDown: false,
    rightDown: false,

    keyUpListener: function(event) {
        if(event.keyCode === leftKeyCode) {
            leftDown = false;
        }
        if(event.keyCode === rightKeyCode) {
            rightDown = false;
        }
    },

    keyDownListener: function(event) {
        if(event.keyCode === leftKeyCode) {
            leftDown = true;
        }
        if(event.keyCode === rightKeyCode) {
            rightDown = true;
        }
    },

/** you can pass which those variables inside the required objects, in this case, 
  * the player. It would be much cleaner that way and you also won't have the 
  * keypress delay/repeat problem which is different in different operating systems. 
  */
    update: function(delta) {
        player.update(delta, leftDown, rightDown);
    }
};

/* You wan't the player to not instantly start or stop running. To do that, you
 * need one more variable other than the velocity ("dx" in this case) which is 
 * the acceleration (lets call it "ax").
 */

/* Inside your player object, update the velocity and position like this :- */

var player = {
    update: function(delta, leftDown, rightDown) {
        // When left key is down, velocity will deccelerate till it reaches -max value.
        if(leftDown) {      
            if(this.dx > -this.maxValue) {
                this.dx -= this.ax * delta;
                if(this.dx < -this.maxValue) {
                    this.dx = - this.maxValue;
                }
            }
        }
        // When right key is down, velocity will accelerate till it reaches max value.
        if(rightDown) {     
            if(this.dx < this.maxValue) {
                this.dx += this.ax * delta;
                if(this.dx > this.maxValue) {
                    this.dx = this.maxValue;
                }
            }
        }
        // When both keys are down, or when both keys are up, bring the velocity to zero.
        if((leftDown && rightDown) || (!leftDown && !rightDown)) {      
            if(this.dx < 0) {       
                this.dx += this.ax * delta;
                if(this.dx > 0) {
                    this.dx = 0;
                }
            }
            else if(this.dx > 0) {
                this.dx -= this.ax * delta;
                if(this.dx < 0) {
                    this.dx = 0;
                }
            }
        }

        // update the position
        this.x += this.dx * delta;
    }
};
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.