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

02.10.2022, 18:31

2D Position auf Karte, an den Rand kleben, falls sie außerhalb der Karte liegt

Langsam verzweifle ich an einem kleinen Problem... sitze da schon 3 Stunden dran und die Ergebnisse sind immer unerwartet :rolleyes:

Ich möchte eine Funktion/Methode basteln, mit der ich eine 2D Position (z.B. eine Interessante Position auf einer Karte) sozusagen begrenzen kann auf den aktuellen Anzeigebereich.
Die Karte ist relativ zur Spielerposition. Also 0,0 ist genau die Mitte, dort wo der Spieler ist. Und die interessante Position ist eine relative Position zu diesem Nullpunkt/Zentrum.
Von der Karte wird ein Quadratischer Ausschnitt angezeigt der sowohl entlang von X als auch Y, im Bereich von -1 bis +1 liegt.
Diese interessante Position kann nun, z.B. auf 0.75,-0.5 sein. Dann wäre sie ganz normal innerhalb der Anzeige. Die Position muss dann nicht verändert/begrenzt werden.

Interessant wird es nun, wenn der Spieler sich weiter weg von dieser Position bewegt, und so diese Position außerhalb von -1/+1 wandert.
Also die Position wandert nun z.B. auf +3/-1.8. In diesem Fall wäre die Position außerhalb der Anzeige.
Hier möchte ich nun meinen Begrenzer einbauen. Und zwar so, das der Marker welcher anzeigt wo diese 'interessante Position' liegt, am Kartenrand klebt. Um so anzuzeigen in welcher Richtung diese interessante Position liegt.
Der Begrenzer müsste nun so arbeiten, dass vom Marker die X/Y Achse mit dem größeren Wert, genau +1 oder -1 ist, und die Achse mit dem kleineren Wert müsste entsprechend kleiner skaliert sein. Aus dem Beispiel +3/-1.8 sollte also werden: +1/-0.6
Habe ich hier schon einen Denkfehler? +3/-1.8 und +1/-0.6 sind doch genau in der gleichen Richtung (Winkel) vom 0,0 Zentrum, oder?

Genau genommen möchte ich den Bereich noch weiter begrenzen auf +/- 0.96, so das der Marker nicht halb aus der Anzeige raus ist, sondern noch vollständig innerhalb der Anzeige zu sehen ist. Aber zur Einfachheit bleiben wir mal bei einem Bereich von +/- 1

