How do I correctly make character sprite direction match player inputs?

In my top down game I can move the character around and the character will even face the direction he is moving.

However, there is some weird behavior I'm having: when you hold down one direction and then another direction the graphic updates to that direction, but if you keep holding the direction prior it does not update to the correct graphic.

Here is my function that handles the rendering of the player graphic. When that happens it looks like the character is walking sideways. I haven't added animation yet. It just tries to have the right graphic with the corresponding direction.

render: function() {
var game = roguelike.game;
var map = roguelike.map;
var image = game.library.images[1];
var ctx = game.library.ctx;
var centerX = game.library.canvas.width / 2 - map.tileSize / 2;
var centerY = game.library.canvas.height / 2 - map.tileSize / 2;
switch(this.facing) {
case "left":
var cropX = 1 * map.tileSize;
var cropY = 5 * map.tileSize;
break;
case "up":
var cropX = 1 * map.tileSize;
var cropY = 7 * map.tileSize;
break;
case "right":
var cropX = 1 * map.tileSize;
var cropY = 6 * map.tileSize;
break;
case "down":
var cropX = 1 * map.tileSize;
var cropY = 4 * map.tileSize;
break;
}
ctx.drawImage(
image,
cropX,
cropY,
map.tileSize,
map.tileSize,
centerX,
centerY,
map.tileSize,
map.tileSize
);
}


Also you might want to see how I handle my player.facing state. I do it this way.

window.onkeydown = function (event) {
var player = roguelike.player;
switch (event.keyCode) {
//Left
case 37:
player.facing = "left";
player.moving.left = true;
break;
//Up
case 38:
player.facing = "up";
player.moving.up = true;
break;
//Right
case 39:
player.facing = "right";
player.moving.right = true;
break;
//Down
case 40:
player.facing = "down";
player.moving.down = true;
break;
}
};

• It sounds like they key repeat is confusing the game. You might need to set everything to false except the direction he's going for each key. It would be a good idea to make a "goDirection" function so your keyhandler script doesn't become unmaintainably large. Also you should handle onkeyup events and set the appropriate values to false for each key. – pixelmike Jun 15 '15 at 3:52
• Actually that is how the controls are set up. The direction the player goes is working as expected. It's just that the graphic sometimes is the incorrect graphic. Sometimes it looks like the player is strafing. But the direction of the player is correct. – zachdyer Jun 15 '15 at 10:20

Similar to RDeving's answer, here's my usual code:

var keys = {};
window.onkeydown = function(evt) {
keys[evt.keyCode] = true;
}
window.onkeyup = function(evt) {
delete keys[evt.keyCode];
}


if (37 in keys) {
//keycode 39 is down
}
if (38 in keys) {
//keycode 38 is down
}
// ... etc

• nice solution, +1 – PRDeving Aug 2 '16 at 19:06

The problem is that you set the facing variable depending on the last keypress. Set an object with

Var keypressed = {};


An then, in your keypress events handler set the keypressed as

Keypressed[e.keycode] = true;


And implement a key release event so it sets keypressed to false.

In the loop just check for the pressed keys and face depending on the keys that still pressed

As pixelmike mentioned, the problem might be that the keydown event executes every x milliseconds while the key is being pressed, and that is what produces the wrong player.facing value. Since you want the player to move in only one direction, the one of the last key pressed (and I guess that you set player.moving.x = false somewhere because the movement works properly, I would try doing something like this:

player.facing = (player.moving.left&&"left")||(player.moving.right&&"right")... ;


That way, the player will always face and move in the same direction.