简体   繁体   English

圆圆摩擦碰撞

[英]Circle-circle collision with friction

I'm making a small game with javascript and what I want to do is to make 2 circles collide. 我正在用JavaScript做一个小游戏,我想做的是使2个圆圈碰撞。 I already can detect when they collide, I can calculate the exact time between 2 frames when they collide and I can let them collide without friction and rotation. 我已经可以检测到它们何时发生碰撞,可以计算出两帧发生碰撞之间的准确时间 ,并且可以让它们发生碰撞而不会产生摩擦和旋转。 Now I want to add some kind of friction so they will rotate after colliding. 现在,我想增加某种摩擦,以便它们在碰撞后旋转。

In my current code, I use a method in my Ball constructor to see if it will collide in the next frame. 在当前代码中,我在Ball构造函数中使用一个方法来查看它是否会在下一帧中发生冲突。 I also made a Vector2 object. 我也做了一个Vector2对象。

If you don't understand something of my code, feel free to ask. 如果您不了解我的代码,请随时提出。 This is the code I'm currently using: 这是我当前正在使用的代码:

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);
        }
    }
};

Let's say I have a variable frictionCo for the friction coefficient, how can I calculate the velocity and angular velocity (in rad/s) of the balls after the collision? 假设我的摩擦系数有一个摩擦系数Co,如何计算碰撞后球的速度和角速度(以弧度/秒为单位)?

My new code 我的新代码

I finally made my game as I wanted by adding friction. 最终,我通过增加摩擦来制作自己的游戏。 The linear velocity is affected by the radial velocity and vice versa. 线速度受径向速度的影响,反之亦然。

Here is my new code: 这是我的新代码:

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);
        }
    }
};

When the circles collide, they rub against each other and the friction creates a torque that changes the rotational speed of each circle. 当圆碰撞时,它们会相互摩擦,并且摩擦会产生扭矩,从而改变每个圆的旋转速度。 The forces will be equal and opposite, but the torques will depend on the individual radii. 力将相等且方向相反,但扭矩将取决于各个半径。 It's complicated to estimate how long they'll be in contact, but I'd just make up some rule and see how it goes, like the contact time is the same for all collisions. 估计他们将要接触多长时间是很复杂的,但是我只需要制定一些规则,然后看看它如何进行,就像所有碰撞的接触时间都一样。 So for some short time, the forces create torques, and the torques change the rotational speed based on the moment of inertia of the circle or disk. 因此,在短时间内,力会产生扭矩,并且扭矩会根据圆或圆盘的惯性矩来改变转速。

Some details on the frictional force are that: 1) it's usually well approximated as independent of speed, so the direction will always be to oppose the different in surface velocities, but the size won't scale with this velocity difference; 关于摩擦力的一些细节是:1)通常可以很好地近似为与速度无关,因此方向始终是与表面速度的不同相对,但是尺寸不会因该速度差而按比例缩放; 2) in general, friction will depend on the force of contact, which, in a detailed simulation would vary throughout the collision, but you could just estimate it as a constant for all collisions, or make it depend on, say, the total change in linear momentum (which is basically the time average of time impact force). 2)通常,摩擦力取决于接触力,在详细的模拟中,摩擦力会在整个碰撞过程中发生变化,但是您可以将其估算为所有碰撞的常数,或者使其取决于总的变化量。线性动量(基本上是时间冲击力的时间平均值)。

Response to comments: 对评论的回应:
It sounds like you're getting confused thinking about "friction". 听起来您对“摩擦”感到困惑。 Instead, think of friction only as a force applied tangential to the circle at its surface , and calculate the speeds from there (eg, write a function that changes the circle's speed for an arbitrary force vs time). 取而代之的是,仅将摩擦视为与圆在其表面上相切 ,然后从那里开始计算速度(例如,编写一个函数,以随时间变化的任意力改变圆的速度)。 Then separately calculate the frictional force and give this to the equation. 然后分别计算摩擦力并将其赋予方程式。 (Btw, you can't generally do this separation in simulations, but it's an added convenience because the frictional force is independent of speed -- though it's not completely independent since it stops changing the speed when the surface speeds match so watch for this small detail). (顺便说一句,您通常无法在模拟中进行这种分离,但这是一个额外的便利,因为摩擦力与速度无关-尽管它不是完全独立的,因为当表面速度匹配时它会停止改变速度,因此请注意这一点。详情)。

To calculate the resulting change in speed from the tangential frictional force, use standard rotational dynamics. 要根据切向摩擦力计算出速度的变化,请使用标准旋转动力学。 See, for example, here , or any other hits for "rotational dynamics". 参见,例如, here或“旋转动态”的其他任何命中。 Basically, it's like F=ma, except it's now Torque = (moment of interia) * (angular acceleration) . 基本上,它类似于F = ma,除了现在是Torque =(惯性矩)*(角加速度)。 Moment of inertia (I) is a constant for the object, use the frictional force to find the torque (Torque = F*R ), and to find the angular acceleration ( A = T/I ), and use the angular acceleration to find the total change in angular velocity, which will give you the new angular velocity. 惯性矩(I)对物体是一个常数,使用摩擦力找到扭矩(Torque = F * R),然后找到角加速度(A = T / I),然后使用角加速度来找到角速度的总变化,这将为您提供新的角速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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