Mein Problem ist nun, das egal auf welche Idee ich komme um das zu Berechnen, zwar der Marker innerhalb des Anzeigebereichs landet, aber die Achse mit dem kleineren Wert wird immer irgendwie ein wenig falsch berechnet. ?(

Hier die zwei Code Ideen, die mir bisher die 'am wenigsten falschen' ( :rolleyes: ) Ergebnisse gebracht haben.

Idee 1:

C#-Quelltext

1
2
3
4
5
6
7
Vector2 pos = ...;
const float xyMax = 0.96f;
if(pos.x > +xyMax  ||  pos.x < -xyMax  ||  pos.y > +xyMax  ||  pos.y < -xyMax) {
  // Das Größere von x/y zu genau +xyMax bzw. -xyMax. machen.  z.B. wenn  xyMax=1  dann wird  x=3 y=-1.8   zu  x=1 y=-0.6
  float scal = Mathf.Max(pos.x.Abs(), pos.y.Abs())  /  xyMax;
  pos = pos / scal;
}


Idee 2:

C#-Quelltext

1
2
3
4
5
Vector2 pos = ...;
const float xyMax = 0.96f;
if(pos.x > +xyMax  ||  pos.x < -xyMax  ||  pos.y > +xyMax  ||  pos.y < -xyMax) {
  pos = (pos.normalized * xyMax);
}

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

02.10.2022, 18:43

Deine "Idee 1" müsste eigentlich richtig sein. Das hier wäre meine Lösung, ist möglicherweise äquivalent zu deiner:

C#-Quelltext

1
2
float maxAbs = Mathf.Max(Mathf.Abs(pos.x), Mathf.Abs(pos.y));
if (maxAbs > 1.0f) pos /= maxAbs;

Klappt das?

Jonathan

Community-Fossil

  • Private Nachricht senden

3

03.10.2022, 09:14

Also, was sich in diesem Falle grundsätzlich anbietet: Fange mit einer einfachen, aber richtigen Lösung an, sobald die läuft kannst du dir überlegen, ob du die noch effizienter machen willst (da du nicht 1000 Positionen pro Frame projizieren musst, ist die Antwort vermutlich: Nein).

Außerdem: Das hier ist ein 2D Problem, der erste Schritt sollte sein, es aufzumalen.

Du willst einen Punkt auf ein Quadrat (von -1/-1 zu 1/1) projizieren, also hast du 4 verschiedene Fälle, einen pro Seite. Löse erstmal nur einen, dann kannst du mit nichts durcheinander kommen, die anderen 3 gehen dann genauso, aber anders.

Wir nehmen die obere Seite (ist aber wirklich egal), dieser tritt ein wenn der Punkt Y>1 und abs(X)<Y. Und wir wissen, dass am Ende die Y Koordinate 1 ist, und die X Koordinate zwischen -1 und 1 liegt. Es ist eine Gerade, d.h. um den Punkt für einen bestimmten Y_neu Wert zu bestimmen rechnen wir X/Y * Y_neu, in diesem Fall ist Y_neu aber 1, also lassen wir das weg. Da wir vorher schon gesagt haben, dass X kleiner als Y sein muss, sehen wir auch dass bei X/Y ein Wert zwischen -1 und 1 rauskommen muss, was ein gutes Zeichen ist. D.h. du setzt Y auf 1 und X auf X/Y.

Kann man auch cleverer machen und kürzer, aber wenn man seit Stunden nicht auf die richtige Lösung kommt ist es sinnvoll, wenn man eine Strategie hat, mit der man auf jeden Fall schonmal das richtige Ergebnis bekommt, und die man gut durchtesten kann (weil jeder Schritt sehr leicht ist und auf dem Papier nachvollzogen werden kann).
Lieber dumm fragen, als dumm bleiben!

4

03.10.2022, 15:26

Eigentlich bin ich überzeugt dass diese Formel float maxAbs = Mathf.Max(Mathf.Abs(pos.x), Mathf.Abs(pos.y)); richtig sein muss. Vielen Danke dafür!

Aber es funktioniert trotzdem einfach nicht! Die Achse mit dem kleineren Wert wird zwar so wie es sein soll auch etwas verkleinert, aber immer "zu wenig" verkleinert. Es ist fast so, als ob da für die Achse mit dem kleineren Wert, irgendwo bei dem 'Verkleinerungsfaktor' noch ein SQR bzw. '<wert> hoch 2' fehlen würde. ?(

Mathematisch würde dies für mich mit dem SQR zwar keinen Sinn ergeben. Und eigentlich sollte die Formel richtig sein so wie sie jetzt ist. Aber optisch ist das Ergebnis einfach noch nicht korrekt!

Edit: Nun habe ich mal zwei Screenshots eingefügt. Jeweils einen kleinen Bildausschnitt der Karte.
Ganz links der blaue Rand, dort hört die Karte auf. Der grüne Pfeil ist die Spieler-Position. Das kleine blaue Quadrat ist der Marke welcher mir die Probleme macht.
Beim ersten Bild ist der Marker noch innerhalb der Karte und wie man sieht, werden Spier und Marker durch die grüne Linie verbunden.
Im zweiten Bild, ist der Marker außerhalb der Karte. Er klebt zwar links am Rand, aber viel zu hoch! Eigentlich müsste der Marker genau dort sitzen, wo die grüne Verbindungslinie aus der Karte raus läuft! Doch wie man sieht, wandert der Marker nicht weit genug nach unten ?(
Langsam bin ich echt am aufgeben... sind jetzt ca. 15 Stunden die ich da dran hänge... das wird jetzt wohl mein erster bekannter Bug den ich vorerst einmal nicht fixe.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Audori« (03.10.2022, 16:12)


Jonathan

Community-Fossil

  • Private Nachricht senden

5

03.10.2022, 17:41

Ich würde als erstes überprüfen, ob der Fehler in der Berechnung oder der Darstellung liegt. Du kannst dir ja z.B. im Debugger oder durch Textausgaben angucken, wie die Position vorher und nachher ist und dann z.B. auf einem Blatt Papier zeichnen und gucken ob das Ergebnis richtig ist. Falls nicht guckst du halt, welches Ergebnis richtig sein müsste und gehts Schritt für Schritt durch die Berechnung und guckst wo was schief geht.
Vielleicht ist aber auch einfach deine Darstellung kaputt, d.h. die Objekte werden vielleicht nicht dort gezeichnet, wo du denkst. Vielleicht wird die obere linke Ecke der Sprites benutzt anstatt der Mittelpunkte, oder irgendwie sowas. Das solltest du überprüfen indem du Objekte an einer genau definierten Stelle renderst und guckst, ob das Ergebnis richtig ist.

Der Bug sollte relativ leicht zu fixen sein, du musst nur vernünftig eingrenzen, was genau schief läuft.
Lieber dumm fragen, als dumm bleiben!

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

03.10.2022, 21:57

Der Fehler muss in der Darstellung liegen. Denn in deiner Darstellung ändert sich die Richtung zum Zielobjekt, was nicht der Fall sein dürfte bei einer einfachen Multiplikation des Vektors mit einer Zahl (bzw. Division).

Werbeanzeige