Collision realisation with SAT (canvas, javascript)

做~自己de王妃 提交于 2019-12-11 19:19:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!