繁体   English   中英

圆圆摩擦碰撞

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM