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를 반전하고 충돌 시스템은 잘 작동하는 것 같군. 그러나주의 깊게 살펴보면 언급 한 것처럼 멈추는 것을 볼 수 있습니다. 공이 틱당 하나 이상의 픽셀을 이동하여 볼이 다른 픽셀 내부로 이동하게되어 충돌이 반복 될 때까지 계속 충돌 할 것입니다. 안에 있지 않습니다. 이를 방지하려면 거리가 결합 된 반지름보다 작 으면 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

(감사 BTW, didnt가 내가 할 수있는 알고 : 그) 프로토 타입을 살펴 보는 것이 좋습니다. 실제로 사용 된 몇 가지 예를 원하면 여기에서 게임 소스를 확인하십시오 - asteroidio.bitballoon.com –

관련 문제