# Kollisions-Frage



## Androbin (7. Dez 2014)

Hallo Leute,
hier eine kurze Frage zur Kollision:

Vorwort:
Es geht um einen Minecraft-/Cubeworld-Klon, sprich: Die Welt besteht aus Blöcken.
Und eigentlich würde man die Kollision doch so implementieren:
1. Ändere die Geschwindigkeit in X-/Y-/Z-Richtung gemäß ...
2. Für jede Koordinate
2.1 addiere die zugehörige Geschwindigkeit
2.2 setzte sie auf die alten zurück, falls man dann in einem Block feststeckt

Problem:
Wenn man eine bestimmte Geschwindigkeit erreicht hat, "glitcht" man durch alles hindurch

Lösung-Ansatz:
Man wiederholt die Abfragen einmal pro Block, den man zurücklegt.
Nur leider weiß ich an dieser Stelle nicht weiter...

Hat vielleicht jemand von euch etwas anzumerken?
(einen anderen/besseren ("performanteren") Lösungsweg(/-Ansatz))


----------



## Gucky (7. Dez 2014)

Meinst du die Kollision zwischen dir und der Welt oder zwischen Blöcken?

Arbeitest du mit einer Engine? JMonkey o. Ä.?


Du könntest den Spieler auch aus einem Block bestehen lassen und dann zwischen dir und dem Zielort Geraden ziehen. Also nach Art des Raytraycings.


----------



## Androbin (8. Dez 2014)

Gucky hat gesagt.:


> Meinst du die Kollision zwischen dir und der Welt oder zwischen Blöcken?
> 
> Arbeitest du mit einer Engine? JMonkey o. Ä.?
> 
> ...


1. Zwischen mir und der Welt (die Blöcke bewegen sich ja nicht)
2. Ich arbeite mit LWJGL
3. Die Blöcke haben ja ganzzahlige Koordinaten, ich will mich aber auch dazwischen frei bewegen können
Aber was genau ist "Raytraycing"? Könntest du mir das mal genauer erklären?


----------



## Gucky (8. Dez 2014)

Raytraycing ist Strahlenverfolgung. Ich arbeite an einem Spiel, ähnlich dem Deinen, mit und dort haben wir es so gemacht. Aber zum Abbauen der Blöcke.

Wir haben einen Strahl zwischen der Kamera und der Unendlichkeit in Blickrichtung gezogen und gefragt, was dieser Strahl durchschlägt.
So ähnlich könntest du es auch machen, nur halt mit der Bewegung aber sobald es ans Wasser geht, wird das nichts mehr.


Auch eine Möglichkeit wäre es, wenn du eine Klasse Physik schreibst, die sich um Kollisionen u.Ä. kümmert.
Den Spieler baust du als Polygon auf, im einfachsten Fall aus zwei Punkten.
Der Spieler hat einen Bewegungsvektor, der die Richtung angibt und eine Geschwindigkeit, die den Betrag des Weges angibt, den der Spieler zurücklegt.
Tastatureingaben haben nur Einfluss in Form von vek[3] + 5; auf den Bewegungsvektor und nicht in Form von vek[3] = 0;
Dann schreibst du eine Klasse Physik und darin eine Methode prüfeBewegung, der du die Koordinaten des Spielers, seinen Vektor und seine Geschwindigkeit übergeben kannst.
Diese Methode organisiert sich alle Blöcke des aktuellen Chunks.
Dann zieht sie, bildlich gesprochen, Geraden zwischen allen Punkten des Spielerpolygons und dem Endpunkt der Bewegung.
Anschließend läuft sie an allen Geraden "gleichzeitig" entlang und guckt, ob ein Problem auftritt (Kollision, Änderung des Mediums o.Ä.).
Tritt ein solches Problem auf, so gibt sie entweder den geänderten Bewegungsvektor oder die veränderte Geschwindigkeit zurück.

Oder wenn du mehr Vertreter der verwalteten Bewegung und nicht der selbst verwalteten Bewegung bist, dann kann Physik auch gleich den Spieler bewegen.


----------



## Androbin (8. Dez 2014)

@ Gucky
Danke, ich werde es gleich mal ausprobieren!

Jetzt muss ich mir nur noch überlegen, wie ich rauskriege,
durch welche Blöcke der Strahl hindurchgeht, und durch welche nicht!

Hast du dafür vielleicht auch noch eine Formel, o. ä. parat?


----------



## Gucky (8. Dez 2014)

Ich könnte dir eine zweistufige Möglichkeit basierent auf Arrays geben. Allerdings hilft das nur pro Punkt. Du müsstest dann alle soundsoviele Punkte nachprüfen, ob die Gerade in einem Block ist.

int xKoor = linie.xkoor/breiteBlock
int yKoor = linie.ykoor/dickeBlock

Damit bekommst du aus der Vogelperspektive die "Spalte".
Dasselbe müsstest du noch einmal für die Zeile, also genau den Block machen.


----------



## Androbin (8. Dez 2014)

Gucky hat gesagt.:


> Ich könnte dir eine zweistufige Möglichkeit basierent auf Arrays geben. Allerdings hilft das nur pro Punkt. Du müsstest dann alle soundsoviele Punkte nachprüfen, ob die Gerade in einem Block ist.
> 
> int xKoor = linie.xkoor/breiteBlock
> int yKoor = linie.ykoor/dickeBlock
> ...


Danke, das müsste reichen


----------



## Androbin (13. Dez 2014)

Gucky hat gesagt.:


> Allerdings hilft das nur pro Punkt. Du müsstest dann alle soundsoviele Punkte nachprüfen, ob die Gerade in einem Block ist.


Also für die Kollision des Spielers reicht es, wenn ich nur nach jeder Spieler-Breite ("Bauchumfang") die Kollision abfrage.

Neues Problem:
Ich will in meinem Spiel Blöcke (ab-)bauen können, aber
was, wenn ich einen Block nahe an einem Eck erwische?
Dann funktioniert diese Methode (so) nicht.

Lösungsansatz:
Ich könnte für jeden Block (innerhalb eines gewissen Radius) abfragen lasse),
ob ihn die (Halb-)Gerade, die der Spieler-Sicht-Richtungs-Vektor bildet, durchläuft.

Überlegung:
Ich jede Seite des Blocks als Ebene ansehen und dann mit Vektorrechnung weitermachen,
den Schnittpunkt bestimmen und den (Block, dessen) Schnittpunkt (, der) dem Spieler am nächsten, ist als Ergebnis zurückgeben lassen.

Performance:
Außerdem will ich so wenig wie möglich Blöcke, Seiten, etc. abprüfen müssen.
Doch wie kann ich die Menge der zu prüfenden Elemente eingrenzen?

Hat da jemand von euch vielleicht etwas, das er/sie dazu beisteuern könnte?


----------



## Gucky (13. Dez 2014)

Du könntest zuerst bestimmen, welche "Blocksäulen" der Strahl durchläuft. Also zuerst zweidimensional in der X1X2-Ebene arbeiten und dann anhand dieser Werte überprüfen der Reihe nach überprüfen, ob der Strahl die Blöcke durchstößt oder nur an ihnen vorbei läuft.


----------

