В дополнение к тому, что Always Learning говорит , края обрабатываются неправильно. Я предполагаю, что вы хотите, чтобы они подпрыгивали?
Давайте посмотрим на код:
if (window['ball' + i].x < 0 || window['ball' + i].x > w) {
window['ball' + i].x = window['ball' + i].x + ((-1) * window['ball' + i].v * dt);
window['ball' + i].y = window['ball' + i].y + window['ball' + i].v * dt
}
Давайте избавимся от некоторого шума:
if (x < 0 || x > w) {
x = x + ((-1) * v * dt);
y = y + v * dt
}
Вы были правы с -1 * v
, но это все еще только перемещает шар только в пределах границы холста снова. Затем l oop он будет внутри границы и будет действовать нормально, и его скорость будет добавлена снова, снова выведя его за пределы границы, снова запустив этот код. Это эффективно "прилипает" шары к границе. Когда он попадает на одну границу, другая координата все еще перемещается, пока эта координата тоже не выходит за границу. Все шары заканчиваются около 0,0 или по диагонали напротив холста.
То, что вы хотите сделать здесь, это сделать скорость противоположной:
if (x < 0 || x > w || y < 0 || y > h) {
v *= -1
}
Это приведет к мяч отскакивает в противоположном направлении.
Этот код все еще не вполне совершенен, потому что в действительности скорость имеет размерные компоненты, то есть скорость x и скорость yy.
Код гораздо более читабелен при использовании локальных переменных, особенно при использовании массива для шаров. Я могу вернуться позже и измерить скорость, но вот как выглядит код:
const canvas = document.getElementById("canvas");
const height = canvas.clientHeight;
const width = canvas.clientWidth;
canvas.height = height;
canvas.width = width;
const ctx = canvas.getContext("2d");
const h = canvas.height;
const w = canvas.width;
const sAngle = 0;
const numB = 10;
const speed = 50;
const dt = 0.01;
const PI = Math.PI;
const balls = createBalls();
function resetCanvas() {
canvas.width = canvas.width;
}
function createBalls() {
const balls = [];
for (let i = 1; i <= numB; i++) {
const ball = createBall();
if (i % 2 == 0) {
ball.v *= -1;
}
balls.push(ball);
}
return balls;
}
function createBall() {
return { r: 10, color: "white", x: w * Math.random(), y: h * Math.random(), v: speed };
}
function drawBalls() {
balls.forEach(ball => {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, sAngle, 2 * PI);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.strokeStyle = ball.color;
ctx.stroke();
});
}
function moveBalls() {
balls.forEach(ball => {
const { x, y } = ball;
if (x < 0 || x > w || y < 0 || y > h) {
ball.v *= -1
}
ball.x = x + ball.v * dt;
ball.y = y + ball.v * dt
});
}
function animate() {
resetCanvas();
drawBalls();
moveBalls();
};
setInterval(animate, 100 * dt);