我是画布动画的初学者,我尝试过一个简单的示例代码来进行圆碰撞测试。在此之前,我试图搜索互联网,但我无法理解背后的逻辑是什么。下面是我到目前为止得到的代码,问题是他们碰撞的一些圈子但是之后他们粘在一起或者互相叠加,不确定我背后的逻辑中是否有任何遗漏或错误?
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= (a.x-b.x), disy= (a.y-b.y),
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 || d.x-d.size<0) d.vx=d.vx*-1;
if(d.y+d.size>c.height || d.y-d.size<0) d.vy=d.vy*-1;
d.x+= d.vx,
d.y+= d.vy;
can.fillStyle= '#a6e22e';
can.beginPath();
can.arc(d.x, d.y, 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>
答案 0 :(得分:2)
你应该解决未来的问题,而不是当前的问题 数学可能有些困难,但你需要的全部 - 考虑未来的职位 结果速度也不能只是消极来源。
我相应地更正了this article
的功能
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(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
}
function midpoint(a, b) {
return {
x: (a.x + b.x) / 2,
y: (a.y + b.y) / 2
};
}
function resA(a, b) {
var mid = midpoint(a, b);
var dist = distance(a, b);
if (dist > a.r+b.r) return;
a.x = mid.x + (a.r+b.r) * (a.x - b.x) / dist;
a.y = mid.y + (a.r+b.r) * (a.y - b.y) / dist;
}
function staticStaticResolve(a, b) {
var mid = midpoint(a, b);
var dist = distance(a, b);
if (dist > a.r+b.r) return;
a.x = mid.x + a.r * (a.x - b.x) / dist;
a.y = mid.y + a.r * (a.y - b.y) / dist;
b.x = mid.x + b.r * (b.x - a.x) / dist;
b.y = mid.y + b.r * (b.y - a.y) / dist;
}
function coli(a, b) {
var a1 = {
x: a.x + a.vx,
y: a.y + a.vy
};
var b1 = {
x: b.x + b.vx,
y: b.y + b.vy
};
var d = distance(a1, b1);
if (d > a.r+b.r) return;
var n = {
x: (b1.x - a1.x) / d,
y: (b1.y - a1.y) / d
};
var p = 2 * (a.vx*n.x + a.vy*n.y - (b.vx*n.x + b.vy*n.y)) / (a.m + b.m);
a.vx = a.vx - p * b.m * n.x;
a.vy = a.vy - p * b.m * n.y;
b.vx = b.vx + p * a.m * n.x;
b.vy = b.vy + p * a.m * n.y;
}
function drawppl(d, p){
for(var i=0;i<ppl.length;i++){
if(i==p) continue;
coli(d,ppl[i]);
}
if(d.x+d.r>c.width)
d.vx=-Math.abs(d.vx);
if(d.x-d.r<0)
d.vx=Math.abs(d.vx);
if(d.y+d.r>c.height)
d.vy=-Math.abs(d.vy);
if(d.y-d.r<0)
d.vy=Math.abs(d.vy);
d.x += d.vx,
d.y += d.vy;
can.beginPath();
can.arc(d.x, d.y, d.r, 0, Math.PI*2, true);
can.closePath();
//can.fillStyle= d.m > 3 ? '#ff6666' : '#66ff66';
//can.fill();
can.lineWidth = 3;
can.strokeStyle= d.m > 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();
})();
&#13;
html,body {
width:100%;
height:100%;
margin:0;
padding:0;
border:0;
}
&#13;
<canvas></canvas>
&#13;
让我们尝试解决&#34;吃&#34;问题。
当它们太近时,我们只会将它们解析为静态。
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(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
}
function midpoint(a, b) {
return {
x: (a.x + b.x) / 2,
y: (a.y + b.y) / 2
};
}
function resA(a, b) {
var mid = midpoint(a, b);
var dist = distance(a, b);
if (dist > a.r+b.r) return;
a.x = mid.x + (a.r+b.r) * (a.x - b.x) / dist;
a.y = mid.y + (a.r+b.r) * (a.y - b.y) / dist;
}
function staticStaticResolve(a, b) {
var mid = midpoint(a, b);
var dist = distance(a, b);
if (dist > a.r+b.r) return;
a.x = mid.x + a.r * (a.x - b.x) / dist;
a.y = mid.y + a.r * (a.y - b.y) / dist;
b.x = mid.x + b.r * (b.x - a.x) / dist;
b.y = mid.y + b.r * (b.y - a.y) / dist;
}
function coli(a, b) {
var a1 = {
x: a.x + a.vx,
y: a.y + a.vy
};
var b1 = {
x: b.x + b.vx,
y: b.y + b.vy
};
var d = distance(a1, b1);
if (d > a.r+b.r) return;
if (d < Math.min(a.r, b.r)) {
staticStaticResolve(a, b);
}
var n = {
x: (b1.x - a1.x) / d,
y: (b1.y - a1.y) / d
};
var p = 2 * (a.vx*n.x + a.vy*n.y - (b.vx*n.x + b.vy*n.y)) / (a.m + b.m);
a.vx = a.vx - p * b.m * n.x;
a.vy = a.vy - p * b.m * n.y;
b.vx = b.vx + p * a.m * n.x;
b.vy = b.vy + p * a.m * n.y;
}
function drawppl(d, p){
for(var i=0;i<ppl.length;i++){
if(i==p) continue;
coli(d,ppl[i]);
}
if(d.x+d.r>c.width)
d.vx=-Math.abs(d.vx);
if(d.x-d.r<0)
d.vx=Math.abs(d.vx);
if(d.y+d.r>c.height)
d.vy=-Math.abs(d.vy);
if(d.y-d.r<0)
d.vy=Math.abs(d.vy);
d.x += d.vx,
d.y += d.vy;
can.beginPath();
can.arc(d.x, d.y, d.r, 0, Math.PI*2, true);
can.closePath();
//can.fillStyle= d.m > 3 ? '#ff6666' : '#66ff66';
//can.fill();
can.lineWidth = 2;
can.strokeStyle= d.m > 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();
})();
&#13;
html,body {
width:100%;
height:100%;
margin:0;
padding:0;
border:0;
}
&#13;
<canvas></canvas>
&#13;