I'm creating a birds-eye view, 2D game in JS using no engine/library (more for the learning challenge). I've got the character movement working with WASD where the character will either go forward (W) or back (S) depending on their current direction
(A turns left, D turns right), but when I output the angles (direction
) during play-time I'm getting unexpected results.
For example, when a player is facing "up" and I press "W", the player moves up, and the direction
that gets output is 90°
- as expected. When facing "down" and I press "S", the player moves down, and the direction
is 270°
- as expected.
But, when facing left, and I press "W", the character does move left but the output direction
is 0°
, and when facing + moving right, it is 180°
- the exact opposite of what I expect.
These are the functions that move my players:
// Turning
_resetAngle(angle) {
if (angle >= 360) { return 0 }
if (angle < 0) { return 359 }
return angle
}
updateDirection(player, keyboardInput) {
let currentDirection = player.direction
const turnedLeft = keyboardInput['a']
const turnedRight = keyboardInput['d']
if (turnedLeft) { currentDirection -= this.turnAngle }
if (turnedRight) { currentDirection += this.turnAngle }
player.setDirection(this._resetAngle(currentDirection))
}
//Moving
_calculateNewCoords(movingForward, entity) {
let newX
let newY
// please ignore the code duplication, just testing for now
if (movingForward) {
newX = entity.getX() - entity.speed * Math.cos(entity.direction * (Math.PI / 180))
newY = entity.getY() - entity.speed * Math.sin(entity.direction * (Math.PI / 180))
}
else {
newX = entity.getX() + entity.speed * Math.cos(entity.direction * (Math.PI / 180))
newY = entity.getY() + entity.speed * Math.sin(entity.direction * (Math.PI / 180))
}
return { newX, newY }
}
updateCoordinatesByKeyboard(entity, keyboardInput) {
const movingForward = keyboardInput['w']
const movingBackwards = keyboardInput['s']
if ((movingForward && movingBackwards) || !(movingForward || movingBackwards)) { return }
const { newX, newY } = this._calculateNewCoords(movingForward, entity)
if (this._canMove(entity, newX, newY)) { return entity.setXY(newX, newY) }
}
And this is the part that renders the players:
drawCharacter(character, image) {
const scale = this._getScale(character) // for a 'breathing' effect, makes character grow and shrink
this.context.setTransform(scale, 0, 0, scale, this.windowDimensions.width / 2, this.windowDimensions.height / 2)
this.context.rotate(character.direction * Math.PI / 180)
this.context.drawImage(image, -image.width / 2, -image.height / 2)
}
Results when printing player.direction
:
Output: 90
(as expected)
Output: 180
(expect it to be 0)
Output: 270
(as expected)
Output: 0
(expect it to be 180)
Output: 135
(expect it to be 45)
Output: 315
(expect it to be 225)
Again, just to reiterate - the players move as expected (i.e. pressing WASD makes the player turn and move correctly) - but the output direction
s are unexpected, and I'd like to fix that because in the future I'd like to set NPCs at certain angles (i.e. facing 45°) and expect them to face that direction without having to calculate the 'mirror' direction.
Thanks in advance for any help!
I wouldn't say the values you get don't make sense - it's quite the reverse - as it's what I would expect. So it's more of a 'cosmetical' problem as it would be the same for your other game objects.
Nevertheless you can easily recalculate the output to your desired value by:
output = Math.abs((input + 90) % 360 - 270)
This will make:
90 -> 90
180 -> 0
270 -> 270
0 -> 180
135 -> 45
315 -> 225