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:

  1. the ball slows down each bounce, until stopping.
  2. 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

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -