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

05.02.2012, 16:05

Levelformat 2D Platformer

Hallo Community,



ich bin gerade dabei, mir ein Framework für 2D Platformer zu schreiben und habe dabei auch in Aussicht, wofür ich es dann letzten Endes eigentlich benutzen will :p



Seit längerem kämpfe ich allerdings mit dem Problem der internen Leveldarstellung bzw. der externen Verwaltung als Datei. Eventuell habt ihr da mehr Erfahrung und ein paar Tipps.



Was ich speichern will:

- Boden mit Höhe

- schwebende Plattformen (also Ober- und Unterkante eines soliden Tiles)

(- Spezialfall der Mauer, vor die man laufen und die man durch einen Sprung nach oben erklettern kann)

- Levelteile mit Hintergrundtextur (-> "Innenraum")

- Objekte, Gegner

- Hotspots



Momentan verwalte ich meine Levels so, dass ich sie als Bitmap (.png) zeichne und die Levelinformationen in den Farbkanälen kodiere (z. B. Rotkanal: ObjektID, Grünkanal: TexturID, usw.). Die Farbkanal-Infos lese ich dann im Spiel in ein Array (von 1x1 Spielfeldeinheiten große Zellen) aus und zeichne dann nur denjenigen Teil des Arrays, der sich in einem bestimmten Rechteck um den Spieler befindet.
Der Vorteil ist, dass ich dadurch schnell und einfach den nähesten Boden (nicht ganz unwichtig bei einem klettern-und-verstecken-basierten Spiel) unter einem Objekt immer finde, indem ich das Array von Spielerhöhe an nach unten durchlaufen kann und ebenso entscheiden kann, welcher Teil des Levels derzeit ignoriert wird, was beides z. B. bei einer linked list mit variablen Zellgrößen erheblich schwieriger wäre.



Das hat aber auch einige Mankos:



- Ich kann keine größeren Hintergrundbereiche verbinden, um z. B. eine Textur über mehr als 1x1 Spielenheiten gehen zu lassen. Ständiges ein- und ausbinden einer Textur ist aber ineffizient und außerdem kämen dann noch float Informationen für die Texturkoordinaten zu den nötigen Informationen...

- Es gibt einfach nicht genügend Farbkanäle, um z. B. Unterkante, Oberkante, Textur, Schräge, Objekt, Hotspot usw. pro Pixel zu kodieren.

- Das Auslesen klappt super, aber das Erstellen ist wenn man mehr als nur den Boden zeichnen will... nicht gerade angenehm. Der Computer sieht die einzelnen Farbabstufungen deutlich genauer als ich beim Levelerstellen :D



Ich könnte natürlich xml-ähnliche Dateistrukturen für die Informationen einführen und eine Monster-Auslese-Methode schreiben, allerdings wäre das Erstellen/Verwalten mindestens ebenso unangenehm.



Wie würdet ihr Levelinfos intern und extern verwalten? Habt ihr Tipps oder ein gutes Tutorial? Ich suche schon seit einigen Tagen in der Richtung...

2

05.02.2012, 17:44

Ich würde das objektorientiert machen.
Du hast so Dinge wie Boden, Wände, Plattformen. Man kann doch prima z.B. deren Größe speichern und später in der Kollisionsabfrage einen Rechteck/Rechteck Test machen. Der Vorteil davon ist, du kannst z.B. einzelne Plattformgrößen festlegen und dafür jeweils ein Sprite malen, im Editor setzt du dann dein Level nur noch aus den fertigen Objekten zusammen. Außerdem kannst du damit auch relativ einfach bewegliche Plattformen machen, was später interessant sein könnte, und mit dem bisherigen Ansatz schwer sein dürfte. Oh, und der Speicherbedarf ist natürlich viel geringer, da du keine Bitmaps mehr speichern musst.
Nachteile gibt es natürlich auch: Die Kollisionsabfrage wird etwas komplizierter und du bis bei den Formen nicht mehr ganz so flexibel. Aber wie gesagt, ich würde es so machen.
Lieber dumm fragen, als dumm bleiben!

3

12.02.2012, 13:20

Hallo Jonathan,

generell hast du wohl Recht mit dem objektorientierten Ansatz (obwohl ich natürlich aus den Farben Objekte generieren wollte). Bitmaps verbrauchen wirklich jede Menge unnötigen Platz für leere Felder und lassen nur eine begrenzte Anzahl von Informationen in einer einzigen Datei zu. Ich hatte sie hauptsächlich benutzt, weil ich gehofft hatte, erst einmal um das Schreiben eines Leveleditors herumzukommen.

