![]() |
[Andorra2D] Ein paar Fragen - Kollisionen und Timer
Hey,
ich habe ein paar Fragen bezüglich Andorra 2D. 1) Kollisionen Ich habe in meinem Projekt mehrere Sprite-Klassen, die von einer TAnimationSprite(TImageSprite)-Klasse abgeleitet werden:
Code:
TPlayerCharacter und TAICharacter laufen über das Spielfeld (isometrisch) und können mit TCustomProjectile schießen (diverse "Zauber" wie Feuerball, Blitz, Flächenzauber, ...).
TCustomCharacter(TAnimationSprite)
|-- TAICharacter(TCustomCharacter) +-- TPlayerCharacter(TCustomCharacter) TCustomProjectile(TAnimationSprite) |-- TFireballProjectile(TCustomProjectile) +-- T...Projectile(TCustomProjectile) Das Problem hierbei: Bei all diesen Klassen (oder der TAnimationSprite-Hauptklasse) müßte - nach meinem Andorra-Verständnis jedenfalls - im DoMove "Collision" aufgerufen werden, damit diese Sprites ihre eigene Kollision mit anderen Sprites mitbekommen. Zum Beispiel sollen sich auch Charaktere gegenseitig blocken, also nicht einfach gegenseitig durchlaufen können. AI-Charaktere müssen, genauso wie der Player-Charakter und Projektile auch, an Bäumen, Gebäuden, usw. kollidieren. Wenn ich in die TAnimationSprite-Klasse im DoMove Collision aufrufe und somit das Problem für alle abgeleiteten Klassen löse, klappt das auch alles, so wie es soll. Aber: Umso mehr Sprites es werden, desto mehr geht die Performance in den Keller. ~100 Charaktere sind noch ok, ab 200 sinken die FPS von 60 (VSync) auf ~20. Es ist nicht so, dass diese Menge ein Dauerzustand wäre, aber möglich könnte es schon werden. Gibt es da einen besseren Weg? CollisionOptimizationTyp ist bei allen schon auf ctOptimized gestellt. Was mir noch einfallen würde wäre, bei Sprites, die nicht im Sichtfeld des Spielers sind, die Kollisionserkennung zu überspringen. Allerdings geht das im Prinzip nicht, da sich AI-Charaktere auch ausserhalb der Reichweite des Spielers gegenseitig angreifen können sollen, wenn sie sich begegnen. Wobei man hier dann wieder sagen kann: Solange das Sprite nicht im Kampf ist, findet keine Kollisionserkennung statt. Sonst ja. 2) Timer Wie löst man mit Andorra am besten Aufgaben, die Timer involvieren? Zum Beispiel Abklingzeiten auf Fähigkeiten oder "Schaden / Heilung über Zeit"-Zauber? TThread? TTimer? GetTickCount? |
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Wie wärs wenn du ein Quadtree verwendest?
|
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Ok, hab mich damit noch nie mit beschäftigt, aber das was ich gerade darüber gelesen habe, klingt auf jeden Fall interessant. :)
Edit: Hab mich grad mal bisschen belesen. Dabei scheinen sich ja die Meinungen zu spalten? Die einen meinen "Spatial Hashing" wäre für 2D-Objekte besser als ein QuadTree? Vorallem für bewegliche / bewegende Objekte soll ein QuadTree angeblich eher nachteile gegenüber dem "Spatial Hashing" haben? Die Größe der im Spiel befindlichen Sprites variiert. Die Charaktere zB sind in der Regel 96x96 groß, können aber auch bei bestimmten Animationen 128x128 groß sein. Projektile sind entweder TParticleSprites oder TCustomProjectile und können dabei (je nach Zauber und "Zauberstufe") entweder 16x16 oder teilweise bis zu 64x64 groß sein. Was wäre hier nun besser? "Spatial Hashing" oder QuadTree? |
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Uff da müsste dir einer antworten, der sich auch mit Spatial Hashing auskennt.
|
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
„Spatial Hashing“ heißt glaube ich einfach nur, dass man das Spielfeld in ein grobes Gitter einteilt und dann für jede Zelle speichert, welche Objekte darin liegen. Dann testet man nur Objekte, die sich mindestens eine Zelle teilen, gegeneinander. Das ist denke ich für bewegliche Objekte eindeutig die bessere Variante, da die Datenstruktur flach ist, sodass der Overhead bei Änderungen nicht zu groß wird. Außerdem ist es einfacher zu implementieren. So weit ich weiß, verwaltet Andorra2D Sprites intern allerdings schon in so einer Struktur, zumindest schrieb Andreas (Entwickler von Andorra2D) mir das vor Jahren hier im Forum.
Entscheidend für die Effizienz dieses Verfahrens ist aber die Größe der Zellen. Ich weiß nicht, ob Andorra2D die Größe automatisch ermittelt, aber ich würde mal mit verschiedenen Größen experimentieren. Zum 2.: Zitat:
|
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Zitat:
Mir gehts hauptsächlich um das Prinzip eventueller Performancegewinne, um die Spielengine so skalierbar wie möglich zu halten und nicht künstlich den Spielverlauf zu limitieren, weil sonst die Kollisionsprüfung alles in den Keller ziehen würde. Ich hab mir auch schon ein paar grobe Gedanken über ein mögliches alternatives System gemacht, was auch mit Zellen und Gewichtungen arbeiten würde. Wobei die Zellen je nach "Inhalt" ein Gewicht bekommen. Also könnte man ein Gitter aus 16x16 pro Zelle erstellen. Ein 96x96 Sprite würde 4 Zellen ausfüllen, wobei das Zentrum das höchste Gewicht bekommt und nach aussen hin das Gewicht abnimmt. Je nach Bewegung der Sprites verteilt man die Gewichtung in den Zellen neu und addiert diese Gewichtung mit (zB je nach Bewegungsrichtung) benachbarten Zellen. Überschreitet das Ergebnis einen bestimmten Schwellwert findet eine Kollision statt, sonst nicht. :gruebel: Keine Ahnung, ob und wie gut das aufgehen würde und wie performant das wäre. Aber interessant finde ich es schon. Zitat:
Delphi-Quellcode:
Im Haupt-Render-Event der GameEngine wird UpdateTimers aufgerufen, der die ganzen Timer durchgeht, TickCounts aktualisiert und ggf. entsprechende Events ausführt, Timer wieder aus der Liste entfernt, wenn sie nicht mehr gebraucht werden, etc. Läuft butterweich. :thumb:
type
TTimerRecord = record Duration, Interval: Integer; StartTicks: Cardinal; IntervalStartTicks: Cardinal; PassedTicks: Cardinal; TicksLeft: Integer; Enabled: Boolean; Finished: Boolean; FreeOnTimeOut: Boolean; Data: Integer; OnInterval: TNotifyEvent; OnTerminate: TNotifyEvent; end; PTimerRecord = ^TTimerRecord; |
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Achso, dann wäre ja die Quadtree Optimierung eine dynamischere Variante davon... Nun gut, stimmt, da wäre diese Methode angebrachter. Man muss dann halt nur die richtige Zellengröße auswählen
|
AW: [Andorra2D] Ein paar Fragen - Kollisionen und Timer
Hab die Kollision jetzt per Bitmaske gelöst. Jedes Sprite hat 'ne eigene 1-Bit-Kollisionsmaske, die beim DoCollision-Event übereinandergelegt werden und dann wird geschaut, ob und wo sie sich überschneiden. Optimiert und (offenbar :mrgreen:) bugbefreit läuft das jetzt selbst mit 500 Bots, die quer durch die Gegend rennen und fröhlig rumkollidieren, noch akzeptabel und spielbar. :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz