簡體   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