所以,我有这个简单的 2d train sim,并且我已经完成了一个非常好的 SAT 实现,它可以正常工作(至少我没有偶然发现任何错误):
function calcCollision(self){
var dist = self.distanceCheck();
var possible = [], collision = [];
var myBox, otherBox, myMin, myMax, otherMin, otherMax, myBoxRecalc = [], otherBoxRecalc = [];
for (var i=0;i<trainCount;i++){
if (dist[i]!="SELF"&&dist[i]<=(dTrain+10)){
possible.push(i);
}
}
if (possible.length!==0){
myBox = self.box();
self.hit = false;
for (i=0;i<possible.length;i++){
otherBox = window["train_"+possible[i]].box();
//для self координат
for (var j=0;j<4;j++){
myBoxRecalc[j] = XYtoBoxCoordinates(self,myBox[j][0],myBox[j][1]);
otherBoxRecalc[j] = XYtoBoxCoordinates(self,otherBox[j][0],otherBox[j][1]);
}
//для self координат, проекция на X
myMin = myBoxRecalc[0][0];
myMax = myBoxRecalc[0][0];
otherMin = otherBoxRecalc[0][0];
otherMax = otherBoxRecalc[0][0];
for (j=0;j<4;j++){
if (myBoxRecalc[j][0]<myMin) myMin=myBoxRecalc[j][0];
if (myBoxRecalc[j][0]>myMax) myMax=myBoxRecalc[j][0];
if (otherBoxRecalc[j][0]<otherMin) otherMin=otherBoxRecalc[j][0];
if (otherBoxRecalc[j][0]>otherMax) otherMax=otherBoxRecalc[j][0];
}
//console.log(myMin + " " + myMax + " " + otherMin + " " + otherMax);
if (otherMax<myMin||otherMin>myMax) break;
//для self координат, проекция на Y
myMin = myBoxRecalc[0][1];
myMax = myBoxRecalc[0][1];
otherMin = otherBoxRecalc[0][1];
otherMax = otherBoxRecalc[0][1];
for (j=0;j<4;j++){
if (myBoxRecalc[j][1]<myMin) myMin=myBoxRecalc[j][1];
if (myBoxRecalc[j][1]>myMax) myMax=myBoxRecalc[j][1];
if (otherBoxRecalc[j][1]<otherMin) otherMin=otherBoxRecalc[j][1];
if (otherBoxRecalc[j][1]>otherMax) otherMax=otherBoxRecalc[j][1];
}
//console.log(myMin + " " + myMax + " " + otherMin + " " + otherMax);
if (otherMax<myMin||otherMin>myMax) break;
//для other координат
for (j=0;j<4;j++){
myBoxRecalc[j] = XYtoBoxCoordinates(window["train_"+possible[i]],myBox[j][0],myBox[j][1]);
otherBoxRecalc[j] = XYtoBoxCoordinates(window["train_"+possible[i]],otherBox[j][0],otherBox[j][1]);
}
//для other координат, проекция на X
myMin = myBoxRecalc[0][0];
myMax = myBoxRecalc[0][0];
otherMin = otherBoxRecalc[0][0];
otherMax = otherBoxRecalc[0][0];
for (j=0;j<4;j++){
if (myBoxRecalc[j][0]<myMin) myMin=myBoxRecalc[j][0];
if (myBoxRecalc[j][0]>myMax) myMax=myBoxRecalc[j][0];
if (otherBoxRecalc[j][0]<otherMin) otherMin=otherBoxRecalc[j][0];
if (otherBoxRecalc[j][0]>otherMax) otherMax=otherBoxRecalc[j][0];
}
//console.log(myMin + " " + myMax + " " + otherMin + " " + otherMax);
if (otherMax<myMin||otherMin>myMax) break;
//для other координат, проекция на Y
myMin = myBoxRecalc[0][1];
myMax = myBoxRecalc[0][1];
otherMin = otherBoxRecalc[0][1];
otherMax = otherBoxRecalc[0][1];
for (j=0;j<4;j++){
if (myBoxRecalc[j][1]<myMin) myMin=myBoxRecalc[j][1];
if (myBoxRecalc[j][1]>myMax) myMax=myBoxRecalc[j][1];
if (otherBoxRecalc[j][1]<otherMin) otherMin=otherBoxRecalc[j][1];
if (otherBoxRecalc[j][1]>otherMax) otherMax=otherBoxRecalc[j][1];
}
//console.log(myMin + " " + myMax + " " + otherMin + " " + otherMax);
if (otherMax<myMin||otherMin>myMax) break;
collision.push(possible[i]);
}
} else return false;
if (collision.length!==0){
self.hit = true;
return collision;
} else return false;
}
它检测可能的碰撞对象self
并在发生碰撞时返回它们的 ID。正如我已经说过的,它工作得很好。之后问题出现了,当我试图对碰撞产生反应时。我已经在算法上苦苦挣扎了将近一周,这是我想出的最佳解决方案:
function moveCollided(){
for (var i = 0; i < trainCount; i++) {
var banged = calcCollision(window["train_"+i]);
//console.log(banged);
if (window["train_"+i].hit){
window["train_"+i].speed -= (window["train_"+i].speed/3);
for (var j = 0; j < banged.length; j++) {
window["train_"+banged[j]].speed += calcSpeedIncrement(window["train_"+i],window["train_"+banged[j]]);
}
}
}
setTimeout(moveCollided, 15);
}
这个函数降低了火车的速度,并calcSpeedIncrement(self,other)
为它撞到的火车增加了一些速度( )。我在笔直的轨道上得到了很好的碰撞效果,但是如果你继续向前推进,一列火车就会滑过另一列。同样“滑过”的另一个问题是当其中一列火车站在转弯处时发生碰撞。
有没有人对如何解决这些问题有任何想法?