Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

13.09.2017, 11:01

A* und Kollision bzw. ein Punkt ist kein Pixel

Hallo,

in meinen vorherigen Beiträgen bin ich etwas zu weit vorgeprescht, was so grundsätzliche Sachen betrifft. Deshalb kann es sein, dass ich jetzt eine Frage erneut stelle. Aber das nur so am Rande.

Das mit der Isometrie funktioniert zwar, zumindest teilweise, aber ich möchte doch erst nochmal orthogonal weitermachen.

Mittlerweile ist es mir gelungen, die Knoten für den A* auf die Größe 1x1 zu schrumpfen, was meiner Kenntnis nach der Größe eines Pixels entspricht und für die Bewegung wird der Einheitenposition einfach direkt die Pfadposition zugewiesen. Das läuft auch bei sehr vielen Einheiten, die sich unabhängig voneinander bewegen(jede in eine andere Richtung) ziemlich flüssig (bin stolz auf mich ^^).

Nun ist das ja alles schön und gut, ABER wie sieht das dann mit der Kollision bzw. nicht begehbaren Hindernissen aus, denn die Klasse Node mit ihren zwei Parametern ist eine Klasse, während ein Pixel ein Pixel ist?

Das Problem ist, dass ich nur zwei Möglichkeiten kenne eine sehr genaue Kollision zu erzielen.

1. Ich erzeuge auf einer Canvas ein BufferedImage, lese von diesem alle Pixel aus, und weise denen dann die jeweiligen Pixel aus den einzelnen Kachelbildern zu, um die Karte zu erzeugen. Das Problem hierbei ist, dass ich nicht nur jede Kachel auslesen müsste, sondern auch irgendwie meine Nodes zu Pixeln, die ja in einem int-Array vorliegen, caste, um dann sagen zu können: Dieses Pixel ist begehbar und ein anderes nicht.

2. Ich erzeuge auf einem JPanel ein Spielfeld aus einzelnen Nodes und erweitere diese zu einer eigenen Pixelklasse usw. .Aber das scheint mir zu aufwendig zu sein, je mehr man darüber nachdenkt.

Der Grund für mein Anliegen ist, dass ich wie in meinen früheren Beiträgen hier im Forum, zwar eine Kollisionsabfrage erfolgreich implementiert habe, aber diese war dann meist ungenau. Entweder blieb irgendwo die Einheit hängen, oder es gab seltsame Überschneidungen bis hin zu unerklärlichen Neupositionierungen der Einheiten, also alles in allem sehr ungenau.

Ich brauch im Prinzip nur eine Art Konzept, wie man A*, Kollisionsabfrage und Welt in Einklang bringt.

Falls mich jemand versteht, bin ich für Vorschläge offen.

MfG

Javaist

2

18.09.2017, 17:53

Um es nochmal konkret zu sagen:

Meine Frage war doof... .

Es macht ja keinen Sinn das gesamte Knotenspielfeld zur Laufzeit zu malen, auch wenn es ginge die Knoten als Pixel zu definieren,denn dann ruckelt alles ja wie verrückt.

Andererseits habe ich allerdings immer noch keine praktikable Lösung zu meinem Problem gefunden.

Melde mich aber hier wieder wenn ich was habe.

Bis dann.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

18.09.2017, 18:00

Worum geht es denn bei der Kollision? Geht es um die Kollision mit der Umwelt? Guck dir dafür mal Navigations Meshs an. Deine Knoten sind hier keine Punkte sondern Polygone. Eine Einheit bewegt sich nur innerhalb dieser Polygone.
Geht es dir darum ob sich ein Spieler auf einem Knoten befindet? Welche Form haben deine Spielfiguren? Vereinfacht kannst du sie vielleicht als Kreis darstellen. Dann reicht es aus den Abstand zwischen Mittelpunkt der Spielfigur und Mittelpunkt des Nodes zu bestimmen. Denk bei der ganzen Sache mal weniger in Pixeln als einfach in Weltkoordinaten. Wenn der Abstand kleiner als der Radius der Figur ist so befindet sich der Knoten unter deiner Figur. Andererseits kannst du deine Figur vielleicht besser durch ein Rechteck darstellen. Dann musst du dir eben überlegen wie du bestimmen kannst ob ein Punkt innerhalb eines Rechtecks ist. Ist das auch nicht ausreichend so kannst du deine Figur vielleicht aus mehreren Rechtecken und Kreisen zusammen bauen. Wie gesagt, hier geht es nur um die Kollision. Die muss in den seltensten Fällen wirklich pixelgenau sein.
Vielleicht hilft es aber auch einfach wenn du noch mal genau beschreibst was dein aktuelles Problem ist. Was soll womit kollidieren und was klappt dabei nicht? Gegebenenfalls machst du dazu vielleicht eine kleine Skizze.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

