Please see this Fiddle: https://jsfiddle.net/sfarbota/wd5aa1wv/2/
I am trying to make the ball bounce inside the circle at the correct angles without losing speed. I think I have the collision detection down, but I am facing 2 issues:
- The ball slows down with each bounce, until eventually stopping.
- The angles at which it bounces appear to be incorrect.
This is partially based off of the answer given here: https://stackoverflow.com/a/12053397/170309 but I had to translate from Java and also skipped a few lines from their example that seemed irrelevant.
Here is the code:
JavaScript:
function getBall(xVal, yVal, dxVal, dyVal, rVal, colorVal) {
var ball = {
x: xVal,
lastX: xVal,
y: yVal,
lastY: yVal,
dx: dxVal,
dy: dyVal,
r: rVal,
color: colorVal,
normX: 0,
normY: 0
};
return ball;
}
var canvas = document.getElementById("myCanvas");
var xLabel = document.getElementById("x");
var yLabel = document.getElementById("y");
var dxLabel = document.getElementById("dx");
var dyLabel = document.getElementById("dy");
var vLabel = document.getElementById("v");
var normXLabel = document.getElementById("normX");
var normYLabel = document.getElementById("normY");
var ctx = canvas.getContext("2d");
var containerR = 200;
canvas.width = containerR * 2;
canvas.height = containerR * 2;
canvas.style["border-radius"] = containerR + "px";
var balls = [
//getBall(canvas.width / 2, canvas.height - 30, 2, -2, 20, "#0095DD"),
//getBall(canvas.width / 3, canvas.height - 50, 3, -3, 30, "#DD9500"),
//getBall(canvas.width / 4, canvas.height - 60, -3, 4, 10, "#00DD95"),
getBall(canvas.width / 2, canvas.height / 5, -1.5, 3, 40, "#DD0095")
];
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < balls.length; i++) {
var curBall = balls[i];
ctx.beginPath();
ctx.arc(curBall.x, curBall.y, curBall.r, 0, Math.PI * 2);
ctx.fillStyle = curBall.color;
ctx.fill();
ctx.closePath();
curBall.lastX = curBall.x;
curBall.lastY = curBall.y;
curBall.x += curBall.dx;
curBall.y += curBall.dy;
if (containerR <= curBall.r + Math.sqrt(Math.pow(curBall.x - containerR, 2) + Math.pow(curBall.y - containerR, 2))) {
curBall.normX = (curBall.x + curBall.r) - (containerR);
curBall.normY = (curBall.y + curBall.r) - (containerR);
var normD = Math.sqrt(Math.pow(curBall.x, 2) + Math.pow(curBall.y, 2));
if (normD == 0)
normD = 1;
curBall.normX /= normD;
curBall.normY /= normD;
var dotProduct = (curBall.dx * curBall.normX) + (curBall.dy * curBall.normY);
curBall.dx = -2 * dotProduct * curBall.normX;
curBall.dy = -2 * dotProduct * curBall.normY;
}
xLabel.innerText = "x: " + curBall.x;
yLabel.innerText = "y: " + curBall.y;
dxLabel.innerText = "dx: " + curBall.dx;
dyLabel.innerText = "dy: " + curBall.dy;
vLabel.innerText = "v: " + curBall.dy / curBall.dx;
normXLabel.innerText = "normX: " + curBall.normX;
normYLabel.innerText = "normY: " + curBall.normY;
}
}
setInterval(draw, 10);
HTML:
<canvas id="myCanvas"></canvas>
<div id="x"></div>
<div id="y"></div>
<div id="dx"></div>
<div id="dy"></div>
<div id="v"></div>
<div id="normX"></div>
<div id="normY"></div>
CSS:
canvas { background: #eee; }