由于要写一个模拟多个小球相互碰撞的程序,所以我就研究了下两个小球相互碰撞之后的速度变化规律(理想环境下无摩擦无碰撞损耗等的完全弹性碰撞)。
我们都知道,两个小球如果是在同一条直线上相向而行,则我们可以通过能量守恒(动能守恒)和动量守恒来计算碰撞之后的速度,若两小球质量相等,则交换它们的速度。若质量不相等,则可以求出:
设两小球的质量为m1,m2,碰撞前速度为v1,v2,碰撞后速度为v'1,v'2。
则有以下两个公式同时成立:
m1 * v1 + m2 * v2 = m1 * v'1 + m2 * v'2 ---------------------------------------------------------------------(1)
1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * v'1^2 + 1/2 * m2 * v'2^2 -----------------------------(2)
(1)、(2)可化为:
m1 * v1 - m1 * v'1 = m2 * v'2 - m2 * v2 ----------------------------------------------------------------------(3)
1/2 * m1 * v1^2 - 1/2 * m1 * v'1^2 = 1/2 * m2 * v'2^2 - 1/2 * m2 * v2^2 -----------------------------(4)
(4)/(3)得:
v1 + v'1 = v2 + v'2 -------------------------------------------------------------------------------------------------(5)
(1)、(5)可化为:
m2 * v'2 = m1 * v1 + m2 * v2 - m1 * v'1 ---------------------------------------------------------------------(6)
v'2 = v1 + v'1 - v2 --------------------------------------------------------------------------------------------------(7)
把(7)代入(6)得:
m2 * v1 + m2 * v'1 - m2 * v2 = m1 * v1 + m2 * v2 - m1 * v'1 -------------------------------------------(8)
由(8)化简得:
v'1 = [ 2 * m2 * v2 + ( m1 - m2 ) * v1 ] / ( m1 + m2 )
同理可得:
v'2 = [ 2 * m1 * v1 + ( m2 - m1 ) * v2 ] / ( m1 + m2 )
这样就计算出碰撞后两小球的速度了。
但是,两小球能在同一直线上相向而行的概率基本为零,最常发生的碰撞则是这样的:
所以,我们得想办法把这样的碰撞情况转化为我们会处理的情况,加以计算。
那么我们来分析一下:
两小球的碰撞点在两球心的连线上,那么在理想状态下,两小球的相互作用力应该是沿着两球心的连线方向的。
根据牛顿第一定律,力是改变屋里运动状态的唯一原因,既然在垂直于两球心的连线的方向上没有力的作用,那么两小球在垂直于两球心的连线的方向上的分运动是不变的。
这样的话,两小球在垂直于两球心的连线的方向上的速度是不变的,那么同样这个方向上的动量和动能也是不变的。
那么,两小球在两球心的连线方向的分运动也遵循动量守恒和动能守恒。
这样,我们就能把一般碰撞事件转化为我们可以解决的在同一条直线上相向而行的碰撞事件来进行计算了。
现在,我们来分析一下分速度应该如何计算。
设小球速度为a,两球心连线为b,小球速度在两球心连线方向上的分速度为c,小球速度在垂直于两球心连线的方向上的分速度为d。
那么a · b = ( c + d ) · b = c · b + d · b。
而d与b相互垂直,所以d · b = 0。
那么a · b = c · b。
设b的斜率为k,那么可以再设a = ( x1, y1 ),b = ( x2, k · x2 ),c = ( x, k · x ),
那么代入得:
x1 · x2 + y1 · ( k · x2 ) = x · x2 + ( k · x ) · ( k · x2 )。
x = ( x1 · x2 + k · y1 · x2 ) / ( x2 + k^2 · x2 )
x = ( x1 + k · y1 ) / ( k^2 + 1 )
那么k · x为:
k · x = k · ( x1 + k · y1 ) / ( k^2 + 1 )
k · x = ( x1 + k · y1 ) / ( k + 1 / k )
现在回过头来,把这个公式代入小球的数据:
设碰撞时,小球1的速度为( v1x, v1y ),位置为( x1, y1 );小球2的速度为( v1x, v1y ),位置为( x2, y2 ),两球心连线方向的斜率为k。
那么小球1在两球心连线方向上的分速度v1_1,
它在x轴方向的分速度为:
v1_1x = ( v1x + k · v1y ) / ( k^2 + 1 )
它在x轴方向的分速度为:
v1_1y = k * v1_1x = ( v1x + k · v1y ) / ( k + 1 / k )
即:
v1_1 = ( ( v1x + k · v1y ) / ( k^2 + 1 ), ( v1x + k · v1y ) / ( k + 1 / k ) )
那么小球1在垂直于两球心连线的方向上的分速度v1_0,
它在x轴方向的分速度为:
v1_0x = v1x - v1_1x = v1x - ( v1x + k · v1y ) / ( k^2 + 1 )
它在x轴方向的分速度为:
v1_0y = v1y - v1_1y = v1y - ( v1x + k · v1y ) / ( k + 1 / k )
即:
v1_0 = ( v1x - ( v1x + k · v1y ) / ( k^2 + 1 ), v1y - ( v1x + k · v1y ) / ( k + 1 / k ) )
同理,小球2在两球心连线方向上的分速度为:
v2_1 = ( v2_1x, v2_1y ) = ( ( v2x + k · v2y ) / ( k^2 + 1 ), ( v2x + k · v2y ) / ( k + 1 / k ) )
小球2在垂直于两球心连线的方向上的分速度为:
v2_0 = ( v2_0x, v2_0y ) = ( v2x - ( v2x + k · v2y ) / ( k^2 + 1 ), v2y - ( v2x + k · v2y ) / ( k + 1 / k ) )
经过计算,我们可以得到碰撞后两小球在两球心连线方向上的分速度v_1_1,v_2_1。
那么碰撞后两小球的速度为v_1 = v1_0 + v_1_1,v_2 = v2_0 + v_2_1。
当然,若写成代码则不需要那么麻烦,只要定义几个中间变量,这些结果都可以由计算机计算(当然,下面的代码只是理想状况下的,因为线程的刷新是有间隔的,那么就会出现两小球边缘越过相切,达到相交的状态,解决这个问题还是相当简单的,自己去考虑吧。):
public void bumpEachother(Ball ball1, Ball ball2) { //获取两小球的质量 float m1 = ball1.getM(); float m2 = ball2.getM(); //获取两小球的位置 Point2D.Float position1 = ball1.getPosition(); Point2D.Float position2 = ball2.getPosition(); //获取两小球的速度 Point2D.Float velocity1 = ball1.getVelocity(); Point2D.Float velocity2 = ball2.getVelocity(); //定义碰撞后两小球的速度 Point2D.Float velocity_1 = new Point2D.Float(); Point2D.Float velocity_2 = new Point2D.Float(); //定义两小球在垂直于两球心连线的方向的速度 Point2D.Float velocity1_0 = new Point2D.Float(); Point2D.Float velocity2_0 = new Point2D.Float(); //定义碰撞前两小球在两球心连线方向的速度 Point2D.Float velocity1_1 = new Point2D.Float(); Point2D.Float velocity2_1 = new Point2D.Float(); //定义碰撞后两小球在两球心连线方向的速度 Point2D.Float velocity_1_1 = new Point2D.Float(); Point2D.Float velocity_2_1 = new Point2D.Float(); //定义两球心连线的斜率为k float k = (position1.y - position2.y) / (position1.x - position2.x); //计算碰撞前两小球在两球心连线方向的速度 velocity1_1.x = (velocity1.x + k * velocity1.y) / (1 + k * k); velocity1_1.y = k * velocity1_1.x; velocity2_1.x = (velocity2.x + k * velocity2.y) / (1 + k * k); velocity2_1.y = k * velocity2_1.x; //计算两小球在垂直于两球心连线的方向的速度 velocity1_0.x = velocity1.x - velocity1_1.x; velocity1_0.y = velocity1.y - velocity1_1.y; velocity2_0.x = velocity2.x - velocity2_1.x; velocity2_0.y = velocity2.y - velocity2_1.y; //计算碰撞后两小球在两球心连线方向的速度 velocity_1_1.x = (2 * m2 * velocity2_1.x + (m1 - m2) * velocity1_1.x) / (m1 + m2); velocity_1_1.y = (2 * m2 * velocity2_1.y + (m1 - m2) * velocity1_1.y) / (m1 + m2); velocity_2_1.x = (2 * m1 * velocity1_1.x + (m2 - m1) * velocity2_1.x) / (m1 + m2); velocity_2_1.y = (2 * m1 * velocity1_1.y + (m2 - m1) * velocity2_1.y) / (m1 + m2); //计算碰撞后两小球的速度 velocity_1.x = velocity1_0.x + velocity_1_1.x; velocity_1.y = velocity1_0.y + velocity_1_1.y; velocity_2.x = velocity2_0.x + velocity_2_1.x; velocity_2.y = velocity2_0.y + velocity_2_1.y; //重设两小球速度 ball1.setVelocity(velocity_1); ball2.setVelocity(velocity_2); }
好了,这样的话,两小球之间的相互碰撞事件的处理就完成啦,只要判断出两小球相撞,就可以调用这个类来改变小球速度啦~~
有人要Ball类的代码,我找了半天才找到,毕竟已经过了这么久了,不一定是一个版本的,不知道有没有问题……
import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; /** * @author lolo * */ public class Ball { //小球半径 private float radius; //小球位置 private Point2D.Float position; //小球速度 private Point2D.Float velocity; //小球形状 private Ellipse2D.Float sphere; /** * 构造方法 * * @param radius the radius to set * @param density the density to set * @param position the position to set * @param velocity the velocity to set */ public Ball(float radius, float density, Point2D.Float position, Point2D.Float velocity) { this.radius = radius; this.position = position; this.velocity = velocity; this.sphere = new Ellipse2D.Float(0, 0, 2 * radius, 2 * radius); } /** * 绘制小球 * * @param g the Graphics2D which is used to draw */ public void drawBall(Graphics2D g){ sphere.x = position.x - radius; sphere.y = position.y - radius; g.fill(sphere); } /** * @return the radius */ public float getRadius() { return radius; } /** * @return the position */ public Point2D.Float getPosition() { return position; } /** * @param position the position to set */ public void setPosition(Point2D.Float position) { this.position = position; } /** * @param positionX the position.x to set */ public void setPositionX(float positionX) { this.position.x = positionX; } /** * @param positionY the position.y to set */ public void setPositionY(float positionY) { this.position.y = positionY; } /** * @return the velocity */ public Point2D.Float getVelocity() { return velocity; } /** * @param velocity the velocity to set */ public void setVelocity(Point2D.Float velocity) { this.velocity = velocity; } /** * @param velocityX the velocity.x to set */ public void setVelocityX(float velocityX) { this.velocity.x = velocityX; } /** * @param velocityY the velocity.y to set */ public void setVelocityY(float velocityY) { this.velocity.y = velocityY; } }
相关推荐
C++ 小球碰撞 C++ 小球碰撞 C++ 小球碰撞
小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 小球碰撞 课程设计 ...
输入小球的数量,大小及速度后,点击完成进入运行模态框,点击初始后,点击运行即可
小球的碰撞时互相能量交换 含代码
利用VC++6.0 MFC 模拟小球碰撞过程,可设置两个小球的速度
js html5 canvas制作多个小球碰撞的动画效果 js html5 canvas制作多个小球碰撞的动画效果
有两个小球,第一个小球竖直下落,直到与下方静止的小球相切碰撞后,静止的小球水平移动,下落的小球停止
小球碰撞叠加html5
两个小球相向碰撞后反弹,其中有按钮的控制,可以随时停止,随时播放,只要是学习按钮的使用
两个代码,用matlab分别演示单个小球在方框内发生完全弹性碰撞和3个小球在方框内发生完全弹性碰撞(考虑小球之间碰撞),每次碰撞都显示对应冲量。
java小球碰撞边框反弹并且互相碰撞消失
一个小游戏,游戏中玩家通过触屏产生小球,触碰的时间控制小球的大小,释放时的...小球产生过程中被其它小球碰撞则游戏结束。游戏任务是产生有限个小球占满一定比例的空间。游戏中会有各种小道具帮助玩家完成任务……
不可控制小球的运动,可在manyballs类中随意改变小球的个数
Java 小球碰撞 碰撞检测 碰撞引擎,看了一些网上的例子,然后实现了一种小球碰撞的算法,是使用平面向量和冲量守恒完成的。
用C语言写的两个小球碰撞后反弹的程序,可以稍加修改成为自己的程序,希望您能够继续完善算法。
四个小球在一定区域相互碰撞,满足动量定理,设计微分方程求解以及循环语句的运用
该小程序是用Visual 中的OPENGL 做的三维小球碰撞程序,特别适合新入门者学习借鉴。
opengl 实现多个小球的碰撞和反弹模拟,小球的数目可以自己确定
本程序实现的游戏规则...运动的小球碰到上边缘、左边缘、右边缘、和9个固定位置的小球都会发生碰撞反弹。如果运动的小球将屏幕上9个固定位置的小球全部打掉,则玩家获胜;如果小球掉出下边缘,则玩家失败,游戏结束。
MFC对话框程序实现的小球碰撞演示实验。