Avatar billede quiw Nybegynder
17. januar 2013 - 21:11 Der er 2 kommentarer og
1 løsning

Collision detection.

Goddag eksperter. Jeg roder lidt med et javascript 2d spil, som er bygget op om en masse "tiles", som en person kan gå rundt på. Tiles er 20x20 pixels.

Jeg har en række tiles i form af et 2 dimensionelt array, kaldet tiles[x][y]. Den enkelte tile, har en funktion der hedder "isWalkable()", for at tjekke om man kan "gå" på denne tile.


Min player har en move funktion, hvor inputtet er en vector (afgjort af input fra piletaster, 1,-1 eller 0). Mit problem er nu, at jeg gerne blokere spilleren i at gå på tiles der ikke er isWalkable().

Min funktion i spiller-klassen ser sådan ud:

var position = [10,10]; //Eksempel på spillerens nuværende position.

function move(vector){ //Funktion til at flytte spilleren
          position[0] += Math.round(vector[0]*speed*0.01);
        position[1] += Math.round(vector[1]*speed*0.01);
}

Hvordan laver jeg min move funktion, således at spilleren ikke kan gå på de "forbudte" tiles? PS: spillerens position er i pixels, hvor tiles er et 2d array.

Hvis man bare tjekker, om spilleren er på et forbudt tile og blokerer input, resulterer det naturligvis i en deadlock hvor spilleren aldrig kan flytte sig igen. Jeg har også forsøgte at "raycaste" og tjekke om nabo-tiles er isWalkable(), men af mystiske årsager kan man "snyde" sig forbi dem. Der må være en pæn måde at blokere spillerens retning, således at man ikke kan træde ind på de forbudte tiles.

På forhånd tak.
Avatar billede quiw Nybegynder
17. januar 2013 - 21:18 #1
PS: Spilleren er 10x10 pixels, så de skal ligges til spillerens position.
Avatar billede quiw Nybegynder
18. januar 2013 - 00:42 #2
Jeg har forsøgt mig med:

        var leftTop = [position[0] + Math.round(vector[0]*speed*0.01),position[1] + Math.round(vector[1]*speed*0.01)];
        var leftButtom = [position[0]+Math.round(vector[0]*speed*0.01),position[1]+tileSize+Math.round(vector[0]*speed*0.01)];
        var rightTop = [position[0]+tileSize+Math.round(vector[0]*speed*0.01),position[1]+Math.round(vector[0]*speed*0.01)];
        var rightButtom = [position[0]+tileSize+Math.round(vector[0]*speed*0.01),position[1]+tileSize+Math.round(vector[0]*speed*0.01)];

        //Find corresponding tile:
        leftTop = coordinateToTile(leftTop);
        rightTop = coordinateToTile(rightTop);
        leftButtom = coordinateToTile(leftButtom);
        rightButtom = coordinateToTile(rightButtom);

        //Check if walkable:
        if(!map[leftTop[0]][leftTop[1]].isWalkable() || !map[leftButtom[0]][leftButtom[1]].isWalkable()){
            if(vector[0]<=0){
                vector[0] = 0;
            }
        }else if(!map[rightTop[0]][rightTop[1]].isWalkable() || !map[rightButtom[0]][rightButtom[1]].isWalkable()){
            if(vector[0]>=0){
                vector[0] = 0;
            }
        }

        if(!map[leftTop[0]][leftTop[1]].isWalkable() || !map[rightTop[0]][rightTop[1]].isWalkable()){
            if(vector[1]<=0){
                vector[1] = 0;
            }
        }else if(!map[leftButtom[0]][leftButtom[1]].isWalkable() || !map[rightButtom[0]][rightButtom[1]].isWalkable()){
            if(vector[1]>=0){
                vector[1] = 0;
            }
        }


Jeg nærmer mig noget, men den opfører sig stadig ikke optimalt: nogle gange springer den igennem, andre gange sidder den fast.
Avatar billede quiw Nybegynder
18. januar 2013 - 01:43 #3
Problemet er løst:

Lavede en funktion som tjekkede valideten:

function checkValid(coordinate){
    var leftTop = coordinateToTile(coordinate);
    var rightTop = coordinateToTile([coordinate[0]+tileSize-2,coordinate[1]]);
    var leftButtom = coordinateToTile([coordinate[0],coordinate[1]+tileSize-2]);
    var rightButtom = coordinateToTile([coordinate[0]+tileSize-2,coordinate[1]+tileSize-2]);

    if(!map[leftTop[0]][leftTop[1]].isWalkable()){
        return false;
    }
    if(!map[rightTop[0]][rightTop[1]].isWalkable()){
        return false;
    }
    if(!map[leftButtom[0]][leftButtom[1]].isWalkable()){
        return false;
    }
    if(!map[rightButtom[0]][rightButtom[1]].isWalkable()){
        return false;
    }
    return true;
}

Og en move funktion, som testede akserne:
this.move = function(vector){
        var target = [position[0] + Math.round(vector[0]*speed*0.01),position[1] + Math.round(vector[1]*speed*0.01)];
       
        if(!checkValid(target)){
            target = [position[0] + Math.round(0*speed*0.01),position[1] + Math.round(vector[1]*speed*0.01)];
            if(!checkValid(target)){
                vector[1]=0;
            }
            target = [position[0] + Math.round(vector[0]*speed*0.01),position[1] + Math.round(0*speed*0.01)];
            if(!checkValid(target)){
                vector[0]=0;
            }
        }

        position[0]+= Math.round(vector[0]*speed*0.01);
        position[1]+= Math.round(vector[1]*speed*0.01);
    }
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester