在简单碰撞中包含动量守恒定律
Including the Law of Conservation of Momentum In a Simple Collision
我使用 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;
}
};
Processing 附带的示例之一恰好说明了这一点:使用动量守恒方程来计算多个球的速度。
该示例可用 here,或者您可以通过转至 File
-> 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;
}
}
我使用 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;
}
};
Processing 附带的示例之一恰好说明了这一点:使用动量守恒方程来计算多个球的速度。
该示例可用 here,或者您可以通过转至 File
-> 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;
}
}