繁体   English   中英

画布圆检测碰撞和响应

[英]canvas circle detect collision and response

我是画布动画的初学者,我尝试过一个简单的示例代码来进行圆碰撞测试。 在此之前,我试图搜索互联网,但我无法理解背后的逻辑是什么。 下面是我到目前为止得到的代码,问题是他们碰撞的一些圈子但是之后他们粘在一起或互相叠加,不确定我背后的逻辑中是否有任何遗漏或错误?

  window.requestAnimationFrame= (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); (function(){ var c= document.getElementsByTagName('canvas')[0], can= c.getContext('2d'), ppl= [], count= 20; function resize(){ c.width= window.innerWidth, c.height= window.innerHeight, can.fillStyle='#000000', can.fillRect(0,0,c.width,c.height) } function pplD(){ var tf,pplnew={ x: Math.floor(Math.random()*c.width), y: Math.floor(Math.random()*c.height), size: 20,//Math.random()*4+8, vx: (Math.random()-0.5)*4+2, vy: (Math.random()-0.5)*4+2 } for(var i=0;i<ppl.length;i++){ tf= coli(pplnew,ppl[i]); if(tf){ pplD(); return } } return pplnew; } function canF(){ for(var i=0;i<count;i++){ ppl.push(new pplD) } requestAnimationFrame(render) } function coli(a,b){ var dis= a.size+b.size, disx= (ax-bx), disy= (ay-by), disxy= Math.sqrt((disx*disx)+(disy*disy)), c; if(disxy<dis){ if((a.vx>0 && b.vx>0) || (a.vx<0 && b.vx<0)){ c= a.vx, a.vx= b.vx, b.vx= c }else{ a.vx*= -1, b.vx*= -1 } if((a.vy>0 && b.vy>0) || (a.vy<0 && b.vy<0)){ c= a.vy, a.vy= b.vy, b.vy= c }else{ a.vy*= -1, b.vy*= -1 } return true; } return false; } function drawppl(d,p){ var tf; for(var i=0;i<ppl.length;i++){ if(i==p) continue; tf= coli(d,ppl[i]); } if(d.x+d.size>c.width || dx-d.size<0) d.vx=d.vx*-1; if(d.y+d.size>c.height || dy-d.size<0) d.vy=d.vy*-1; d.x+= d.vx, d.y+= d.vy; can.fillStyle= '#a6e22e'; can.beginPath(); can.arc(dx, dy, d.size, 0, Math.PI*2, true); can.closePath(); can.fill() } function render(){ can.fillStyle='rgba(0,0,0,0.2)', can.fillRect(0,0,c.width,c.height) for(var i=0;i<ppl.length;i++){ drawppl(ppl[i],i) } requestAnimationFrame(render) } window.onresize= resize; resize(); canF() })(); 
 html,body { width:100%; height:100%; margin:0; padding:0; border:0; } 
 <canvas></canvas> 

你应该解决未来的问题,而不是当前的问题。
数学可能有些困难,但你需要的全部 - 考虑未来的职位。
结果速度也不能仅仅是源的负面。

因此,我纠正你的函数这篇文章

 window.requestAnimationFrame= (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); (function(){ var c= document.getElementsByTagName('canvas')[0], can = c.getContext('2d'), ppl = [], count = 12; function resize(){ c.width = window.innerWidth; c.height = window.innerHeight; // console.log('Container', {x: c.width, y: c.height}); can.fillStyle='#000000', can.fillRect(0,0,c.width,c.height) } function pplD(){ var r = Math.random()*20+10; var tf,pplnew={ x: Math.floor(Math.random()*c.width-2*r)+3*r, y: Math.floor(Math.random()*c.height-2*r)+3*r, r: r, m: r/30, // mass vx: (Math.random()-0.5)*4+2, vy: (Math.random()-0.5)*4+2 } for(var i=0;i<ppl.length;i++){ resA(pplnew,ppl[i]); } return pplnew; } function canF(){ for(var i=0;i<count;i++){ ppl.push(new pplD) } // make heavy one ppl[0].m = 5; requestAnimationFrame(render) } function distance(a, b) { return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); } function midpoint(a, b) { return { x: (ax + bx) / 2, y: (ay + by) / 2 }; } function resA(a, b) { var mid = midpoint(a, b); var dist = distance(a, b); if (dist > a.r+br) return; ax = mid.x + (a.r+br) * (ax - bx) / dist; ay = mid.y + (a.r+br) * (ay - by) / dist; } function staticStaticResolve(a, b) { var mid = midpoint(a, b); var dist = distance(a, b); if (dist > a.r+br) return; ax = mid.x + ar * (ax - bx) / dist; ay = mid.y + ar * (ay - by) / dist; bx = mid.x + br * (bx - ax) / dist; by = mid.y + br * (by - ay) / dist; } function coli(a, b) { var a1 = { x: ax + a.vx, y: ay + a.vy }; var b1 = { x: bx + b.vx, y: by + b.vy }; var d = distance(a1, b1); if (d > a.r+br) return; var n = { x: (b1.x - a1.x) / d, y: (b1.y - a1.y) / d }; var p = 2 * (a.vx*nx + a.vy*ny - (b.vx*nx + b.vy*ny)) / (am + bm); a.vx = a.vx - p * bm * nx; a.vy = a.vy - p * bm * ny; b.vx = b.vx + p * am * nx; b.vy = b.vy + p * am * ny; } function drawppl(d, p){ for(var i=0;i<ppl.length;i++){ if(i==p) continue; coli(d,ppl[i]); } if(d.x+dr>c.width) d.vx=-Math.abs(d.vx); if(dx-dr<0) d.vx=Math.abs(d.vx); if(d.y+dr>c.height) d.vy=-Math.abs(d.vy); if(dy-dr<0) d.vy=Math.abs(d.vy); dx += d.vx, dy += d.vy; can.beginPath(); can.arc(dx, dy, dr, 0, Math.PI*2, true); can.closePath(); //can.fillStyle= dm > 3 ? '#ff6666' : '#66ff66'; //can.fill(); can.lineWidth = 3; can.strokeStyle= dm > 3 ? '#ff6666' : '#66ff66'; can.stroke(); } function render(){ can.fillStyle='rgba(0,0,0,0.2)', can.fillRect(0,0,c.width,c.height) for(var i=0;i<ppl.length;i++){ drawppl(ppl[i],i) } requestAnimationFrame(render) } window.onresize= resize; resize(); canF(); })(); 
 html,body { width:100%; height:100%; margin:0; padding:0; border:0; } 
 <canvas></canvas> 

让我们试着解决“吃”问题。
当它们太近时,我们只会将它们解析为静态。

 window.requestAnimationFrame= (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); (function(){ var c= document.getElementsByTagName('canvas')[0], can = c.getContext('2d'), ppl = [], count = 12; function resize(){ c.width = window.innerWidth; c.height = window.innerHeight; // console.log('Container', {x: c.width, y: c.height}); can.fillStyle='#000000'; can.fillRect(0,0,c.width,c.height) } function pplD(){ var r = Math.random()*20+10; var tf,pplnew={ x: Math.floor(Math.random()*c.width-2*r)+3*r, y: Math.floor(Math.random()*c.height-2*r)+3*r, r: r, m: r/30, // mass vx: (Math.random()-0.5)*4+2, vy: (Math.random()-0.5)*4+2 } for(var i=0;i<ppl.length;i++){ resA(pplnew,ppl[i]); } return pplnew; } function canF(){ for(var i=0;i<count;i++){ ppl.push(new pplD) } // make heavy one ppl[0].m = 5; requestAnimationFrame(render) } function distance(a, b) { return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); } function midpoint(a, b) { return { x: (ax + bx) / 2, y: (ay + by) / 2 }; } function resA(a, b) { var mid = midpoint(a, b); var dist = distance(a, b); if (dist > a.r+br) return; ax = mid.x + (a.r+br) * (ax - bx) / dist; ay = mid.y + (a.r+br) * (ay - by) / dist; } function staticStaticResolve(a, b) { var mid = midpoint(a, b); var dist = distance(a, b); if (dist > a.r+br) return; ax = mid.x + ar * (ax - bx) / dist; ay = mid.y + ar * (ay - by) / dist; bx = mid.x + br * (bx - ax) / dist; by = mid.y + br * (by - ay) / dist; } function coli(a, b) { var a1 = { x: ax + a.vx, y: ay + a.vy }; var b1 = { x: bx + b.vx, y: by + b.vy }; var d = distance(a1, b1); if (d > a.r+br) return; if (d < Math.min(ar, br)) { staticStaticResolve(a, b); } var n = { x: (b1.x - a1.x) / d, y: (b1.y - a1.y) / d }; var p = 2 * (a.vx*nx + a.vy*ny - (b.vx*nx + b.vy*ny)) / (am + bm); a.vx = a.vx - p * bm * nx; a.vy = a.vy - p * bm * ny; b.vx = b.vx + p * am * nx; b.vy = b.vy + p * am * ny; } function drawppl(d, p){ for(var i=0;i<ppl.length;i++){ if(i==p) continue; coli(d,ppl[i]); } if(d.x+dr>c.width) d.vx=-Math.abs(d.vx); if(dx-dr<0) d.vx=Math.abs(d.vx); if(d.y+dr>c.height) d.vy=-Math.abs(d.vy); if(dy-dr<0) d.vy=Math.abs(d.vy); dx += d.vx, dy += d.vy; can.beginPath(); can.arc(dx, dy, dr, 0, Math.PI*2, true); can.closePath(); //can.fillStyle= dm > 3 ? '#ff6666' : '#66ff66'; //can.fill(); can.lineWidth = 2; can.strokeStyle= dm > 3 ? '#ff6666' : '#66ff66'; can.stroke(); } var times = []; function render(){ times = times.filter(t => t>Date.now()-1000); times.push(Date.now()); can.fillStyle='rgba(0,0,0,0.5)', can.fillRect(0,0,c.width,c.height) can.font = "30px Arial"; can.fillStyle='#ffffff'; can.fillText("FPS: "+ times.length,10,50); for(var i=0;i<ppl.length;i++){ drawppl(ppl[i],i) } requestAnimationFrame(render) } window.onresize= resize; resize(); canF(); })(); 
 html,body { width:100%; height:100%; margin:0; padding:0; border:0; } 
 <canvas></canvas> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM