Smooth character movement in canvas game using keyboard controls
Asked Answered
E

3

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;
        }
    }
}
Escobedo answered 11/3, 2013 at 16:51 Comment(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.Cipher
Pretty much just recreate the laws of physics with JavaScript O.OCalcic
I
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;
});
Iow answered 11/3, 2013 at 19:43 Comment(2)
Love your answer. Is there any difference between putting the requestAnimationFrame(update) call at the end of the update function rather than the top?Boutin
@Boutin noMonoclinous
E
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)

Esker answered 11/3, 2013 at 17:29 Comment(0)
D
1

You could try reducing the speed continuously on every frame

if(!playerUp && !playerDown && moveSpeed > 0){
    moveSpeed--;
}
Dave answered 10/2, 2018 at 2:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.