I am trying to achieve left/right circular movement inside my main circle. I have class Circle and Ball. Circle is responsible for drawing a "circle" where I am placing my Ball, that is moving inside.
class Circle {
constructor(gameWIdth, gameHeight) {
this.gameHeight = gameHeight;
this.gameWIdth = gameWIdth;
this.circX = 100;
this.circY = 100;
this.radius = 55;
}
draw(context) {
context.beginPath();
context.fillStyle = "white";
context.arc(
this.gameWIdth / 2,
this.gameHeight / 2,
100,
0,
Math.PI * 2,
false
); // outer (filled)
context.arc(
this.gameWIdth / 2,
this.gameHeight / 2,
this.radius,
0,
Math.PI * 2,
true
); // outer (unfills it)
context.fill();
}
}
class Ball {
constructor(gameWIdth, gameHeight) {
this.gameWIdth = gameWIdth;
this.gameHeight = gameHeight;
this.ballX = this.gameWIdth / 2;
this.ballY = this.gameHeight / 2;
this.vx = 0.03;
this.radians = Math.PI * 2;
}
draw() {
context.beginPath();
context.fillStyle = "green";
context.arc(this.ballX, this.ballY - 67, 15, 0, Math.PI * 2, false);
context.fill();
}
update(input) {
if (input.includes("ArrowLeft")) {
this.ballX = this.ballX Math.cos(this.radians) * -2;
this.ballY = this.ballY Math.sin(this.radians) * -2;
} else if (input.includes("ArrowRight")) {
this.ballX = this.ballX Math.cos(this.radians) * 2;
this.ballY = this.ballY Math.sin(this.radians) * 2;
}
//circular move
this.radians = this.vx;
this.ballX = this.ballX Math.cos(this.radians) * 2;
this.ballY = this.ballY Math.sin(this.radians) * 2;
console.log(this.ballX, this.ballY);
}
}
class Input {
constructor() {
this.keys = [];
window.addEventListener("keydown", (e) => {
if (
(e.key === "ArrowLeft" || "ArrowRight") &&
this.keys.indexOf(e.key) === -1
) {
this.keys.push(e.key);
}
console.log(e.key, this.keys);
});
window.addEventListener("keyup", (e) => {
if (e.key === "ArrowLeft" || "ArrowRight") {
this.keys.splice(this.keys.indexOf(e.key), 1);
}
console.log(e.key, this.keys);
});
}
}
class Game {
constructor(context, width, height) {
this.context = context;
this.width = width;
this.height = height;
this.circle = new Circle(canvas.width, canvas.height);
this.ball = new Ball(canvas.width, canvas.height);
this.input = new Input();
}
draw() {
this.circle.draw(context);
this.ball.draw(context);
}
update() {
this.ball.update(this.input.keys);
}
}
const game = new Game(context, canvas.width, canvas.height);
const drawCanvas = () => {
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
};
const animation = () => {
drawCanvas();
game.draw();
game.update();
requestAnimationFrame(animation);
};
animation();
For now I am inputing left right arrow press and i do want my ball to change direction based on arrow press. I was playing with
if (input.includes("ArrowLeft")) {
this.ballX = this.ballX Math.cos(this.radians) * -2;
this.ballY = this.ballY Math.sin(this.radians) * -2;
} else if (input.includes("ArrowRight")) {
this.ballX = this.ballX Math.cos(this.radians) * 2;
this.ballY = this.ballY Math.sin(this.radians) * 2;
}
where * -2
should revert movement, but it is not working as I thought it will
Here is codesandobx I do get that this can be a bit more complicated than I anticipated
CodePudding user response:
Usually you make something change direction by modifying its speed. Here I change the value of this.vx to be either positive or negative.
I also changed the calculations for ball position slightly, I just used numbers like 75 and 66 that seemed to be approximately correct, but you might need to change those for your needs.
update(input) {
if (input.includes("ArrowLeft")) {
if (this.vx > 0) this.vx *= -1;
} else if (input.includes("ArrowRight")) {
if (this.vx < 0) this.vx *= -1;
}
//circular move
this.radians = this.vx;
this.ballX = Math.cos(this.radians) * 75 this.gameWIdth / 2;
this.ballY = Math.sin(this.radians) * 75 this.gameHeight / 2 66;
}
CodePudding user response:
Adding to ballX
and ballY
is the wrong approach here.
In general, getting a point on a circle, like your ball's position, looks like this.
x = centerX Math.cos(angle) * radius
y = centerY Math.sin(angle) * radius
In your case, the only thing that changes is angle
. So this is the only thing you need to update.
update() {
if (input === 'ArrowLeft') {
velocity = -0.03
} else if (input === 'ArrowRight') {
velocity = 0.03
}
angle = velocity
}
draw() {
const x = centerX Math.cos(angle) * pathRadius
const y = centerY Math.sin(angle) * pathRadius
ctx.arc(x, y, ballRadius, 0, Math.PI * 2)
}
It's good to think about the minimum information your program needs to keep track of. Here, you only need to store angle
, and then you can calculate x
and y
when you need them.