4

26.09.2017, 16:35

A* und Kollision bzw. ein Punkt ist kein Pixel

Ok, ich habe ein aus 1x1 großen Knoten bestehendes grid-Array, das allerdings nicht gemalt werden soll, während Sprites bzw. Tiles aus Pixeln bestehen. Mittlerweile habe ich folgendes geschafft: Ich bin einfach davon ausgegangen, dass jeder Pixel aus meinen Sprite und Tile Bildern genauso groß ist wie meine eigens erzeugten Knoten für den A*. So. Nun habe ich einfach die nichtbegehbaren Kacheln mit TILED komplett als Bild gespeichert und anschließend die nichttransparenten Pixel der gesamten obstacle Map EINMAL mittels getRGB() in einer boolschen Methode, die true zurückgibt, wenn das Pixel nichttransparent ist,eingelesen. Und siehe da das funktionierte. Somit kann man behaupten, das ich sowas ähnliches wie Pixelgenaue Kollision erzielthabe, denn der A* nimmt jedes Pixel der nichtbegehbaren Elemente des Spiels als obstacle und umgeht diese dann dementsprechend. Also das war eig. von Anfang an der Plan, ich habs eig nicht so mit Perfektionismus, aber ich mags halt möglichst exakt.

Also noch zu deiner Antwort nochmal.

Das was du mir empfiehlst ist mir alles schon bekannt und habe es auch implementiert. Also BoundingBoxen und irgendwelche Kreisshapes, die dann (mir leider zu unpräzise) die obstacles darstellen und für die Kollisionen verwendet werden. Das ist ja auch richtig so. Aber deswegen stelle ich ja meine Frage auch so komisch mit ein Punkt ist kein Pixel. Ich versuche eben auch ein bißchen unkonventionellere Herangehensweisen auszuprobieren.

ABER: Was ich eingangs ganz vergessen habe zu erwähnen ist, das ich versuche eine Art Strategiespiel in 2D-Grafik zu entwickeln. HHHH.
Man sollte hier natürlich schon sagen was man überhaupt machen will. :)

Das Thema hätte sich damit eigentlich erledigt. Das einzige, was halt nicht erledigt ist, ist meine Annahme, das ein Pixel genau 1x1 groß ist.

Nun habe ich aber noch eine Frage:

Wie wird in Spielen wie Starcraft 2 o.ä. die Ziellinien vom Startknoten der Einheit zum Zielknoten ermittelt?

Das ist keine triviale Frage Vorsicht hier. Mir ist durchaus klar, dass ich von der x-bzw. y-Position eine simple Linie Zeichnen kann. Das Problem, dass ich aber damit habe ist, dass der berechnete Weg des A* ungleich zur dieser Ideallinie ist.

Und hier meine eigentliche neue Frage: Wie berechne ich diese eben beschriebene Ideallinie nur durch den A*? Denn das wäre optimal für mich. Nur komme ich da nicht wirklich weiter. Ich werde mir nun die Algorithmen zum Lininzeichnen anschauen (Bresenham Line usw.), aber vielleicht hat hier jemand ne bessere Idee?

Meine Vorstellung ist es dabei, wenn ich eine Einheit anklicke und diese dann irgendwo auf der Karte hinschicke, wird mittels A* der direkte Weg zum Ziel(Luftlinie) angezeigt und eben dank des A* , jedes obstacle auf der Ideallinie umgangen. Ich hoffe soweit klar.

Bisher erzeuge ich mit meinem A* eine Linie mit einem leichten Knick und ich weiss leider nicht wie man den rausbekommt. Zum einen kann das am f-Wert liegen zum anderen an der Sortierung der openList oder ich muss noch was am Algorithmus selbst ergänzen. Bin leider etwas faul zurzeit und möchte eig keinen Wertetabelleabend machen. ^^

Wäre für Hilfe dankbar.

Gruß Javaist

5

26.09.2017, 16:44

Nachtrag: Sorry ich habe deinen Vorschlag nicht ganz verstanden gehabt. Ich habe gerade geschaut was Navigations Meshes sind und wie das funktioniert. Sehr interessant wirklich. Es ging mir nur um die Kollision beweglicher Einheiten mit der Umwelt nichts mehr. Und das habe ich jetzt für mich somit erledigt. Trotzdem danke.

Meine neue Frage ist aber noch aktuell.

Gruß Javaist

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

26.09.2017, 18:46

Nachtrag: Sorry ich habe deinen Vorschlag nicht ganz verstanden gehabt. Ich habe gerade geschaut was Navigations Meshes sind und wie das funktioniert. Sehr interessant wirklich. Es ging mir nur um die Kollision beweglicher Einheiten mit der Umwelt nichts mehr. Und das habe ich jetzt für mich somit erledigt. Trotzdem danke.

