Kachelbasierte 2D-Kollisionserkennungsprobleme


8

Ich versuche, diesem Tutorial http://www.tonypa.pri.ee/tbw/tut05.html zu folgen , um Echtzeitkollisionen in einer kachelbasierten Welt zu implementieren.

Ich finde die Mittelkoordinaten meiner Entitäten dank dieser Eigenschaften:

public float CenterX
{
    get { return X + Width / 2f; }
    set { X = value - Width / 2f; }
}
public float CenterY
{
    get { return Y + Height / 2f; }
    set { Y = value - Height / 2f; }
}

Dann habe ich in meiner Update-Methode in der Player-Klasse, die jeden Frame heißt, diesen Code:

public override void Update()
{
    base.Update();

    int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
    int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
    int leftX =     (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
    int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);

    bool upleft = Game.CurrentMap[leftX, upY] != 1;
    bool downleft = Game.CurrentMap[leftX, downY] != 1;
    bool upright = Game.CurrentMap[rightX, upY] != 1;
    bool downright = Game.CurrentMap[rightX, downY] != 1;

    if(NextX == 1)
    {
        if (upright && downright)
           CenterX += Speed;
        else
           CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
    }
 }

downY, upY, leftX und rightX sollten jeweils die niedrigste Y-Position, die höchste Y-Position, die X-Position ganz links und die X-Position ganz rechts finden. Ich füge + Speed ​​* NextX hinzu, da im Tutorial die Funktion getMyCorners mit folgenden Parametern aufgerufen wird:

getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);

Die Methoden GetCellX und GetCellY:

public int GetCellX(float mX)
{
    return (int)Math.Floor(mX / SGame.Camera.TileSize); 
}
public int GetCellY(float mY)
{
    return (int)Math.Floor(mY / SGame.Camera.TileSize); 
}

Das Problem ist, dass der Spieler beim Auftreffen auf eine Wand "flackert" und die Eckenerkennung nicht einmal richtig funktioniert, da sie Wände überlappen kann, die nur eine der Ecken treffen. Ich verstehe nicht, was los ist. Im Tutorial sollten die Felder ob.x und ob.y mit meinen CenterX- und CenterY-Eigenschaften übereinstimmen, und ob.width und ob.height sollten mit Width / 2f und Height / 2f übereinstimmen. Es funktioniert jedoch immer noch nicht.

Danke für Ihre Hilfe.


Testen Sie die Kollision, sobald sich der Spieler an dieser Stelle befindet, und drücken Sie sie zurück, wenn sie kollidiert, oder testen Sie, ob der nächste Zug eine Kollision ist?
Kyndigs

Ich würde empfehlen, in dieser Aktualisierungsfunktion einen Tastendruck hinzuzufügen, der den aktuellen Prozess unterbricht, wenn Sie die Taste drücken. Drücken Sie dann die Taste, wenn der Player "flackert", und gehen Sie durch den Debugger. (Achten Sie darauf, was mit den Zahlen passiert.) Versuchen Sie herauszufinden, was mit den Zahlen passiert, wenn sie flackern.
Michael Coleman

Antworten:


1

Ein paar Vorschläge, obwohl ich nicht sicher bin, ob sie das Problem beheben werden, da ich keinen vollständigen Code zum Ausführen und Debuggen habe.

In diesem Code:

if(NextX == 1)
{
    if (upright && downright)
       CenterX += Speed;
    else
       CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}

Die else-Anweisung verschiebt das Objekt, obwohl sich das Objekt nicht bewegen sollte.
Ich denke, Sie versuchen, das Objekt bündig mit der Wand zu machen, aber möglicherweise ist die Berechnung falsch.
Wenn Sie die else-Anweisung auskommentieren, flackert das Objekt dann immer noch?

Die Berechnung sieht etwas verdächtig aus, da sie subtrahiert (Breite / 2f), und dann führt der CenterX-Set-Operator dieselbe Subtraktion erneut durch.

Eine andere Sache, auf die ich hinweisen möchte, um die Klarheit des Codes zu verbessern, ist, dass Sie die Eigenschaften für CenterX veranlasst haben, den Wert hin und her zu berechnen, aber der Code ist immer wieder mit derselben Berechnung übersät.
Dies könnte durchaus Teil des Problems sein. In jedem Fall würde ich vorschlagen, ein paar weitere Eigenschaften zu erstellen und für alle einen Standard festzulegen. Stellen Sie beispielsweise das Center als gespeicherte Eigenschaft ein und berechnen Sie die anderen daraus:

public float CenterX
{
    get { return X; }
    set { X; }
}

public float LeftX
{
    get { return CenterX - Width / 2f; }
    set { CenterX = value + Width / 2f; }
}

public float RightX
{
    get { return CenterX + Width / 2f; }
    set { CenterX = value - Width / 2f; }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.