javascript - Why is this ball inside a circle not bouncing properly? -
please see fiddle: https://jsfiddle.net/sfarbota/wd5aa1wv/2/
i trying make ball bounce inside circle @ correct angles without losing speed. think have collision detection down, facing 2 issues:
- the ball slows down each bounce, until stopping.
- the angles @ bounces appear incorrect.
this partially based off of answer given here: https://stackoverflow.com/a/12053397/170309 had translate java , skipped few lines example seemed irrelevant.
here 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); (var = 0; < 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; }
my math rusty, i'm not quite sure how compute new trajectory of ball using dot product, i'm sure can compute relevant trig functions: use atan2
compute angle collision point , current trajectory angle, use 2 compute new angle, , pair of sin
, cos
multiplied speed new x/y speeds.
jsfiddle: https://jsfiddle.net/jacquesc/wd5aa1wv/6/
the important part is:
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 center of large circle center of small circle, // same angle center of large cercle // collision point var angletocollisionpoint = math.atan2(-dy, dx); // angle of current movement var oldangle = math.atan2(-curball.dy, curball.dx); // new angle var newangle = 2 * angletocollisionpoint - oldangle; // new x/y speeds, using current speed , new angle curball.dx = -v * math.cos(newangle); curball.dy = v * math.sin(newangle); }
also note switched setinterval
requestanimationframe
, make sure there's no more 1 update per frame. ideally want compute movement based on actual time elapsed since last update rather rely on being same.
update
using dot 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; }
Comments
Post a Comment