包括简单碰撞中的动量守恒定律

时间:2016-03-10 03:30:42

标签: javascript processing physics processing.js

我使用JavaScript制作动画,基本上演示了当两个球池碰撞时会发生什么。但是,我想尽可能使其尽可能真实,这样它至少包括动量守恒定律(m1 * v1 + m2 * v2 = m1 * v1' + m2 * v2'),其中每个球的运动和速度都模仿了它在现实生活中的实际运动。在我目前的代码中,我有一定的值可以保持球的速度和方向,但通过这种方式,这是不现实的,如果我要改变它的任何当前值,代码会出现故障(球会从屏幕上移开,会无限地来回反弹等)有没有办法设置我的代码,以便在每个球池的运动和速度中实现动量守恒定律?

//initializes pool stick
var pole = 0;
//initializes cue ball position (y)
var white = 250;
//starting position of yellow (x)
var x = 200;
//starting position of yellow (y)
var y = 141;
//initial velocity of white 
var whitespeed=0;
var xspeed = 0;
var yspeed = -2;
var draw = function() {
//color of pool table floor
background(0, 0, 0);
//color of barrier
fill(5, 54, 32);
//takes out all lines from joined shapes
noStroke();
//design dimensions for the barriers/hole openings
triangle(80, 46, 93, 31, 58, 31);
triangle(322, 47, 344, 31, 267, 31);
triangle(320, 369, 343, 369, 320, 353);
triangle(80, 353, 57, 369, 90, 369);
rect(79, 353, 242, 16);
rect(80, 31, 242, 16);
rect(31, 83, 16, 237);
rect(352, 83, 16, 237);
triangle(31, 43, 31, 85, 47, 85);
triangle(368, 64, 368, 85, 352, 84);
triangle(31, 343, 47, 320, 31, 307);
triangle(368, 342, 368, 317, 352, 320);
//outline color of the barriers
stroke(11, 145, 114);
//controls speed and path of both the cue and yellow balls
if(white<=160){
    whitespeed += whitespeed;
    whitespeed += xspeed;
    whitespeed += yspeed;

    y += yspeed;
if(white<165) {
    xspeed = 3;
    whitespeed = 1;
}
if(x>349) {
    xspeed = -1;
    yspeed = -1;
    whitespeed = 0;
}
if(x<59) {
    xspeed = -1;
    yspeed = -1;
    whitespeed = 0;
}
if(y<52) {
    yspeed = -1;
    xspeed = -1;
    whitespeed = 0;
} 
if(y>350) {
    yspeed = 1;
    xspeed = 1;
    whitespeed = 0;
}
if(x>350){
    yspeed = 1;
    xspeed = 1;
    whitespeed = 0;
}
if(x<65 || y<58){
    xspeed = 2;
    yspeed = 0;
    whitespeed = 0;
}
}
//White Ball Dimensions/Properties
fill(255, 255, 255);
ellipse(200, white, 20, 20);
white -= whitespeed;
//Yellow Ball  
fill(243, 250, 40);
ellipse(x, y, 20, 20);
//Table Details and Colors
fill(0, 0, 0);
rect(0, 57, 30, 292);
rect(368, 57, 30, 292);
rect(50, 0, 295, 30);
rect(50, 369, 295, 30);
fill(43, 227, 172);
rect(0, 0, 50, 58);
rect(345, 0, 57, 58);
rect(0, 345, 50, 58);
rect(345, 345, 56, 58);
ellipse(16, 77, 5, 5);
ellipse(16, 111, 5, 5);
ellipse(16, 149, 5, 5);
ellipse(16, 248, 5, 5);
ellipse(16, 281, 5, 5);
ellipse(16, 315, 5, 5);
ellipse(109, 18, 5, 5);
ellipse(196, 18, 5, 5);
ellipse(284, 18, 5, 5);
ellipse(109, 382, 5, 5);
ellipse(196, 382, 5, 5);
ellipse(284, 382, 5, 5);
ellipse(382, 77, 5, 5);
ellipse(382, 111, 5, 5);
ellipse(382, 149, 5, 5);
ellipse(382, 248, 5, 5);
ellipse(382, 281, 5, 5);
ellipse(382, 315, 5, 5);
//Table Hole Details
fill(0, 0, 0);
stroke(0, 0, 0);
ellipse(40, 41, 41, 43);
ellipse(360, 43, 41, 43);
ellipse(37, 362, 41, 43);
ellipse(358, 359, 38, 39);
ellipse(373, 200, 27, 39);
ellipse(25, 200, 27, 39); 
fill(43, 227, 172);
ellipse(43, 44, 36, 39);
ellipse(358, 46, 36, 39);
ellipse(40, 359, 36, 39);
ellipse(355, 355, 36, 39);
ellipse(371, 201, 36, 39);
ellipse(28, 201, 36, 39);
// Cue Details
fill(245, 183, 76);
rect(200, mouseY, 6, 235);
fill(255, 255, 255);
rect(200, mouseY, 6, 8);
fill(163, 106, 36);
rect(200, mouseY+139, 6, 96);
fill(0, 0, 0);
rect(200, mouseY, 6, -1);
//Speed of white ball before collision/Mouse movement
if(mouseY<260){
    whitespeed = 6;
}


};

