Autor Beitrag
.50AE
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 100



BeitragVerfasst: So 26.11.06 22:36 
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:
ausblenden 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//5 wird später durch die jeweilige Textur aus der Level-Datei ersetzt
  feld[y*x].Picture.Bitmap := feldbild[feldteil[y*x]]; //Bild wird eingefügt. Das Bild wurde bei FormShow schon geladen.
  feld[y*x].Transparent := true;
  feld[y*x].Picture.Bitmap.TransparentColor := clfuchsia;
  end;
 end;


MfG
50ae


Moderiert von user profile iconChristian S.: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Di 28.11.2006 um 19:03
Ironwulf
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 733
Erhaltene Danke: 2



BeitragVerfasst: 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

ausblenden 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])); //TileAuswahl, gibt den string zurück aus dem das bild geladen wird
    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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 51

Win XP
Delphi 2005 PE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 100



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 51

Win XP
Delphi 2005 PE
BeitragVerfasst: Di 28.11.06 15:26 
user profile icon.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 :)


Zuletzt bearbeitet von monster am Di 28.11.06 15:35, insgesamt 1-mal bearbeitet
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: 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 (Suche in: Delphi-Forum, Delphi-Library FEAR2D).

mfg
.50AE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 100



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 51

Win XP
Delphi 2005 PE
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 102



BeitragVerfasst: 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).