My math is rusty, so I'm not quite sure how you could calculate a new ball path using only a point product, but I'm sure you can calculate it using the appropriate trigger functions: use atan2 to calculate the angle to the collision point and the current angle paths, use these two to calculate the new angle, and the pair sin and cos times the speed to get the new speeds x / y.
jsFiddle: https://jsfiddle.net/jacquesc/wd5aa1wv/6/
Main part:
var dx = curBall.x - containerR; var dy = curBall.y - containerR; if (Math.sqrt(dx * dx + dy * dy) >= containerR - curBall.r) { // current speed var v = Math.sqrt(curBall.dx * curBall.dx + curBall.dy * curBall.dy); // Angle from center of large circle to center of small circle, // which is the same as angle from center of large cercle // to the collision point var angleToCollisionPoint = Math.atan2(-dy, dx); // Angle of the current movement var oldAngle = Math.atan2(-curBall.dy, curBall.dx); // New angle var newAngle = 2 * angleToCollisionPoint - oldAngle; // new x/y speeds, using current speed and new angle curBall.dx = -v * Math.cos(newAngle); curBall.dy = v * Math.sin(newAngle); }
Also note that I switched from setInterval to requestAnimationFrame , which will contain no more than one update for each frame. Ideally, you would like to calculate the movement based on the actual time elapsed since the last update, and not rely on the fact that it is always the same.
Update
Use of point products:
jsFiddle: https://jsfiddle.net/jacquesc/wd5aa1wv/9/
var dx = curBall.x - containerR; var dy = curBall.y - containerR; var distanceFromCenter = Math.sqrt(dx * dx + dy * dy); if (distanceFromCenter >= containerR - curBall.r) { var normalMagnitude = distanceFromCenter; var normalX = dx / normalMagnitude; var normalY = dy / normalMagnitude; var tangentX = -normalY; var tangentY = normalX; var normalSpeed = -(normalX * curBall.dx + normalY * curBall.dy); var tangentSpeed = tangentX * curBall.dx + tangentY * curBall.dy; curBall.dx = normalSpeed * normalX + tangentSpeed * tangentX; curBall.dy = normalSpeed * normalY + tangentSpeed * tangentY; }
source share