簡體   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