2017-09-27 3 views
3

何らかの理由で私のコードが機能しません。それは衝突シミュレーションでなければならないが、ボールは一緒にくっついているだけなので、なぜその理由が分からないようだ。私はhttps://en.wikipedia.org/wiki/Elastic_collision#Two-dimensional_collision_with_two_moving_objectsから式を使用していると、私の知る限り、私は完全にそれをコピーしている見ることができるように、私も、操作の順序が正しいことを確認するためにブラケットを追加したが、それでもここで運Javascriptの衝突が機能しない

は私のコードではありません。

手始めに

var canvas = document.getElementById("canvas"), 
 
    ctx = canvas.getContext("2d"); 
 

 
function Ball(){ 
 
    this.pos = { 
 
     "x": Math.random() * canvas.width, 
 
     "y": Math.random() * canvas.height 
 
    }; 
 
    this.vel = { 
 
     "x": Math.random() - 0.5, 
 
     "y": Math.random() - 0.5 
 
    }; 
 
    this.r = 16; 
 
    this.colliding = false; 
 
    this.m = 1; 
 
} 
 

 
function mag(v){ 
 
    return Math.sqrt((v.x * v.x) + (v.y * v.y)); 
 
} 
 

 
function dir(v){ 
 
    return Math.atan2(v.y, v.x); 
 
} 
 

 
function dist(a, b){ 
 
    var dx = b.x - a.x, 
 
     dy = b.y - a.y; 
 
    return Math.sqrt(dx * dx + dy * dy); 
 
} 
 

 
var balls = []; 
 
for(var i = 0; i < 10; i++){ 
 
    balls.push(new Ball()); 
 
} 
 

 
setInterval(function(){ 
 
    for(var i = 0; i < balls.length; i++){ 
 
     balls[i].pos.x += balls[i].vel.x; 
 
     balls[i].pos.y += balls[i].vel.y; 
 

 
     if(balls[i].pos.x + balls[i].r > canvas.width){ 
 
      balls[i].pos.x = canvas.width - balls[i].r; 
 
      balls[i].vel.x *= -1; 
 
     } 
 
     if(balls[i].pos.x < balls[i].r){ 
 
      balls[i].pos.x = balls[i].r; 
 
      balls[i].vel.x *= -1; 
 
     } 
 
     if(balls[i].pos.y + balls[i].r > canvas.height){ 
 
      balls[i].pos.y = canvas.height - balls[i].r; 
 
      balls[i].vel.y *= -1; 
 
     } 
 
     if(balls[i].pos.y < balls[i].r){ 
 
      balls[i].pos.y = balls[i].r; 
 
      balls[i].vel.y *= -1; 
 
     } 
 

 
     balls[i].colliding = false; 
 
    } 
 

 
    for(var i = 0; i < balls.length; i++){ 
 
     for(var j = i + 1; j < balls.length; j++){ 
 
      if(mag(balls[i].vel) < 0){ 
 
       break; 
 
      } 
 

 
      if(dist(balls[i].pos, balls[j].pos) < balls[i].r + balls[j].r){ 
 
       balls[i].colliding = true; 
 

 
       var contact = Math.atan2(balls[j].pos.y - balls[i].pos.y, balls[j].pos.x - balls[i].pos.x); 
 

 
       balls[i].vel.x = ((((mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact) * (balls[i].m - balls[j].m)) + (2 * balls[j].m * mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact)))/(balls[i].m + balls[j].m)) * Math.cos(contact)) + (mag(balls[i].vel) * Math.sin(dir(balls[i].vel) - contact) * Math.cos(contact + (Math.PI/2))); 
 
       balls[i].vel.y = ((((mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact) * (balls[i].m - balls[j].m)) + (2 * balls[j].m * mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact)))/(balls[i].m + balls[j].m)) * Math.sin(contact)) + (mag(balls[i].vel) * Math.sin(dir(balls[i].vel) - contact) * Math.sin(contact + (Math.PI/2))); 
 

 
       balls[j].vel.x = ((((mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact) * (balls[j].m - balls[i].m)) + (2 * balls[i].m * mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact)))/(balls[j].m + balls[i].m)) * Math.cos(contact)) + (mag(balls[j].vel) * Math.sin(dir(balls[j].vel) - contact) * Math.cos(contact + (Math.PI/2))); 
 
       balls[j].vel.y = ((((mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact) * (balls[j].m - balls[i].m)) + (2 * balls[i].m * mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact)))/(balls[j].m + balls[i].m)) * Math.sin(contact)) + (mag(balls[j].vel) * Math.sin(dir(balls[j].vel) - contact) * Math.sin(contact + (Math.PI/2))); 
 
      } 
 
     } 
 
    } 
 

 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
    for(var i = 0; i < balls.length; i++){ 
 
     ctx.beginPath(); 
 

 
     if(balls[i].colliding){ 
 
      ctx.fillStyle = "#f00"; 
 
     }else{ 
 
      ctx.fillStyle = "#0f0"; 
 
     } 
 

 

 
     ctx.arc(balls[i].pos.x, balls[i].pos.y, balls[i].r, 0, 2 * Math.PI); 
 
     ctx.fill(); 
 
    } 
 
}, 16);
<!DOCTYPE html> 
 
<html lang="en"> 
 
    <head> 
 
     <meta charset="utf-8"> 
 
     <title></title> 
 
    </head> 
 
    <body> 
 
     <canvas id="canvas" width="640" height="480"></canvas> 
 
     <script src="main.js"></script> 
 
    </body> 
 
</html>

+0

@TJCrowderは何の違い –

+2

@TJCrowder追加スニペットを行いませんパフォーマンスのためにも –

答えて

0

