Итак, во-первых, давайте начнем с определения того, что такое «отскок» - скорость одинакова, но направление (на обеих осях) будет инвертировано. Если мы будем рассматривать dx и dy как вектор, то сначала мы сможем получить входящую скорость шара следующим образом:
var ballSpeed = Math.sqrt((ball.dx * ball.dx) + (ball.dy * ball.dy));
Приведенное выше значение всегда будет положительным, независимо от того, что делают dx и dy.
Далее нам понадобится входящее направление мяча - этот бит такой же, как у вас:
diffX = paddle.x-ball.x;
diffY = paddle.y-ball.y;
Однако если мы будем рассматривать это как вектор, он по существу имеет совершенно неизвестную длину. Итак, давайте нормализуем это так, чтобы это был вектор направления длиной 1:
var distanceBetweenPaddleAndBall = Math.sqrt((diffX * diffX) + (diffY * diffY));
diffX /= distanceBetweenPaddleAndBall;
diffY /= distanceBetweenPaddleAndBall;
diffX и diffY теперь являются нормализованным вектором направления - направление, в котором движется мяч, - а ballSpeed - это скорость, с которой мы хотели бы идти.
Так что теперь мы применим наш отскок - измените направление и сохраните скорость. Это становится так:
dir = {
x : -diffX * ballSpeed,
y : -diffY * ballSpeed
};
Соберите все вместе, и мы получим следующее:
if (collision(ball, paddle)) {
diffX = paddle.x-ball.x;
diffY = paddle.y-ball.y;
// How fast is the ball coming in?
var ballSpeed = Math.sqrt((ball.dx * ball.dx) + (ball.dy * ball.dy));
// How far is the ball from the paddle?
var distanceBetweenPaddleAndBall = Math.sqrt((diffX * diffX) + (diffY * diffY));
// Normalise diffX and diffY so we have a direction vector:
diffX /= distanceBetweenPaddleAndBall;
diffY /= distanceBetweenPaddleAndBall;
// Apply the bounce and the original ball speed:
dir = {
x : -diffX * ballSpeed,
y : -diffY * ballSpeed
};
ball.dx = dir.x;
ball.dy = dir.y;
}
И вот оно как вилка вашей скрипки тоже .