Strategiespiel: Regionen für Kollisionserkennung
-
So kleinliche Dinge mag ich gern
Das mit float hab ich oft ausprobiert, aber leider war float nie schneller als double, manchmal langsamer. Das mag vielleicht eben daran liegen, dass CPUs nach deiner Aussage mit double rechnen. Vielleicht muss dann ständig gecastet werden, ich weiß es nicht.
Das mit dem quadratischem Abstand brauche ich nicht, weil ich eine rechteckige Kollision verwende. Wahrscheinlich ist "radius" eine unpassende Bezeichnung für die Variable
Ich bestimmte praktisch den x- und den y- Abstand der Einheiten und wenn der Betrag einer der beiden Abstände kleiner als der "radius" ist, dann kollidieren die Einheiten.Ich hab die Variable radius genannt, weil sie nicht die Länge und Breite der Einheit ist, sondern die halbe Länge/Breite. Praktisch ein "eckiger Radius".
-
float ist eigentlich nicht langsammer als double, das reinladen passiert beide male in einem takt.
aber mit float kannst du halt so schön casten, dann ist es ein int, hab mich wohl auch versehendistanceX = *((float)&( ((int)&distanceX) & 0x7FFFFFF ));
so müßte es dann richtig sein... manchma bin ich zu beeilt.
du solltest die kollisionsberechnung nicht so extrem durchführen.
es wäre viel einfacher wenn du ein paar knotenpunkte in der level hättest (grob verteilt) und dir vorher speicherst welcher mit welchem verbunden ist.
anschliessend beim wegfinden müßtest du nur den weg von der einheit zum ersten knotenpunkt finden und dann am ende vom knotenpunkt zu richtigen ziel, aber für den groben weg über die ganze level müßtest du nicht wirklich was aufwendiges berechnen...
"die schnellste berechnung ist die, die man nicht machen muss" ist das mottound vorspeichern von knoten ist oft verwendet und läuft gut.
hilft dir aber bei lokalen kollisionen nicht
was bringt deine radiusberechnung und wieso machst du die nicht für beide elemente der kollision?
rapso->greets();
-
Ich habe sowas änhliches auch schonmal gemacht.
War nur eine Spielerei.
Ich habe für die Regionen eine Klasse entworfen, die alle benötigten Informationen hält. Wenn ich Einheiten bewege mussten diese nur von Region-A nach Region-B umgeschrieben werden.
Es gibt also für jede Region ein Objekt. Jedes Objekt hat die Kennungen der dort befindlichen Einheiten.
Anhand dieser Kennungen kann man dann auf das Einheiten-Objekt referenzieren.
Dort steht dann Position, Energie bla bla usw.
(edit)
Was noch wichtig ist: Sobald eine Einheit bein Bewegen eine Region verlässt, muss diese natürlich ihre Kennung im Region-A Objekt austragen und ins Region-B Objekt wieder eintragen.Ich glaube mit einem unsichtbaren Grid ist das ganze einfacher - Was spricht dagegen, ein Grid zu verwenden wie z.B bei den ersten beiden C&C teilen ?
-
(ganz meine rede)
mach WarCraft ja vielleicht auch und nur so fein tesseliert dass man das nicht sofort merkt.
ist das einfachste und schnellste.rapso->greets();
-
@Junky: Ja genau, und jetzt würde mich interressieren wie du das gespeichert hast, welche Einheiten in dem Objekt sind
@rapso: Die Wegfindung findet eh nur in einem kleinen Umkreis statt, ist also lokal.
distanceX = *((float)&( *((int*)&distanceX) & 0x7FFFFFF ));
c:\Programme\Microsoft Visual Studio .NET\Projects\StoneAge\main.cpp(2483) : error C2102: '&' requires l-value
Leider blick ich da überhaupt nimma durch, also kann ich den Fehler nicht beheben
-
@Optimizer:
Wie bereits beschrieben habe:
In einem Array werden Kennungen (Jede Einheit hat eine eindeutige) der Einheiten gespeichert die sich in der betreffenden Region aufhalten.
Anhand dieser Kennungen komm ich an die genauen Informationen der Einheiten (Position, aktuelle Aufgabe usw)
-
Schon klar, aber wie speicherst du pro Objekt mehrere Kennungen? Ach so, du hast in jedem Objekt ein Array oder wie?
Wie sind denn so deine Erfahrungen, lohnt es sich die Karte in Regionen aufzuteilen? Wieviele Einheiten konnte es in deinem Spiel maximal gleichzeitig geben?
-
du weißt in welchem feld das object ist, das bekommst du anhand der x/y coordinaten raus. und das feld kennt das objekt über z.B. id oder pointer.
selbst wenn es mehrere felder sind, das objekt weiß welche es überdekt.
-
Ja, meine Frage war nur, wie ich das am besten speicher, welche EinheitEN (Mehrzahl) in dem Feld sind. Ich leg jetzt pro Feld ein Array mit den IDs an, so geht's auf jeden Fall.
-
in den spielen sind die felder so klein dass eben nicht mehrere einheiten drinne sein können.. physikalischgesagt kann zur selben zeit nur eine materie an einem platz sein.
rapso->greets();
-
Egal, wie klein du das Feld machst, es können immer zwei Einheiten so da stehen, dass ihre Ränder in das Feld hineinragen - wenn du wirklich double-Ortsvektoren als Koordinaten verwendest. Und das wollte ich unbedingt machen, damit Einheiten praktisch in JEDE Richtung (nicht nur in 8 oder 16) gehen können und dabei immer die selbe Geschwindigkeit haben.
Außerdem find ich es auch nicht sinnvoll, eine Einheit über 50 Felder erstrecken zu lassen.Ich weiß was du meinst und mir sagen willst - aber ich will kein Grid-basiertes Spiel schreiben.
Wir können uns nächste Woche gerne weiter darüber unterhalten, aber jetzt muss ich in meine BarracksDas mit den Regionen werd ich mir nochmal genau durch den Kopf gehen lassen... ich hab inzwischen noch ein bisschen was optimieren können und hoffe, nächstes Wochenende eine neue Version hochladen zu können.
-
Optimizer schrieb:
Schon klar, aber wie speicherst du pro Objekt mehrere Kennungen? Ach so, du hast in jedem Objekt ein Array oder wie?
Wie sind denn so deine Erfahrungen, lohnt es sich die Karte in Regionen aufzuteilen? Wieviele Einheiten konnte es in deinem Spiel maximal gleichzeitig geben?Also, zuerst muss ich mal sagen das ich das ganze auf Grundlage der MFC entwickelt habe - Damit hatte ich die Klasse CObArray zur Verfügung die eigentlich die ganze "Einheiten-Verwaltung" so einfach macht.
Innerhalb des "Regionen-Objekts" sieht das etwa so aus, das es genau ein Objekt des Typs "CObArray" gibt. Dieses Objekt bekommt jeweils die Adresse des Sprite-Objekts zugewiesen dessen Einheit sich in der Region befindet./Pseudo
Sprite* pEinheit = new Sprite; ... // Einheit betritt neue Region pAlteRegion->pEinheiten.Remove(pEinheit); pNeueRegion->pEinheiten.Add(pEinheit); ... usw
Es werden also nur Adressen unter den Regionen-Objekten ausgetauscht.
Aber da du höchstwahrscheinlich kein MFC nutzen wirst musst du dir diese Organisation selbst schaffen. Darum sagte ich das mit dem Array und den ID's
Man könnte dann (das ist natürlich nicht so schick wie mit dem Pointer-Array) immer Index-Werte der Einheiten-Arrays tauschen.
-
Stimmt, ein Pointer-Array wäre sicherlich sinnvoller...
-
willkommen back bundeswehr mensch, ist schon ne neue version online?
rapso->greets();
-
Nein, aber ich hoffe heute noch
Ein paar Probleme muss ich noch lösen.