圆圈与摩擦碰撞

时间:2014-02-25 16:50:53

标签: javascript rotation 2d physics collision

我正在用javascript制作一个小游戏,我想做的是让2个圆圈碰撞。我已经可以检测到碰撞时,我可以计算碰撞时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);
        }
    }
};

假设我的摩擦系数有一个变摩擦力,如何计算碰撞后球的速度和角速度(以rad / s为单位)?

我的新代码

我终于通过添加摩擦来制作我想要的游戏。线速度受径向速度的影响,反之亦然。

这是我的新代码:

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 个答案:

答案 0 :(得分:2)

当圆圈碰撞时,它们相互摩擦,摩擦产生扭矩,改变每个圆圈的旋转速度。力将是相等和相反的,但扭矩将取决于各个半径。估计他们接触的时间有多复杂,但我只是制定一些规则并看看它是如何进行的,就像所有碰撞的接触时间都是一样的。因此,在短时间内,力会产生扭矩,扭矩会根据圆或圆盘的惯性矩改变旋转速度。

关于摩擦力的一些细节是:1)它通常很接近于与速度无关,因此方向总是反对不同的表面速度,但尺寸不会随着速度差而缩放; 2)一般来说,摩擦力取决于接触力,在整个碰撞过程中,详细模拟会发生变化,但你可以将其估算为所有碰撞的常数,或者使其依赖于总变化线性动量(基本上是时间冲击力的时间平均值)。

对评论的回应:
听起来你对“摩擦”的思考感到困惑。相反,将摩擦仅视为与其表面处的圆相切的力,并从那里计算速度(例如,编写一个函数,可以改变圆的速度以获得任意力与时间的关系)。然后分别计算摩擦力并将其计算出来。 (顺便说一句,你通常不能在模拟中进行这种分离,但它更方便,因为摩擦力与速度无关 - 虽然它不是完全独立的,因为它在表面速度匹配时停止改变速度所以注意这个小细节)。

要根据切向摩擦力计算速度的变化,请使用标准旋转动力学。例如,参见here或“旋转动力学”的任何其他命中。基本上,它就像F = ma,除了它现在是Torque =(interia的时刻)*(角加速度)。转动惯量(I)是物体的常数,用摩擦力求扭矩(Torque = F * R),并找出角加速度(A = T / I),并用角加速度找到角速度的总变化,它将为您提供新的角速度。