1 个答案:

答案 0 :(得分:0)

Processing附带的一个例子就是这样:使用动量守恒方程来计算多个球的速度。

该示例可用here,或者您可以通过转到File - &gt;从处理编辑器运行它。 Examples

该示例包含相当多的代码,但有趣的部分是:

void checkCollision(Ball other) {

    // get distances between the balls components
    PVector bVect = PVector.sub(other.position, position);

    // calculate magnitude of the vector separating the balls
    float bVectMag = bVect.mag();

    if (bVectMag < r + other.r) {
      // get angle of bVect
      float theta  = bVect.heading();
      // precalculate trig values
      float sine = sin(theta);
      float cosine = cos(theta);

      /* bTemp will hold rotated ball positions. You 
       just need to worry about bTemp[1] position*/
      PVector[] bTemp = {
        new PVector(), new PVector()
        };

        /* this ball's position is relative to the other
         so you can use the vector between them (bVect) as the 
         reference point in the rotation expressions.
         bTemp[0].position.x and bTemp[0].position.y will initialize
         automatically to 0.0, which is what you want
         since b[1] will rotate around b[0] */
        bTemp[1].x  = cosine * bVect.x + sine * bVect.y;
      bTemp[1].y  = cosine * bVect.y - sine * bVect.x;

      // rotate Temporary velocities
      PVector[] vTemp = {
        new PVector(), new PVector()
        };

        vTemp[0].x  = cosine * velocity.x + sine * velocity.y;
      vTemp[0].y  = cosine * velocity.y - sine * velocity.x;
      vTemp[1].x  = cosine * other.velocity.x + sine * other.velocity.y;
      vTemp[1].y  = cosine * other.velocity.y - sine * other.velocity.x;

      /* Now that velocities are rotated, you can use 1D
       conservation of momentum equations to calculate 
       the final velocity along the x-axis. */
      PVector[] vFinal = {  
        new PVector(), new PVector()
        };

      // final rotated velocity for b[0]
      vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
      vFinal[0].y = vTemp[0].y;

      // final rotated velocity for b[0]
      vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m);
      vFinal[1].y = vTemp[1].y;

      // hack to avoid clumping
      bTemp[0].x += vFinal[0].x;
      bTemp[1].x += vFinal[1].x;

      /* Rotate ball positions and velocities back
       Reverse signs in trig expressions to rotate 
       in the opposite direction */
      // rotate balls
      PVector[] bFinal = { 
        new PVector(), new PVector()
        };

      bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
      bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
      bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
      bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;

      // update balls to screen position
      other.position.x = position.x + bFinal[1].x;
      other.position.y = position.y + bFinal[1].y;

      position.add(bFinal[0]);

      // update velocities
      velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
      velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
      other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
      other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
    }
  }