16

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;
        }
    }
}
BSMP
  • 4,596
  • 8
  • 33
  • 44
Joe Taylor
  • 579
  • 1
  • 6
  • 21
  • 2
    Look into basic physical simulation of force, momentum and friction. Make it so that your keys add a sort of force to the ship, that has a mass, and upon which friction is applied... With appropriate choosing of the parameters (mass, friction, force), you can create all kinds of behaviors. It is tricky though! But you can use it later: get a bonus with which a ship acts quicker, or a negative bonus, that makes the ship act heavy. – ppeterka Mar 11 '13 at 16:54
  • 2
    Pretty much just recreate the laws of physics with JavaScript O.O – VoidKing Mar 11 '13 at 16:55

3 Answers3

29

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;
});
Loktar
  • 34,764
  • 7
  • 90
  • 104
  • Love your answer. Is there any difference between putting the requestAnimationFrame(update) call at the end of the update function rather than the top? – macalaca Nov 08 '17 at 03:25
  • @macalaca [no](https://stackoverflow.com/a/38229580/6243352) – ggorlen Jun 19 '21 at 02:18
2

I think what I would do is on keyup don't stop the ship, just have a function that slows it down a little then call this function in setInterval at whatever interval gives you the desired effect and then once the speed of the ship is zero call clearInterval

So on keyup u basically setup setInterval(slowShip, 500)

Tutan Ramen
  • 1,234
  • 1
  • 8
  • 27
1

You could try reducing the speed continuously on every frame

if(!playerUp && !playerDown && moveSpeed > 0){
    moveSpeed--;
}
Andrew T.
  • 4,701
  • 8
  • 43
  • 62