问题
So, I have this simple 2d train sim, and I already made a pretty nice SAT realisation, that works without errors (at least I have not stumbled upon any):
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;
}
It detects possible collision objects for self
and returns their ID's if there is a collision. As I already said, it works just fine. The problem appears after that, when i'm trying to create a reaction on the collision. I've been struggling over the algorithm for almost a week, and that's the best solution that I came up with:
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);
}
This function decreases the speed of the train, and adds some speed (calcSpeedIncrement(self,other)
) to the train it crashed into. I'm getting a nice collision effect in the straight tracks, but if you keep pushing forward one train slides over the other. And another problem with the same "sliding over" is the collision when one of the trains is standing on the turn.
Does anyone have any ideas on how to solve these problems?
回答1:
I would simple not try to re-invent the wheel and go for an existing solution. Have you looked at the very popular 2D-physics engine Box2D? Here is a nice implementation of it in JavaScript.
来源:https://stackoverflow.com/questions/17404339/collision-realisation-with-sat-canvas-javascript