[英]Circle-circle collision with friction
我正在用JavaScript做一个小游戏,我想做的是使2个圆圈碰撞。 我已经可以检测到它们何时发生碰撞,可以计算出两帧发生碰撞之间的准确时间 ,并且可以让它们发生碰撞而不会产生摩擦和旋转。 现在,我想增加某种摩擦,以便它们在碰撞后旋转。
在当前代码中,我在Ball构造函数中使用一个方法来查看它是否会在下一帧中发生冲突。 我也做了一个Vector2对象。
如果您不了解我的代码,请随时提出。 这是我当前正在使用的代码:
this.checkCollision=function(ball,delta){
var that=this;
var radii=this.r+ball.r;
var rVelA=Vector2.scale(this.v,delta); //the velocity per frame
var rVelB=Vector2.scale(ball.v,delta);
var A=function(t){return Vector2.add(that.p,Vector2.scale(rVelA,t));}; //position in function of time
var B=function(t){return Vector2.add(ball.p,Vector2.scale(rVelB,t));}; //position in function of time
var P=Vector2.substract(this.p,ball.p); //relative position
var V=Vector2.substract(rVelA,rVelB); //relative velocity
var a=V.getSLength();
var b=2*(P.x*V.x+P.y*V.y);
var c=P.getSLength()-radii*radii;
var D=b*b-4*a*c;
if(D>=0){
var t=(-b-Math.sqrt(D))/(2*a);
if(t<=1&&t>=0){
var x,y;
P=A(t); //position of ball A on collision
var Q=B(t); //position of ball B on collision
x=(Q.x-P.x)/radii;
y=(Q.y-P.y)/radii;
var newXvA=x*x*ball.v.x+x*y*ball.v.y+y*y*that.v.x-y*x*that.v.y;
var newYvA=x*y*ball.v.x+y*y*ball.v.y-x*y*that.v.x+x*x*that.v.y;
var newXvB=x*x*that.v.x+x*y*that.v.y+y*y*ball.v.x-y*x*ball.v.y;
var newYvB=x*y*that.v.x+y*y*that.v.y-x*y*ball.v.x+x*x*ball.v.y;
//Collider(ball object, collision position, previous velocity, new velocity)
var colliderA=new Collider(this,P,that.v.clone(),new Vector2(newXvA,newYvA));
var colliderB=new Collider(ball,Q,ball.v.clone(),new Vector2(newXvB,newYvB));
//Collision(collider A, collider B, collision time)
return new Collision(colliderA,colliderB,t);
}
}
};
假设我的摩擦系数有一个摩擦系数Co,如何计算碰撞后球的速度和角速度(以弧度/秒为单位)?
最终,我通过增加摩擦来制作自己的游戏。 线速度受径向速度的影响,反之亦然。
这是我的新代码:
this.checkCollision=function(ball,delta){
var that=this;
var radii=this.r+ball.r;
var rVelA=Vector2.scale(this.v,delta); //the velocity per frame
var rVelB=Vector2.scale(ball.v,delta);
var A=function(t){return Vector2.add(that.p,Vector2.scale(rVelA,t));}; //position in function of time
var B=function(t){return Vector2.add(ball.p,Vector2.scale(rVelB,t));};
var P=Vector2.substract(this.p,ball.p); //relative position
var V=Vector2.substract(rVelA,rVelB); //relative velocity
var a=V.getSLength();
var b=2*(P.x*V.x+P.y*V.y);
var c=P.getSLength()-radii*radii;
var D=b*b-4*a*c;
if(D>=0){
var t=(-b-Math.sqrt(D))/(2*a);
if(t<=1&&t>=0){
var x,y;
P=A(t); //position of first ball on collision
var Q=B(t); //position of other ball on collision
var angle=Math.atan2(Q.y-P.y,Q.x-P.x);
var rotVA=this.v.clone().rotate(-angle); //rotate so they collide straight (rotated velocity of A)
var rotVB=ball.v.clone().rotate(-angle);
var IA=this.mass*this.r*this.r/2; //Inertia
var IB=this.mass*this.r*this.r/2;
var vt=rotVA.y+this.rotV*this.r-rotVB.y+ball.rotV*ball.r;
var s=Math.sign(vt);
var x=2*(rotVA.x-rotVB.x)/(1/this.mass+1/ball.mass);
var dvt=-x*s*frictionCo*(3/this.mass+3/ball.mass);
if(-s*dvt>s*vt){
s*=-vt/dvt; //if they stop rotating to adjust the friction
}
var newVA=Vector2.add(rotVA,new Vector2(-x/this.mass,-s*frictionCo*x/this.mass)).rotate(angle);
var newVB=Vector2.add(rotVB,new Vector2(x/ball.mass,s*frictionCo*x/ball.mass)).rotate(angle);
var newRotA=this.rotV-s*frictionCo*this.r*x/IA;
var newRotB=ball.rotV-s*frictionCo*ball.r*x/IB;
//Collider(ball object, collision position, previous velocity, new velocity, new radial velocity)
var colliderA=new Collider(this,P,that.v.clone(),newVA,newRotA);
var colliderB=new Collider(ball,Q,ball.v.clone(),newVB,newRotB);
//Collision(collider A, collider B, collision time)
return new Collision(colliderA,colliderB,t);
}
}
};
当圆碰撞时,它们会相互摩擦,并且摩擦会产生扭矩,从而改变每个圆的旋转速度。 力将相等且方向相反,但扭矩将取决于各个半径。 估计他们将要接触多长时间是很复杂的,但是我只需要制定一些规则,然后看看它如何进行,就像所有碰撞的接触时间都一样。 因此,在短时间内,力会产生扭矩,并且扭矩会根据圆或圆盘的惯性矩来改变转速。
关于摩擦力的一些细节是:1)通常可以很好地近似为与速度无关,因此方向始终是与表面速度的不同相对,但是尺寸不会因该速度差而按比例缩放; 2)通常,摩擦力取决于接触力,在详细的模拟中,摩擦力会在整个碰撞过程中发生变化,但是您可以将其估算为所有碰撞的常数,或者使其取决于总的变化量。线性动量(基本上是时间冲击力的时间平均值)。
对评论的回应:
听起来您对“摩擦”感到困惑。 取而代之的是,仅将摩擦视为与圆在其表面上相切的力 ,然后从那里开始计算速度(例如,编写一个函数,以随时间变化的任意力改变圆的速度)。 然后分别计算摩擦力并将其赋予方程式。 (顺便说一句,您通常无法在模拟中进行这种分离,但这是一个额外的便利,因为摩擦力与速度无关-尽管它不是完全独立的,因为当表面速度匹配时它会停止改变速度,因此请注意这一点。详情)。
要根据切向摩擦力计算出速度的变化,请使用标准旋转动力学。 参见,例如, here或“旋转动态”的其他任何命中。 基本上,它类似于F = ma,除了现在是Torque =(惯性矩)*(角加速度)。 惯性矩(I)对物体是一个常数,使用摩擦力找到扭矩(Torque = F * R),然后找到角加速度(A = T / I),然后使用角加速度来找到角速度的总变化,这将为您提供新的角速度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.