Designmäßig habe ich jetzt eine Technik aus dem Raytracing benutzt: ich lade alle Levelobjekte (dazu zählt auch Boden in beliebiger Form) in eine LinkedList und sortiere diese möglichst nach gleichen verwendeten Texturen (das Wechseln von Texturen verbraucht unverhältnismäßig viel Zeit bei OpenGL).
Anschließend lasse ich den Konstruktor die Dimensionen des Levels analysieren und erstelle ein entsprechend großes Voxelgitter.
Dann parse ich alle Objekte danach, in welchen Voxeln sie überhaupt sichtbar sind und registriere in den entsprechenden Voxeln eine Referenz auf das Objekt.

Somit habe ich mehrere Fliegen mit einer Klappe geschlagen (obwohl bewegliche Plattformen, die nicht geplant sind aber wohl auch bewegliche Gegner ;-) natürlich bei der Bewegung in den entsprechenden Voxeln registriert und deregistriert werden müssen):
- Objekte können vollkommen frei und flexibel definiert werden
- Es kann sehr schnell bestimmt werden, welche Objekte überhaupt gerendert werden müssen (Nur Objekte im Bildschirm-Rechteck um Kameramittelpunkt)
- Kollisions-, Sichtlinien-, Schusslinien- usw. Abfragen können recht effizient gestaltet werden, indem alle leeren Voxel beim Raycasting einfach übersprungen werden, und der Zugriff auf solche Informationen ist extrem einfach möglich

Beispiel: Nächsten Boden am punkt (X, Y) finden:
- X und Y abrunden
- Im Voxelgitter von Y bis 0 absteigen und bei jedem Schritt überprüfen, ob das Voxel leer ist
-> nein -> enthält solide Objekte?
-> ja -> Oberkanten der soliden Objekte am ungerundeten X-Punkt ermitteln und den höchsten Wert zurückgeben (natürlich kann hier auch gerade eine Lücke sein, dann gehts weiter nach unten)
-> am Unteren Ende ohne Ergebnis angekommen? Hier muss wohl ein Loch sein...


Momentan fahre ich mit der Methode ganz gut; Als Test habe ich einen Bildschirm voller Plattformen geladen und lasse eine Partikelquelle über Tausend Teilchen durch die Gegend jagen, komplett mit Kollisionsabfragen, und das Ganze läuft ohne erkennbare Prozessorlast; sollte also für einen Sidescroller mit deutlich weniger Objekten schnell genug sein. Es bleibt zu überlegen, ob sich das Ganze immer noch rechnet, wenn die Levels viel größer werden, da dann doch ganz schön große Arrays vorgehalten werden müssen. Notfalls könnte man dann die Voxel gröber machen, allerdings ginge dann etwas Effizienz verloren... natürlich könnte man das noch optimieren, indem man nur besetzte Voxel überhaupt initialisiert...

Was haltet ihr von dem Ansatz? Gibts große Bedenken?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

12.02.2012, 13:41

Hört sich gut an :)

Du könntest bewegliche Plattformen auch einfach statisch in allen Voxeln registrieren in denen sie sich theoretisch aufhalten können und fertig ;)

Und du könntest die Objekte doch eigentlich schon sortiert in die Datei speichern, damit das Laden schneller geht ;)

5

12.02.2012, 14:02

Danke für die Kritik - und dann auch noch genau die, die ich hören wollte ;)



Hm, das mit den beweglichen Elementen klingt plausibel - zumindest wenn es um bewegliche Plattformen geht (ich bau noch welche ein, wenn das so weitergeht - nur wir so oft davon reden :D ) - oder anderweitig in bestimmtem Rahmen bewegliche Elemente. Bei Gegnern wird das allerdings schwer möglich sein (die werden ja so eine fortgeschrittene AI bekommen, dass sie mich durch das ganze Spiel jagen und dabei noch Kant lesen...)



Und klar, sortiert speichern ginge natürlich - da sind wir aber wieder bei dem hypotethischen Leveleditor, der im Moment noch etwas hintenansteht. Für heute ist eine StateMachine geplant (fast fertig) und dann mache ich mich an eine rudimentäre Eingabelogik... jaaa, ich drück mich weil ich keine Ahnung hab von GUI-Programmierung *gg*





(interessant: bei jedem Klick auf Vorschau wird aus einigen leeren Zeilenumbrüchen je eine zusätzliche Leerzeile... und das in einem Programmiererforum? :D )

Werbeanzeige