Ich hab mir jetzt nicht angeschaut wie du das gemacht hast, aber ich kann ja mal sagen wie ich das machen würde:
Ich hab mir mal dein Levelformat angekuckt:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
******************************
* * *
* * *
* ***** *********
* * *
* L * L *
* * *
* *
* ******* *
* ****** * *
* L * * L *
* * *
******************************
|
Ich weiss zwar nicht was das L ist aber egal. Du wirst diese Daten wohl irgendwo in einem 2D-Array oder einem entsprechenden Speicherblock haben.
Ich würde jetzt aus der Position des Spieler berechnen in welchem "Block" er sich gerade befindet, der 2D-Index des Blocks sozusagen. Diese Berechnung sollte recht einfach sein, ich weiss jetzt leider nicht wo dein Nullpunkt ist aber es wird irgendetwas wie:
|
C-/C++-Quelltext
|
1
2
|
xIndex=floor(SpielerPosition.X/Laenge_eines_Blocks);
yIndex=floor(SpielerPosition.Z/Laenge_eines_Blocks);
|
Das machst du mit der alten Position und der neuen Position die der Spieler hätte wenn er uneingeschränkt dahin laufen könnte wo er wollte.
Im allgemeinen wirst du wohl nur einen Block weit kommen in einem Frame aber um allgemein zu bleiben: Diese 2 Position spannen ein Rechteck auf (Hier als # dargestellt. S ist Start. E ist Ende):
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
******************************
* * *
* *######E *
* *####### *********
* ####### *
* L S###### L *
* * *
* *
* ******* *
* ****** * *
* L * * L *
* * *
******************************
|
Besser wäre wohl eine Linie aus # mit dem Linien-Algorithmus aber da man sich sowieso nicht so viele Blöcke bewegt wäre das wohl etwas übertrieben.
Nun prüftst du jeden Block in diesem Rechteck ob da ein Hinderniss ist und wenn ja machst du eine Rechteck-Linie-Kollision die sehr einfach ist. Dann speicherst du den Schnittpunkt, wenn es einen gibt und gehst weiter durch die Blöcke durch. Wenn du einen neuen findest mit dem es einen Schnittpunkt gibt speicherst du den näheren.
Bist du nun durch alle Blöcke im Rechteck durch hast du den Schnittpunkt gefunden.
Um das "entlang sliden" zu realisieren musst du wissen ob der Schnittpunkt in einer Ebene parallel zur X- oder in einer parallel zur Z-Achse liegt. Das ist auch einfach festzustellen, denn wenn er in einer Ebene parallel zu X-Achse liegt ist die Z-Koordinate des Schnittpunktes durch die Länge eines Blocks (bis auf eine sehr kleine Ungenauigkeit) ein Ganzzahlwert.
In jedem Fall setzt du die alte Position nun auf den Schnittpunkt.
Liegt jetzt der Schnittpunkt auf einer Ebene parallel zu X-Achse heisst das das du nun nur noch entlagn der X-Achse entlang gleitest. Die neue Position hat nun also die Z-Koordinate der alten Position aber die X-Koordinate der Position die ursprünglich das Ziel war. Analog kannst du dir das wohl auch für einen Punkt parallel zur Z-Achse denken.
Diese alte und neue Position die du jetzt hast musst du leider noch mal durch die ganze Kollisionsroutine laufen lassen, da während dem entlang gleiten durchaus noch eine Kollision stattfinden könnte. Du kannst die neue Position übernehmen sobald:
a.) keine Kollision aufgetreten ist oder
b.) Die alte Position gleich der neuen ist (dann steht du senkrecht vor einer Wand)
Leider wird das nicht die gewünschten Ergebniss liefern, da du so in die Würfel hineinsehen wirst wenn du an ihnen entlang gleitest. Um das zu beheben musst du bei der Rechteck-Linien-Kollision die Ausmasse des Rechtecks ein wenig vergrössern (um ein wenig mehr als die Near Clipping plane), ausserdem musst du alle Blöcke in einem ein wenig grösserem Rechteck prüfen:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
******************************
* *######## *
* *######E# *
* *######## *********
* ######## *
* L S#######L *
* * *
* *
* ******* *
* ****** * *
* L * * L *
* * *
******************************
|
Wenn du dich nach oben rechts bewegst musst du oben und rechts eine Linie anhängen, da du sonst den Hindernis-Blöcken zu nahe treten könntest.
Puh, Fertig!!!
Ich weiss jetzt nicht ob das die beste Lösung ist, aber es müsste so funktionieren.