When the mouse moves it doesn't point in the mouseX or mouseY direction.
The current method points and rotates at the top right point slightly offset on the canvas.
All the other SO questions didn't work for this specific game.
I would prefer the most straightforward answer and an explanation of how it works.
I need a vanilla javascript answer.
/**
* @type { HTMLCanvasElement }
*/
var scene = document.getElementById("scene");
var ctx = scene.getContext("2d");
var mouseX = 0;
var mouseY = 0;
var prevSceneTranslateXL = 0;
var prevSceneTranslateYL = 0;
var prevSceneTranslateXR = 0;
var prevSceneTranslateYR = 0;
var sceneTranslateX = 0;
var sceneTranslateY = 0;
var friction = 4 / 5;
var keysDown = [];
scene.width = window.innerWidth;
scene.height = window.innerHeight;
var bg = new Image();
bg.src = "./assets/groundBgAlt.png";
class Player {
constructor(x, y, radius, color, borderColor) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
class Enemy {
constructor(radius, color, borderColor) {
this.x = Math.random() * scene.width + 25;
this.y = Math.random() * scene.height + 25;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
var player1 = new Player(1000, 1000, 25, "#0080ff", "#606060");
var enemies = [];
// for (i = 0; i < 20; i++) {
// enemies.push(new Enemy(50, 50, "#ff0000", "#bb0000"));
// }
function drawPlayer(player) {
ctx.strokeStyle = "#606060";
ctx.lineWidth = 2;
ctx.fillStyle = "#cccccc";
ctx.save();
ctx.beginPath();
ctx.translate(player.x, player.y);
ctx.rotate(player1.angle);
ctx.roundRect(-10, -45, 20, 25, 2);
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.strokeStyle = player.borderColor;
ctx.lineWidth = 2;
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
function drawEnemies(enemy) {
ctx.strokeStyle = enemy.borderColor;
ctx.lineWidth = 3;
ctx.fillStyle = enemy.color;
ctx.beginPath();
ctx.rect(enemy.x, enemy.y, enemy.width, enemy.height);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
var gradientBG = ctx.createRadialGradient(1000, 1000, 1000, 1000, 1000, 100);
gradientBG.addColorStop(0.0, "#ffffff");
gradientBG.addColorStop(1.0, "#eeeeee");
function main() {
ctx.clearRect(-250, -250, 2500, 2500);
ctx.fillStyle = gradientBG;
ctx.fillRect(0, 0, 2000, 2000);
if (player1.x < 0) {
sceneTranslateX = prevSceneTranslateXL;
player1.x = 0;
player1.velX = 0;
}
if (player1.x > 2000) {
sceneTranslateX = prevSceneTranslateXR;
player1.x = 2000;
player1.velX = 0;
}
if (player1.y < 0) {
sceneTranslateY = prevSceneTranslateYL;
player1.y = 0;
player1.velY = 0;
}
if (player1.y > 2000) {
sceneTranslateY = prevSceneTranslateYR;
player1.y = 2000;
player1.velY = 0;
}
if (keysDown["w"] || keysDown["ArrowUp"]) {
if (player1.velY > player1.speed * -1) {
player1.velY--;
}
}
if (keysDown["a"] || keysDown["ArrowLeft"]) {
if (player1.velX > player1.speed * -1) {
player1.velX--;
}
}
if (keysDown["s"] || keysDown["ArrowDown"]) {
if (player1.velY < player1.speed) {
player1.velY++;
}
}
if (keysDown["d"] || keysDown["ArrowRight"]) {
if (player1.velX < player1.speed) {
player1.velX++;
}
}
player1.velX *= friction;
player1.velY *= friction;
player1.x += player1.velX;
player1.y += player1.velY;
sceneTranslateX *= friction;
sceneTranslateY *= friction;
sceneTranslateX += -player1.velX;
sceneTranslateY += -player1.velY;
prevSceneTranslateXL = sceneTranslateX - 1;
prevSceneTranslateYL = sceneTranslateY - 1;
prevSceneTranslateXR = sceneTranslateX + 1;
prevSceneTranslateYR = sceneTranslateY + 1;
ctx.translate(sceneTranslateX / 5, sceneTranslateY / 5);
drawPlayer(player1);
// for (i = 0; i < enemies.length; i++) {
// drawEnemies(enemies[i]);
// }
requestAnimationFrame(main);
}
ctx.translate((scene.width / 2) - player1.x, (scene.height / 2) - player1.y);
main();
document.addEventListener("keydown", (e) => {
keysDown[e.key] = true;
});
document.addEventListener("keyup", (e) => {
keysDown[e.key] = false;
});
document.addEventListener("mousemove", (e) => {
var angle = Math.atan2(e.pageY - player1.y, e.pageX - player1.x);
player1.angle = angle;
});
* {
font-family: roboto, Arial, Helvetica, sans-serif, system-ui, system 'Courier New', Courier, monospace;
padding: 0px 0px;
margin: 0px 0px;
box-sizing: border-box;
}
body {
background: radial-gradient(circle, #bbbbbb 10%, #cccccc);
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/styles.css">
<script src="scripts/index.js" defer></script>
<title>Document</title>
</head>
<body>
<canvas id="scene" width="1024" height="576"></canvas>
</body>
</html>
The way the game is made makes it really hard to rotate objects.
Alright, I figured this out awhile back now, but I figured I should answer my own question here in case someone else would find it useful.
/**
* @type { HTMLCanvasElement }
*/
var scene = document.getElementById("scene");
var ctx = scene.getContext("2d");
var mouseX = 0;
var mouseY = 0;
var friction = 4 / 5;
var keysDown = [];
var vWidth = window.innerWidth;
var vHeight = window.innerHeight;
scene.width = vWidth;
scene.height = vHeight;
var bg = new Image();
bg.src = "./assets/groundBgAlt.png";
class Player {
constructor(x, y, radius, color, borderColor) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
class Enemy {
constructor(radius, color, borderColor) {
this.x = Math.random() * scene.width + 25;
this.y = Math.random() * scene.height + 25;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
var player1 = new Player(1000, 1000, 25, "#0080ff", "#606060");
var enemies = [];
for (i = 0; i < 20; i++) {
enemies.push(new Enemy(50, 50, "#ff0000", "#bb0000"));
}
function drawPlayer(player) {
ctx.strokeStyle = "#606060";
ctx.lineWidth = 2;
ctx.fillStyle = "#cccccc";
ctx.save();
ctx.beginPath();
ctx.translate(player.x, player.y);
ctx.rotate(player1.angle);
ctx.roundRect(-10, -45, 20, 25, 2);
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.strokeStyle = player.borderColor;
ctx.lineWidth = 2;
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
function drawEnemies(enemy) {
ctx.strokeStyle = enemy.borderColor;
ctx.lineWidth = 3;
ctx.fillStyle = enemy.color;
ctx.beginPath();
ctx.rect(enemy.x, enemy.y, enemy.width, enemy.height);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
var gradientBG = ctx.createRadialGradient(1000, 1000, 1000, 1000, 1000, 100);
gradientBG.addColorStop(0.0, "#ffffff");
gradientBG.addColorStop(1.0, "#eeeeee");
function main() {
if (player1.x < 0) {
player1.x = 0;
player1.velX = 0;
}
if (player1.x > 2000) {
player1.x = 2000;
player1.velX = 0;
}
if (player1.y < 0) {
player1.y = 0;
player1.velY = 0;
}
if (player1.y > 2000) {
player1.y = 2000;
player1.velY = 0;
}
if (keysDown["w"] || keysDown["ArrowUp"]) {
if (player1.velY > player1.speed * -1) {
player1.velY--;
}
}
if (keysDown["a"] || keysDown["ArrowLeft"]) {
if (player1.velX > player1.speed * -1) {
player1.velX--;
}
}
if (keysDown["s"] || keysDown["ArrowDown"]) {
if (player1.velY < player1.speed) {
player1.velY++;
}
}
if (keysDown["d"] || keysDown["ArrowRight"]) {
if (player1.velX < player1.speed) {
player1.velX++;
}
}
player1.velX *= friction;
player1.velY *= friction;
player1.x += player1.velX;
player1.y += player1.velY;
ctx.save();
ctx.translate(-player1.x + (scene.width / 2), -player1.y + (scene.height / 2));
ctx.clearRect(-250, -250, 2500, 2500);
ctx.fillStyle = gradientBG;
ctx.fillRect(0, 0, 2000, 2000);
drawPlayer(player1);
for (i = 0; i < enemies.length; i++) {
drawEnemies(enemies[i]);
}
ctx.restore();
requestAnimationFrame(main);
}
main();
document.addEventListener("keydown", (e) => {
keysDown[e.key] = true;
});
document.addEventListener("keyup", (e) => {
keysDown[e.key] = false;
});
document.addEventListener("mousemove", (e) => {
var angle = Math.atan2(e.clientY - (vHeight / 2), e.clientX - (vWidth / 2));
player1.angle = angle + 90 * Math.PI / 180;
});
window.addEventListener("resize", () => {
vWidth = window.innerWidth;
vHeight = window.innerHeight
scene.width = vWidth;
scene.height = vHeight;
});
* {
font-family: roboto, Arial, Helvetica, sans-serif, system-ui, system 'Courier New', Courier, monospace;
padding: 0px 0px;
margin: 0px 0px;
box-sizing: border-box;
}
body {
background: radial-gradient(circle, #bbbbbb 10%, #cccccc);
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="scene"></canvas>
</body>
</html>