Search code examples
javascriptcanvasgame-physicseasing

Smooth character movement in canvas game using keyboard controls


I'm creating a side-scrolling endless space themed game using canvas and JavaScript. I'm controlling a spaceship just by using the up and down arrows and I want to implement some kind of movement easing so that the ship doesn't just stop dead when I let go of the keys. I've looked around and haven't found anything plus my own attempts just aren't working. This is what I've tried.

Jet.prototype.checkDirection = function () {
if (this.isUpKey) {
    this.drawY -= this.speed;
    if (this.speed < 5) {
        this.speed += 0.1;
    }
}
if (this.isDownKey) {
    this.drawY += this.speed;
    if (this.speed < 5) {
        this.speed += 0.1;
    }
}
if (!this.isUpKey) {
    if (!this.isDownKey) {
        if (this.speed >= 0) {
            this.drawY -= this.speed;
            this.speed -= 1;
        }
    }
}
if (!this.isDownKey) {
    if (!this.isUpKey) {
        if (this.speed >= 0) {
            this.drawY += this.speed;
            this.speed -= 1;
        }
    }
}

Solution

  • You just want to apply some friction. Its pretty easy. You can do something like the following.

    this.speed*=0.98;
    

    The lower the value (0.8, 0.5, etc) the faster you will slow down.

    I provided a demo where you can move around and will gradually slow down. Go ahead and play with the value and see how it affects it.

    Live Demo

    var canvas = document.getElementById("canvas"),
        ctx = canvas.getContext("2d");
    
    canvas.width = canvas.height = 300;
    
    var x = 150,  //initial x
        y = 150,  // initial y
        velY = 0,
        velX = 0,
        speed = 2, // max speed
        friction = 0.98, // friction
        keys = [];
    
    function update() {
        requestAnimationFrame(update);
    
        // check the keys and do the movement.
        if (keys[38]) {
            if (velY > -speed) {
                velY--;
            }
        }
    
        if (keys[40]) {
            if (velY < speed) {
                velY++;
            }
        }
        if (keys[39]) {
            if (velX < speed) {
                velX++;
            }
        }
        if (keys[37]) {
            if (velX > -speed) {
                velX--;
            }
        }
    
        // apply some friction to y velocity.
        velY *= friction;
        y += velY;
    
        // apply some friction to x velocity.
        velX *= friction;
        x += velX;
    
        // bounds checking
        if (x >= 295) {
            x = 295;
        } else if (x <= 5) {
            x = 5;
        }
    
        if (y > 295) {
            y = 295;
        } else if (y <= 5) {
            y = 5;
        }
    
        // do the drawing
        ctx.clearRect(0, 0, 300, 300);
        ctx.beginPath();
        ctx.arc(x, y, 5, 0, Math.PI * 2);
        ctx.fill();
    }
    
    update();
    
    // key events
    document.body.addEventListener("keydown", function (e) {
        keys[e.keyCode] = true;
    });
    document.body.addEventListener("keyup", function (e) {
        keys[e.keyCode] = false;
    });