Entwickler-Ecke
Multimedia / Grafik - 2D Spiel: Felder erstellen dauert ewig
.50AE - So 26.11.06 22:36
Titel: 2D Spiel: Felder erstellen dauert ewig
Hallo,
ich erstelle gerade ein 2D Jump'n'Run Spiel (ähnlich wie PeterMorphose, falls es jemand kennt).
Das Spielfeld ist aus Feldern (TImage Objekte) aufgebaut. Insgesamt soll es etwa 50 (Anzahl Felder in y-Richtung) * 200 (Anzahl Felder in x-Richtung) geben.
Das entspricht dann 10.000 Feldern.
Jedoch, selbst eine einzelne Reihe (umfasst 200 Felder) zu erstellen und die Teiltextur hineinzuladen dauert sehr lange..
Da man sich später im Spiel teleportieren können soll, müssen aber alle Felder ziemlich früh und schnell existent sein..
Gibt es hier noch eine andere Lösung.. eine schnellere?
Mein bisheriger Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| for y:=1 to 50 do begin for x:=1 to 200 do begin feld[y*x] := timage.create(self); feld[y*x].Parent := pspielfeld; feld[y*x].Width := 24; feld[y*x].Height := 24; feld[y*x].Top := pspielfeld.height-(24*y); feld[y*x].Left := 1+(24*(x-1)); feldteil[y*x] := 5; feld[y*x].Picture.Bitmap := feldbild[feldteil[y*x]]; feld[y*x].Transparent := true; feld[y*x].Picture.Bitmap.TransparentColor := clfuchsia; end; end; |
MfG
50ae
Moderiert von
Christian S.: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Di 28.11.2006 um 19:03
Ironwulf - So 26.11.06 22:45
erstmal solltest du einen zweidimensionalen array nehmen, wie wird sonst unterschieden ob das feld x:= 45, y:= 46 ein anderes sein kann als x:= 46 und y:= 45
Edit:
wenn ich "welten baue" :D nehm ich meist nur ein image das schaut dann etwa so aus
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| breite:= 24 Ebene:= TBitmap.Create; Ebene.TransparentColor:= $00FF8080; Ebene.Transparent:= True;
for i:= 1 to 50 Do for j:= 1 to 200 Do begin Ebene.LoadFromFile(TileAuswahl(Feld[i,j])); Form1.Image1.Canvas.Draw((i - 1) * Breite, (j - 1) * breite, Ebene); |
ka ob das schneller ist, aber es wird auf jedenfall schneller wenn du die bilder ein bitmap lädst und dann von da aus weiter in die einzelnen Felder lädst, anstatt immer von der festplatte (merk grad das das bei mir so is und du das schon richtig gmacht hast ;D )
monster - So 26.11.06 23:28
Ich bin kein sehr erfahrener Programmierer, aber wenn Du zehntausend Steuerelemente erstellst, von denen jedes einzelne ein paar mehr Bytes Bilddaten enthält und die alle von Windows verwaltet werden müssen und über Funktionen verfügen, von denen Du gar nichts wissen willst, erzeugt das wohl eine Menge Ballast.
Und der sorgt wohl dafür, dass es so lange dauert.
Ich würd ein Stringgrid oder was in der Art nehmen und darauf alles selbst malen.
Dabei musst Du defaultDrawing auf false stellen, damit Windows dir nicht ins Handwerk pfuscht (zum Beispiel mit dem allseits beliebten SelectionFrame) und Rahmen sowie fixedRows ausschalten. Dann setzt Du die von dir gewünschte Zellbreite und -höhe (quadratisch?) und machst dich an das onDrawCell-Event. In der Prozedur malst Du dann das Bild, dass da hineingehört und was Du sonst noch so darstellen willst.
Ist eigentlich so einfach wie es klingt und geschätzte 28712,3% schneller als deine Lösung.
Viel Spaß :)
EDIT: Je mehr ich drüber nachdenke, wärs wohl besser eine eigene Miniengine dafür zu schreiben, auch wenn Du wirklich die GDI benutzen willst... Denn die Spielfigur und alle Gegner etc. werden sich doch bestimmt pixelweise und nicht feldweise bewegen und außerdem gibt es ja Speerfallen und sowas, die über dem Hintergrund gezeichnet werden müssen...
.50AE - Mo 27.11.06 18:56
Hoi,
Danke erstmal für eure Antworten!
Wenn ich Zeit hab werd ich einige Sachen ausprobieren.
Die Ergebnisse werd ich dann hier verlauten lassen...
@Ironwult
Das mit dem Zweidimensionalen Array ist ein guter Tip :wink:
Die hab ich noch nie verwendet und daher auch nicht dran gedacht.
Ein Freund von mir hat auch gemeint ich könnte es mal mit BitBlt (oder so) versuchen und alles in ein Bild laden (wie Du bereits gesagt has).
Mal sehen was draus wird.
@monster:
Wenn ich alles selbst in ein Stringgrid male, dauert es dann nicht trotzdem noch sehr lange?
Nun zu den Spielfiguten etc.. Die bewegen sich natürlich schon pixelweise.
Da man bei den TImages Transparenz einstellen kann, seh ich kein Problem darin, auch die Objekte damit darzustellen.
Bis denne, 50ae
//Edit:
Das mit BitBlt klappt perfekt!
20000 "Felder" in weniger als einer Sekunde!
monster - Di 28.11.06 15:26
.50AE hat folgendes geschrieben: |
[...]
@monster:
[1] Wenn ich alles selbst in ein Stringgrid male, dauert es dann nicht trotzdem noch sehr lange?
[2] Nun zu den Spielfiguten etc.. Die bewegen sich natürlich schon pixelweise.
Da man bei den TImages Transparenz einstellen kann, seh ich kein Problem darin, auch die Objekte damit darzustellen. |
zu 1: sollte es nicht, die Zellen des Stringgrid sind ja keine Objektinstanzen wie deine Imagearmee und Du zeichnest die Bilder ja sozusagen onDemand (schönes Unword ;)). Du hast sie also an zentraler Stelle im Speicher und malst sie nur, wenn der User das Feld auch tatsächlich sieht.
zu 2: Das ist das Problem an stringgrids und auch an Images, es ist zwar möglich, alle Spielobjekte wie das Spielersubstitut (ist heute nicht der Tag des Machwortes? Das wollt ich schon immer mal benutzen *g*) und die Gegnerhorden etc. auch pixelweise darzustellen, aber das führt doch zu dem Problem, dass Du berechnen musst, wieviel Spieler1 jetzt in Feld x, y und wieviel in x+1,y und wieviel in x+1, y+1 etc.pp. steckt. Deshalb würde ich ein Array nehmen, das u.a. Verweise auf die zu verwendende Grafik (als integer oder als Zeiger) und die Information über Durchlässigkeit eines Tiles enthält (sprich ob die Spielerfigur da durch kann (Luft) oder nicht (solide).
Außerdem brauchst Du eine Prozedur, die das malt (und zwar nur die Tiles, die man auch sieht). Dann würde ich eine Klasse TWorldObject oder so erstellen, die zum Beispiel die absoluten Koordinaten ausgehend vom Ursprung der Karte enthält (links oben) und die zugrundeliegende(n) Grafik(en). Schließlich noch eine Funktion um die Kartenkoordinate in die Zeichenflächenkoordinate umzurechnen, damit eine Zeichenfunktion die Objekte pixelgenau platzieren kann.
Ich hab das Jump'n'Run nie gespielt, das dir als Vorbild dient, aber Du kannst wohl davon ausgehen, dass es etwas schwieriger wird als Du vielleicht annimmst.
Wann werden Gegner erstellt? Wann werden sie getötet? Wer gibt zerstörte Gegnerobjekte wieder frei? Kollisionsabfrage? Gravitation? Wann wird die Gegnerintelligenz aktiviert und wie implementiere ich unterschiedliche KI für jeden Gegnertyp?
Ich hab darüber mal nachgedacht und kam zu dem Schluß, dass es wohl das Einfachste ist, wenn man einen Klassenstammbaum von Spielobjekten macht, die alle von TWorldObject abgeleitet sind und sofern nötig eigene Methoden für KI etc. haben, die von einer zentralen TWorld-Klasse verwaltet werden, etwa mit Arrays, in die sich Instanzen eintragen können, um wenn gewünscht benachrichtigt zu werden, falls der Spieler etwa zu nah an eine wild nach allem schnappende fleischfressende Pflanze kommt, damit sie ihr Köpfchen zu ihm rüber neigt.
Will nicht sagen, dass mein Ansatz toll ist, will nur wissen, ob Du das denn schon wenigstens im Kopf soweit durchdacht hast, denn selbst ein billiges Jump'n'Run kann ganz schnell ganz langsam und unübersichtlich werden, wenn man nicht wenigstens nen ungefähren Plan hat...
(Ich muss mir angewöhnen, weniger zu schreiben, sorry *g*).
Viel Spaß mit deiner Hüpforgie :)
F34r0fTh3D4rk - Di 28.11.06 15:29
nimm ein image und zeichne deine bilder allesamt auf dieses, anstatt mehrere tausend images zu verbraten und selbst das wird schon nicht sonderlich schnell laufen, wenn man es einfach so lässt. bzw nimm lieber gleich eine paintbox oder opengl (
FEAR2D).
mfg
.50AE - Di 28.11.06 17:11
Okay, danke für die ausführliche Beschreibung monster :)
Die ganzen Daten der Felder und Objekte hatte ich schon per Klassen und Arrays angegeben :)
Die Felder schnell zu erstellen geht ja inzw. auch (siehe Edit vom letzten Beitrag).
Ich werd jetzt mal sehen wie weit ich komm (ich mach vermutlich erst den Level Editor xD), wenns fertig ist findet Ihrs sicher in der Freeware-Abteilung :D
MfG
50ae
monster - Di 28.11.06 17:54
na da bin ich ehrlich mal gespannt (tatsache ist nämlich, dass ich gerade nebenbei an einer 2d-engine bastle mit dem mittelfristigen ziel, ein jump'n'run im mariostyle damit zu realisieren, deshalb natürlich für mich alles seeehr interessant was du da machst ;))
perry5 - Fr 01.12.06 16:10
Zum Thema 1/2D Array:
Man kann sher wohl ein 1D Array nehmen, ein 2D Array ist im Speicher nichts anders. Nur die Berechnung ist verkehrt. Sie müsste lauten:
[x+y*XSize]
dann geht das auch.
Zum Thema Geschwindigkeit: Man sollte am besten DirectX oder OGL benutzen, damit kiregt man auf jedne FAll ordnetlich Speed und coole Effekte (borausgesetzt man weiß, was man tut).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!