Circle-Circle Collision sometimes fail

126 Views Asked by At

I'm aware of how to check if two circles are intersecting one another. However, sometimes the circles get stuck on each other and they'll start rotating.

How could I fix this?

This is my code:

FFIELD.Footballer = function(id, x, y, c, xn, yn) {
this.type = 'footballer';
this.ident = id;
this.x = x;   
this.r = 17;                
this.y = y;     
this.color = c;
this.moving = false;
this.xn = xn; 
this.yn = yn; 
this.vx = 0;
this.vy = 0;
this.sxy = [this.x, this.y]; 
this.lxy = [this.x, this.y]
this.wallsC = 0; 

//lenleft calculates speed using distance between start and endpoint    
//EXAMPLE OF USING SPEED in the update function:
//this.x += this.vx*this.speed;
//this.y += this.vy*this.speed;

this.lenleft = function() {
    //if any of walls was already hit
    if (this.wallsC != 0) {
        this.lxy = this.sxy;
        this.sxy = [this.x, this.y];
        this.raz = [(this.sxy[0] - this.lxy[0]) *0.1, (this.sxy[1] - this.lxy[1])*0.1];
        this.len = this.len - Math.sqrt(this.raz[0]* this.raz[0] + this.raz[1] * this.raz[1]);
        this.speed = this.len/6; 
    //if no walls were hit  
    } else {
        this.raz = [(this.xn - this.x)*0.1, (this.yn - this.y)*0.1];
        this.len = Math.sqrt(this.raz[0]* this.raz[0] + this.raz[1] * this.raz[1]);
        this.speed = this.len/6; 
    }
}

//if end point atribute is set
if(xn != null) {
    this.lenleft();        
    this.vx = this.raz[0] / this.len
    this.vy = this.raz[1] / this.len      
}      


this.deflect = function(i) {     

    //elastic collision
    nx = FFIELD.entities[i].x - this.x; 
    ny = FFIELD.entities[i].y - this.y;
    absn = Math.sqrt(Math.pow(nx,2) + Math.pow(ny,2));        
    nx = nx / absn;
    ny = ny / absn;
    scp = this.vx * nx + this.vy * ny;
    bcp = FFIELD.entities[i].vx * nx + FFIELD.entities[i].vy * ny;
    this.vx = this.vx - nx * scp + nx * bcp;
    this.vy = this.vy - ny * scp + ny * bcp;
    FFIELD.entities[i].vx = FFIELD.entities[i].vx + nx * scp - nx * bcp;
    FFIELD.entities[i].vy = FFIELD.entities[i].vy + ny * scp - ny * bcp;    

    // if this circle is not moving  
    if(scp == 0) {
        FFIELD.entities[i].lenleft();
        this.len = FFIELD.entities[i].len;        
        this.moving = true;
    }
    // if other circle is not moving  
    if(bcp == 0) {
        this.lenleft();
        FFIELD.entities[i].len = this.len;            
        FFIELD.entities[i].moving = true;
    }
    // if both circles are moving  
    else {
        this.lenleft();
        FFIELD.entities[i].lenleft();
    }
}

this.walls = function() {
    //keeping wallsC count because of lenleft function
    if (this.y <= 18) {            
        this.vy = this.vy * -1;             
        this.wallsC += 1;            
    }
    if (this.y >= FFIELD.HEIGHT - 18) {            
        this.vy = this.vy * -1; 
        this.wallsC += 1;
    }
    if (this.x <= 18) { 
        this.vx = this.vx * -1;              
        this.wallsC += 1;
    }
    if (this.x >= FFIELD.WIDTH - 18) { 
        this.vx = this.vx * -1;             
        this.wallsC += 1;
    }
}

this.move = function () {
    if (this.speed > 0) {                       
        this.moving = true;
    }
    else {
        this.vx = 0;
        this.vy = 0;
    }            

}

this.update = function() {

    for (var i = 0; i < FFIELD.entities.length; i++)  
    {  
            if (FFIELD.entities[i].ident != this.ident) {
                hit = FFIELD.collides({x: this.x, y: this.y, r: this.r}, FFIELD.entities[i]);                      
                if (hit) {  
                    this.deflect(i);
                }
            }
    }
    this.move();
    this.walls();

    if(this.moving) {  
        this.speed-=0.04;               
        this.x += this.vx*this.speed;
        this.y += this.vy*this.speed;                        
    }       
};

this.render = function() {
    FFIELD.Draw.circle(this.x, this.y, this.r, this.color);
};

};


// this function checks if two circles overlap
FFIELD.collides = function(a, b) {           
      return Math.abs((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) 
                                < (a.r + b.r) * (a.r + b.r);
};
0

There are 0 best solutions below