、私は衝突のボールjについての新しいvelXとvelYを反転し、あなたの衝突システムがうまく動作しているようです。しかし、あなたが注意深く見ると、あなたが言われたようにそれらが固まっていることに気付くでしょう。それはボールが1刻みに1ピクセル以上移動でき、ボールが別のものの中を移動する結果になるからです。内部にはありません。これを防ぐには、距離が合成された半径よりも小さい場合はvelXとvelYを調整する必要があります。私は、またMath.sqrtを使用してみましたが

var canvas = document.getElementById("canvas"), 
 
    ctx = canvas.getContext("2d"); 
 

 
function Ball(){ 
 
    this.pos = { 
 
     "x": Math.random() * canvas.width, 
 
     "y": Math.random() * canvas.height 
 
    }; 
 
    this.vel = { 
 
     "x": Math.random() - 0.5, 
 
     "y": Math.random() - 0.5 
 
    }; 
 
    this.r = 16; 
 
    this.colliding = false; 
 
    this.m = 1; 
 
} 
 

 
function mag(v){ 
 
    return Math.sqrt((v.x * v.x) + (v.y * v.y)); 
 
} 
 

 
function dir(v){ 
 
    return Math.atan2(v.y, v.x); 
 
} 
 

 
function dist(a, b){ 
 
    var dx = b.x - a.x, 
 
     dy = b.y - a.y; 
 
    return Math.sqrt(dx * dx + dy * dy); 
 
} 
 

 
var balls = []; 
 
for(var i = 0; i < 10; i++){ 
 
    balls.push(new Ball()); 
 
} 
 

 
setInterval(function(){ 
 
    for(var i = 0; i < balls.length; i++){ 
 
     balls[i].pos.x += balls[i].vel.x; 
 
     balls[i].pos.y += balls[i].vel.y; 
 

 
     if(balls[i].pos.x + balls[i].r > canvas.width){ 
 
      balls[i].pos.x = canvas.width - balls[i].r; 
 
      balls[i].vel.x *= -1; 
 
     } 
 
     if(balls[i].pos.x < balls[i].r){ 
 
      balls[i].pos.x = balls[i].r; 
 
      balls[i].vel.x *= -1; 
 
     } 
 
     if(balls[i].pos.y + balls[i].r > canvas.height){ 
 
      balls[i].pos.y = canvas.height - balls[i].r; 
 
      balls[i].vel.y *= -1; 
 
     } 
 
     if(balls[i].pos.y < balls[i].r){ 
 
      balls[i].pos.y = balls[i].r; 
 
      balls[i].vel.y *= -1; 
 
     } 
 

 
     balls[i].colliding = false; 
 
    } 
 

 
    for(var i = 0; i < balls.length; i++){ 
 
     for(var j = i + 1; j < balls.length; j++){ 
 
      if(mag(balls[i].vel) < 0){ 
 
       break; 
 
      } 
 

 
      if(dist(balls[i].pos, balls[j].pos) < balls[i].r + balls[j].r){ 
 
       balls[i].colliding = true; 
 

 
       var contact = Math.atan2(balls[j].pos.y - balls[i].pos.y, balls[j].pos.x - balls[i].pos.x); 
 

 
       balls[i].vel.x = ((((mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact) * (balls[i].m - balls[j].m)) + (2 * balls[j].m * mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact)))/(balls[i].m + balls[j].m)) * Math.cos(contact)) + (mag(balls[i].vel) * Math.sin(dir(balls[i].vel) - contact) * Math.cos(contact + (Math.PI/2))); 
 
       balls[i].vel.y = ((((mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact) * (balls[i].m - balls[j].m)) + (2 * balls[j].m * mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact)))/(balls[i].m + balls[j].m)) * Math.sin(contact)) + (mag(balls[i].vel) * Math.sin(dir(balls[i].vel) - contact) * Math.sin(contact + (Math.PI/2))); 
 

 
       balls[j].vel.x = -((((mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact) * (balls[j].m - balls[i].m)) + (2 * balls[i].m * mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact)))/(balls[j].m + balls[i].m)) * Math.cos(contact)) + (mag(balls[j].vel) * Math.sin(dir(balls[j].vel) - contact) * Math.cos(contact + (Math.PI/2))); 
 
       balls[j].vel.y = -((((mag(balls[j].vel) * Math.cos(dir(balls[j].vel) - contact) * (balls[j].m - balls[i].m)) + (2 * balls[i].m * mag(balls[i].vel) * Math.cos(dir(balls[i].vel) - contact)))/(balls[j].m + balls[i].m)) * Math.sin(contact)) + (mag(balls[j].vel) * Math.sin(dir(balls[j].vel) - contact) * Math.sin(contact + (Math.PI/2))); 
 
      } 
 
     } 
 
    } 
 

 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
    for(var i = 0; i < balls.length; i++){ 
 
     ctx.beginPath(); 
 

 
     if(balls[i].colliding){ 
 
      ctx.fillStyle = "#f00"; 
 
     }else{ 
 
      ctx.fillStyle = "#0f0"; 
 
     } 
 

 

 
     ctx.arc(balls[i].pos.x, balls[i].pos.y, balls[i].r, 0, 2 * Math.PI); 
 
     ctx.fill(); 
 
    } 
 
}, 16);
<!DOCTYPE html> 
 
<html lang="en"> 
 
    <head> 
 
     <meta charset="utf-8"> 
 
     <title></title> 
 
    </head> 
 
    <body> 
 
     <canvas id="canvas" width="640" height="480"></canvas> 
 
     <script src="main.js"></script> 
 
    </body> 
 
</html>

+0

(感謝ところで、didntは私が行うことができます知っている:)こと)プロトタイプを調べることをお勧めします。実際に使用されているいくつかの例が必要な場合は、ここでゲームのソースを確認してください - asteroidio.bitballoon.com –

関連する問題