我知道如何检查两个圆圈是否相互交叉。但是,有时圆圈会相互粘连,它们会开始旋转。
我该如何解决这个问题?
这是我的代码:
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);
};