Genau das erledigt man ja damit. Nicht mehr und nicht weniger. Dein Algorithmus beachtet aber auch die Größen der Einheiten sodass kein Weg gefunden wird der zu nah an Objekten her führt?

Bisher erzeuge ich mit meinem A* eine Linie mit einem leichten Knick und ich weiss leider nicht wie man den rausbekommt.

Hier wäre ein Screenshot hilfreich. Entweder ist deine Heuristik fehlerhaft oder das Ergebnis ist soweit richtig. Was du nachträglich machen kannst ist den Pfad zu smoothen. Dafür gibt es verschiedene Ansätze. Sehr simpel ist es wenn du in deinem Pfad guckst ob einzelne Knoten übersprungen werden können. Ist deine Welt ein Kachelraster und der Weg führt zwei Knoten nach rechts und danach einen nach oben, so ist es unter Umständen ja auch möglich direkt dort hin zu gehen. Dafür kannst du einfach so lange alle Knoten durchlaufen bis du keinen mehr entfernen kannst. Hast du aufeinanderfolgende Knoten n1, n2 und n3 und ist ein direkter Weg von n1 zu n3 möglich so entfernst du n2 und verbindest stattdessen n1 mit n3. Dann geht das ganze wieder von vorne los.
Dazu kommt dass deine Einheiten normalerweise nicht genau der Linie folgen. Die Einheiten müssen auf ihrem Weg vermutlich beweglichen Objekten ausweichen, weshalb du eine zusätzliche lokale Wegfindung benötigst. Von daher kannst du eh nicht genau deinem gefundenen Weg folgen. Der Trick ist jetzt dass sich eine Einheit langsam dreht, bevor die in eine Kurve läuft. Soll heißen, die Einheit geht auf den Knickpunkt zu und dreht sich schon bevor dieser Punkt erreicht wurde in die richtige Richtung.
Hast du denn überhaupt mal versucht mehrere Einheiten so einen Pfad laufen zu lassen? Vielleicht existiert dein Problem am Ende gar nicht da sich der Pfad nicht so auswirkt wie du es vielleicht denkst.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

7

26.09.2017, 21:35

Ok sehr gut du hast mich verstanden. Also zu Deiner ersten Frage:
Ich mache das so, dass wenn man auf ein Obstacle der Umwelt klickt, wird in meinem A* trotzdem der bestmögliche weg dorthin berechnet, sodass die Einheit praktisch dort zum stehen kommt, wo sie am bestmöglichen hinkommt um das Ziel zu erreichen, also das habe ich schon implementiert.

8

26.09.2017, 21:45

Und ja, prinzipiell hast du mit deiner letzten Vermutung in deiner Antwort Recht, denn mein A* berechnet den richtigen Weg(ich habe mich sehr lange damit beschäftigt) und eigentlich könnte ich das so lassen und einfach eine einfache Linie als Zielindikator zeichnen und mit der Abweichung von ca 30 Grad leben. ABER exakt isses natürlich dann doch nicht. Als Heuristik nehme ich einfach die euklidsche Distanz. Im Prinzip möchte ich halt einfach nur erreichen, das die euklidsche Distanz zwischen start und Ziel unter Berücksichtigung der obstacles als Linie gezeichnet wird(also den Zielindikator). Ich hatte ähnliche Gedanken wie du was du als "smoothen" bezeichnest. Aber nimms nicht persönlich ich halte nicht so viel von mathematischem "herumgedoktore". Außerdem wäre das Ergebnis dann zwar etwas besser aber halt nicht wirklich exakt. Vielleicht könnte ich so bis zu 15 Grad gutmachen aber wahrscheinlich nicht mehr.

9

26.09.2017, 21:59

Screenshot:
»Javaist« hat folgendes Bild angehängt:
  • ASternErgebnis.png

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

10

26.09.2017, 23:27

Ich hatte ähnliche Gedanken wie du was du als "smoothen" bezeichnest. Aber nimms nicht persönlich ich halte nicht so viel von mathematischem "herumgedoktore".

Herumgedoktore würde ich es jetzt nicht nennen ;) An sich bleibt dein Weg ja korrekt. Dadurch dass du einzelne Knoten überspringst kannst du einerseits den Weg weiter verkürzen und andererseits Wege "zwischen Knoten finden die frei sind. Wie gesagt, wichtig ist dabei ein Kollisionscheck mit der Welt. Ob das bei dir helfen würde kann man nicht genau sagen. Interessant wäre zu sehen an welchen Stellen Knoten sind und wo sich Hindernisse befinden. Die Linie ist da nicht wirklich aussagekräftig :)
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Werbeanzeige