endlose Maps in 2D
Übersicht

![]() |
garretBetreff: endlose Maps in 2D |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey. Innerhalb des letzten Jahres habe ich immer wieder mal (bin jetzt beim siebenten Neuansatz ![]() Kurz zur Erläuterung: Der Gesamtbildschirm kann immer aus höchstens vier Teilkarten bestehen. diese tragen die Namen Mitte, Rechts, Unten, Rechts_Unten und werden in einem großen Dim-Feld gespeichert. Statt bei einer Bewegung jedes Mal alle Karten neu einlesen zu müssen, habe ich mir gedacht, dass man praktisch nur die Zuweisung ändert. Wenn ich mich also nach rechts bewege und die Feldgrenzen überschreite, wird mein Feld_Rechts ja mein neues Feld_Mitte. Dieses hatte vorher die Zuweisung 0, sodass beim Lesen auf Feld(0,x,y) zugegriffen wird. Da die Daten für Feld_Rechts in 1 gespeichert sind, bekommt Feld_Mitte jetzt die 1 zugewiesen und es wird fortan auf Feld(1,x,y) zugegriffen. Die Zuweisung wechselt bei einer Bewegung nach Rechts also immer zwischen 0 und 1 bei Feld_Mitte und Feld_Rechts, und zwischen 2 und 3 bei Feld_Unten und Feld_Rechts_Unten. Mein Problem liegt nun darin, dass bei manchen Bewegungen falsch gelesen wird, das heißt, es werden Reste der alten Karte gezeichnet. Hoffe, das war wenigstens ein bisschen verständlich. Das Prinzip ist jedenfalls einfach und sollte beim Test ersichtlich sein. Wenn nicht fragt ![]() Das Paket inklusive Testkarten und 2 Grafiken (mit und ohne Bezifferung) ist hier zu finden: https://www.blitzforum.de/upload/file.php?id=5331 Der Code: Code: [AUSKLAPPEN] ;####################################################################################################
; Aneinanderreihen mehrerer Maps um den Eindruck einer großen zu erzeugen ;#################################################################################################### ;#################################################################################################### ; Variablen gGraphicsWidth=1024 gGraphicsHeight=768 Graphics gGraphicsWidth,gGraphicsHeight,32,2 Const cTILESIZE = 16 ; Größe der Tiles Const gXmax = 199 ; max. Spalten pro Datei Const gYmax = 199 ; max. Zeilen pro Datei Global gFeld_Mitte = 0 ; relative Zuweisung der Felder Global gFeld_Rechts = 1 Global gFeld_Unten = 2 Global gFeld_Rechts_Unten = 3 Global max_x_tiles = gGraphicsWidth / cTILESIZE ; Anzahl der maximal gleichzeitig anzeigbaren tiles Global max_y_tiles = gGraphicsHeight / cTILESIZE Global vx = -160, vy = -180 ; Verschiebung der Karte (immer <= 0) Global sektor_x = 1; die momentan aktiven Sektoren Global sektor_y = 0 IMG_Tiles = LoadAnimImage("test16_2.png", cTILESIZE, cTILESIZE, 0, 16) ;das Bild, das die Einzel-Tiles enthält Local IMG_Background ; Bild, das zusammengesetzt den Hintergrund darstellt Dim Feld(3, gXmax, gYmax) t = MilliSecs(); zur Zeitmessung ;#################################################################################################### ; Felder einlesen siehe Funktion Map_Einlesen Map_Einlesen(gFeld_Mitte) Map_Einlesen(gFeld_Rechts) Map_Einlesen(gFeld_Unten) Map_Einlesen(gFeld_Rechts_Unten) ;#################################################################################################### ; das eigentliche Hintergrundbild erstellen IMG_Background = CreateImage(gGraphicsWidth, gGraphicsHeight) SetBuffer ImageBuffer(IMG_Background) ; Je nach Verschiebung der Karte (aus Speicherstand geladen) werden Teile aus bestimmten Feldern gebraucht If (-vx + max_x_tiles) <= gXmax ; nur Feld Mitte (Fall 1) If (max_y_tiles -vy) <= gYmax For i = 0 To (max_x_tiles - 1) For j = 0 To (max_y_tiles - 1) DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE, Feld(gFeld_Mitte, i - vx, j - vy) Next Next ; Feld Mitte und Feld Unten (Fall 2) ElseIf (max_y_tiles - vy) > gYmax For i = 0 To (max_x_tiles - 1) ; Teil von Feld Mitte (oberer Teil) For j = 0 To (gYmax + vy); DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE, Feld(gFeld_Mitte, i - vx, j - vy) Next ; Teil von Feld Unten (unterer Teil) For j = 0 To ((max_y_tiles - 1) - (gYmax + vy)) DrawBlock IMG_Tiles, i * cTILESIZE, (j + gYmax + vy) * cTILESIZE, Feld(gFeld_Unten, i - vx, j) Next Next EndIf ElseIf (max_x_tiles - vx) > gXmax ; Feld Mitte und Feld Rechts (Fall 3) If (-vy + max_y_tiles) <= gYmax For j = 0 To (max_y_tiles - 1) ; Teil von Feld Mitte For i = 0 To (gXmax + vx) DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE, Feld(gFeld_Mitte, i - vx, j - vy) Next ; Teil von Feld Rechts For i = 0 To ((max_x_tiles - 1) - (gXmax + vx)) DrawBlock IMG_Tiles, (i + gXmax + vx) * cTILESIZE, j * cTILESIZE, Feld(gFeld_Rechts, i, j - vy) Next Next ; Teile aller vier Felder sichtbar (Fall 4) ElseIf (max_y_tiles - vy) > gYmax ; 1.) Teil von Feld Mitte und Feld Unten For i = 0 To (gXmax + vx) ; Teil von Feld Mitte (links oben) For j = 0 To (gYmax + vy) DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE, Feld(gFeld_Mitte, i - vx, j - vy) Next ; Teil von Feld Unten (links unten) For j = 0 To ((max_y_tiles - 1) - (gYmax + vy)) DrawBlock IMG_Tiles, i * cTILESIZE, (j + gYmax + vy) * cTILESIZE, Feld(gFeld_Unten, i - vx, j) Next Next ; 2.) Teil von Feld Rechts und Feld Rechts Unten For i = 0 To ((max_x_tiles - 1) - (gXmax + vx)) ; Teil von Feld Rechts For j = 0 To (gYmax + vy) DrawBlock IMG_Tiles, (i + gXmax + vx) * cTILESIZE, j * cTILESIZE, Feld(gFeld_Rechts, i, j - vy) Next ; Teil von Feld Rechts Unten For j = 0 To ((max_y_tiles - 1) - (gYmax + vy)) DrawBlock IMG_Tiles, (i + gXmax + vx) * cTILESIZE, (j + gYmax + vy) * cTILESIZE, Feld(gFeld_Rechts_Unten, i, j) Next Next EndIf EndIf DebugLog Str(MilliSecs()-t)+" ms: Hintergrund erstellt." SetBuffer BackBuffer() ;#################################################################################################### Repeat : Cls ; Steuerung ; ############################################################ ;Bewegung nach Rechts If KeyDown(205) Or JoyXDir() = 1 vx = vx - 1; Verschiebung der Karte If -vx > gXmax ;Zuweisung ändern Tausch = gFeld_Rechts gFeld_Rechts = gFeld_Mitte gFeld_Mitte = Tausch Tausch = gFeld_Rechts_Unten gFeld_Rechts_Unten = gFeld_Unten gFeld_Unten = Tausch vx = 0 sektor_x = sektor_x + 1 ; verschobenen Feldern wieder neue Werte rechts und rechts unten zuweisen Map_Einlesen(gFeld_Rechts) Map_Einlesen(gFeld_Rechts_Unten) EndIf SetBuffer ImageBuffer(IMG_Background) ; der alte Bildschirm wird um eine Spalte verschoben und die neue Spalte drangezeichnet CopyRect cTILESIZE, 0, (max_x_tiles - 1) * cTILESIZE, max_y_tiles * cTILESIZE, 0, 0 ; Feld Mitte sichtbar If -vx <= (gXmax - max_x_tiles) ; nur Feld Mitte sichtbar, Teil aus Feld Mitte ergänzen (Fall 1) If -vy <= (gYmax - max_y_tiles) For i = 0 To max_y_tiles;-vy To (-vy + max_y_tiles) DrawBlock IMG_Tiles, (max_x_tiles) * cTILESIZE, (-vy + i) * cTILESIZE, Feld(gFeld_Mitte, (max_x_tiles) - vx, (-vy + i)) Next ; + Feld Unten sichtbar, Feld Rechts aber nicht (Fall 2) ElseIf -vy > (gYmax - max_y_tiles) ;Teil des Feldes Mitte zeichnen (oberer Teil) For i = 0 To (gYmax + vy) DrawBlock IMG_Tiles, (max_x_tiles) * cTILESIZE, i * cTILESIZE, Feld(gFeld_Mitte, (max_x_tiles) - vx, i - vy) Next ; Rest von Feld Unten dazuzeichnen (unterer Teil) For i = 0 To (max_y_tiles - (gYmax + vy)) DrawBlock IMG_Tiles, (max_x_tiles) * cTILESIZE, ((gYmax + vy) + i) * cTILESIZE, Feld(gFeld_Unten, (max_x_tiles) - vx, i) Next EndIf ; Feld Mitte + Feld Rechts sichtbar ElseIf -vx >= (gXmax - max_x_tiles) ; nur Feld Mitte und Feld Rechts sichtbar, Teil von Feld Rechts ergänzen (Fall 3) If -vy <= (gYmax - max_y_tiles) For i = 0 To max_y_tiles DrawBlock IMG_Tiles, max_x_tiles * cTILESIZE, i * cTILESIZE, Feld(gFeld_Rechts, max_x_tiles - gXmax - vx, i - vy) Next ; Teile aller Felder sichtbar, Teil von Feld Rechts und Feld Unten Rechts ergänzen (Fall 4) ElseIf -vy > (gYmax - max_y_tiles) ;Teil des Feldes Rechts zeichnen (oberer Teil) For i = 0 To (max_y_tiles - (gYmax + vy)) DrawBlock IMG_Tiles, (max_x_tiles - 1) * cTILESIZE, i * cTILESIZE, Feld(gFeld_Rechts, (max_x_tiles - (gXmax + vx)), i ) Next ; Rest von Feld Rechts Unten dazuzeichnen (unterer Teil) For i = 0 To (max_y_tiles - (gYmax + vy)) DrawBlock IMG_Tiles, (max_x_tiles - 1) * cTILESIZE, (gYmax + vy + i) * cTILESIZE, Feld(gFeld_Rechts_Unten, (max_x_tiles - (gXmax + vx)), i ) Next EndIf EndIf SetBuffer BackBuffer() EndIf ; ############################################################ ; Bewegung nach links If KeyDown(203) Or JoyXDir() = -1 vx = vx + 1; Verschiebung der Karte If -vx < 0 ;Zuweisung ändern * (Sternchen unten erläutert) Tausch = gFeld_Rechts gFeld_Rechts = gFeld_Mitte gFeld_Mitte = Tausch Tausch = gFeld_Rechts_Unten gFeld_Rechts_Unten = gFeld_Unten gFeld_Unten = Tausch vx = -gXmax sektor_x = sektor_x - 1 ; verschobenen Feldern wieder neue Werte rechts und rechts unten zuweisen Map_Einlesen(gFeld_Mitte) Map_Einlesen(gFeld_Unten) EndIf SetBuffer ImageBuffer(IMG_Background) ; der alte Bildschirm wird um eine Spalte verschoben und die neue Spalte drangezeichnet CopyRect 0, 0, (max_x_tiles - 1) * cTILESIZE, max_y_tiles * cTILESIZE, cTILESIZE, 0 ; nur Feld Mitte sichtbar, Teil aus Feld Mitte ergänzen (Fall 1 (und Fall 3)) If -vy <= (gYmax - max_y_tiles) For i = 0 To max_y_tiles DrawBlock IMG_Tiles, 0, i * cTILESIZE, Feld(gFeld_Mitte, -vx, (i - vy)) Next ; + Feld Unten sichtbar, Feld Rechts aber nicht (Fall 2 (und Fall 4)) ElseIf -vy > (gYmax - max_y_tiles) ;Teil des Feldes Mitte zeichnen (oberer Teil) For i = 0 To (gYmax + vy); To max_y_tiles DrawBlock IMG_Tiles, 0, i * cTILESIZE, Feld(gFeld_Mitte, -vx, i - vy) Next ; Rest von Feld Unten dazuzeichnen (unterer Teil) For i = 0 To (max_y_tiles - (gYmax + vy)) DrawBlock IMG_Tiles, 0, ((gYmax + vy) + i) * cTILESIZE, Feld(gFeld_Unten, -vx, i) Next EndIf ; Die Abfragen von Feld Mitte + Feld Rechts (Fall 3) sowie "alle Felder sichtbar" (Fall 4) entfallen hier, ; da die anzufügenden Tiles ausschließlich aus Feld Mitte und Feld Unten gelesen werden (aufgrund der ; Änderung der Zuweisung (mit * markiert) SetBuffer BackBuffer() EndIf ; ############################################################ ;Bewegung nach Unten If KeyDown(208) Or JoyYDir() = 1 vy = vy - 1; Verschiebung der Karte If -vy > gYmax ;Zuweisung ändern Tausch = gFeld_Unten gFeld_Unten = gFeld_Mitte gFeld_Mitte = Tausch Tausch = gFeld_Rechts_Unten gFeld_Rechts_Unten = gFeld_Rechts gFeld_Rechts = Tausch vy = 0 sektor_y = sektor_y + 1 ; verschobenen Feldern wieder neue Werte rechts und rechts unten zuweisen Map_Einlesen(gFeld_Unten) Map_Einlesen(gFeld_Rechts_Unten) EndIf SetBuffer ImageBuffer(IMG_Background) ; der alte Bildschirm wird um eine Spalte verschoben und die neue Spalte drangezeichnet CopyRect 0, cTILESIZE, max_x_tiles * cTILESIZE, (max_y_tiles - 1) * cTILESIZE, 0, 0 ; Je nach Position der Spielfigur müssen verschiedene Teile des Feldes gezeichnet werden ; Feld Mitte sichtbar If -vx <= (gXmax - max_x_tiles) ; nur Feld Mitte sichtbar, Teil aus Feld Mitte ergänzen (Fall 1) If -vy <= (gYmax - max_y_tiles) For i = 0 To max_x_tiles DrawBlock IMG_Tiles, (-vx + i) * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Mitte, (-vx + i), max_y_tiles -vy) Next ; + Feld Unten sichtbar, Feld Rechts aber nicht (Fall 2) ElseIf -vy > (gYmax - max_y_tiles) ; Teil von Feld Unten ergänzen For i = 0 To max_x_tiles DrawBlock IMG_Tiles, i * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Unten, i - vx, (max_y_tiles - (gYmax + vy))) Next EndIf ; Feld Mitte + Feld Rechts sichtbar ElseIf -vx > (gXmax - max_x_tiles) ; nur Feld Mitte und Feld Rechts sichtbar, Teil von Feld Rechts ergänzen (Fall 3) If -vy <= (gYmax - max_y_tiles) ;Teil des Feldes Mitte zeichnen (linker Teil) For i = 0 To (gXmax + vx) DrawBlock IMG_Tiles, i * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Mitte, i - vx, (max_y_tiles) - vy) Next ; Rest von Feld Rechts dazuzeichnen (rechter Teil) For i = 0 To (max_x_tiles - (gXmax + vx)) DrawBlock IMG_Tiles, ((gXmax + vx) + i) * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Rechts, i, (max_y_tiles - 1) - vy) Next ; Teile aller Felder sichtbar, Teil von Feld Unten und Feld Rechts Unten ergänzen (Fall 4) ElseIf -vy > (gYmax - max_y_tiles) ; Rest von Feld Unten dazuzeichnen (linker Teil) For i = 0 To ((max_x_tiles) - (gXmax + vx)) DrawBlock IMG_Tiles, i * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Unten, i, max_y_tiles - (gYmax + vy)) Next ;Teil des Feldes Rechts Unten zeichnen (rechter Teil) For i = 0 To (max_x_tiles - (gXmax + vx)) DrawBlock IMG_Tiles, (gXmax + vx + i) * cTILESIZE, (max_y_tiles) * cTILESIZE, Feld(gFeld_Rechts_Unten, i, max_y_tiles - (gYmax + vy)) Next EndIf EndIf SetBuffer BackBuffer() EndIf ; ############################################################ ; Bewegung nach oben If KeyDown(200) Or JoyYDir()= -1 vy = vy + 1; Verschiebung der Karte If -vy < 0 ;Zuweisung ändern * (Sternchen unten erläutert) Tausch = gFeld_Unten gFeld_Unten = gFeld_Mitte gFeld_Mitte = Tausch Tausch = gFeld_Rechts_Unten gFeld_Rechts_Unten = gFeld_Rechts gFeld_Rechts = Tausch vy = -gYmax sektor_y = sektor_y - 1 ; verschobenen Feldern wieder neue Werte rechts und rechts unten zuweisen Map_Einlesen(gFeld_Mitte) Map_Einlesen(gFeld_Rechts) EndIf SetBuffer ImageBuffer(IMG_Background) ; der alte Bildschirm wird um eine Spalte verschoben und die neue Spalte drangezeichnet CopyRect 0, 0, max_x_tiles * cTILESIZE, (max_y_tiles - 1) * cTILESIZE, 0, cTILESIZE ; nur Feld Mitte sichtbar, Teil aus Feld Mitte ergänzen (Fall 1 (und Fall 2)) If -vx < (gXmax - max_x_tiles - 1) For i = 0 To max_x_tiles - 1 DrawBlock IMG_Tiles, i * cTILESIZE, 0, Feld(gFeld_Mitte, (i - vx), -vy) Next ; + Feld Rechts sichtbar, Feld Unten aber nicht (Fall 3 (und Fall 4)) ElseIf -vx >= (gXmax - max_x_tiles) ; Teil des Feldes Mitte zeichnen (linker Teil) For i = 0 To (gXmax + vx) - 1 DrawBlock IMG_Tiles, i * cTILESIZE, 0, Feld(gFeld_Mitte, (i - vx), -vy) Next ; Rest von Feld Rechts dazuzeichnen (rechter Teil) For i = 0 To ((max_x_tiles) - (gXmax + vx)) DrawBlock IMG_Tiles, (i - vx) * cTILESIZE, 0, Feld(gFeld_Rechts, i, -vy) Next EndIf ; Die Abfragen von Feld Mitte + Feld Unten (Fall 2) sowie "alle Felder sichtbar" (Fall 4) entfallen hier, ; da die anzufügenden Tiles ausschließlich aus Feld Mitte und Feld Rechts gelesen werden (aufgrund der ; Änderung der Zuweisung (mit * markiert) SetBuffer BackBuffer() EndIf ;################################################## ; Karte zeichnen DrawBlock IMG_Background, 0, 0 ;################################################## ; Ausgabe Text 10,10, "Auflösung: " + gGraphicsWidth + "*" + gGraphicsHeight Text 10,25, "Größe der Einzeltiles: " + cTILESIZE Text 10,40, "Maximale Anzahl Tiles pro Bildschirm: " + max_x_tiles + "*" + max_y_tiles Text 500,10, "V: " + vx + " / "+vy Text 500,25, "Sektor: " + sektor_x + " / " + sektor_y Text 500,40, "Aktueller Testwert: " Text 10,55, "M"+ gFeld_Mitte Text 10,70, "R"+ gFeld_Rechts Text 10,85, "U"+ gFeld_Unten Text 10,100, "UR"+ gFeld_Rechts_Unten If (-vx > (gXmax - max_x_tiles)) Text 10,120,"Ja" Flip Until KeyHit(1) ;#################################################################################################### DebugLog Str(MilliSecs() - t)+" ms: Spiel beendet." End Function Map_Einlesen(MapKennziffer) Local f_sektor_x, f_sektor_y Local f_Datei ; die jeweiligen Sektoren werden aus der relativen Mapbezeichnung ermittelt Select MapKennziffer Case gFeld_Mitte f_sektor_x = sektor_x f_sektor_y = sektor_y Case gFeld_Rechts f_sektor_x = sektor_x + 1 f_Sektor_y = sektor_y Case gFeld_Unten f_sektor_x = sektor_x f_Sektor_y = sektor_y + 1 Case gFeld_Rechts_Unten f_sektor_x = sektor_x + 1 f_Sektor_y = sektor_y + 1 End Select ; Karte laden f_Datei = ReadFile("x" + Str(f_sektor_x) + "y" + Str(f_sektor_y) + ".map") If f_Datei = 0 DebugLog ">> FEHLER: Datei x" + Str(f_sektor_x) + "y" + Str(f_sektor_y) + ".map nicht gefunden!" For i = 0 To gXmax For j = 0 To gYmax Feld(MapKennziffer, i, j) = ReadShort(f_Datei) Next Next End Function Gruß, garret |
||
>>nec aspera terrent<< (Auch Widerwärtigkeiten schrecken nicht) |
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hab ich das richtig verstanden, dass du die Tiles immer in ein großes Hintergrundbild kopierst? Oo
Wenn das schneller ist als nur sichtbare Tiles zu zeichnen, okay. Das Problem scheint mir das verschieben nach oben und unten zu sein - aber durch den Code durchsteigen warum das so ist... Eine viel bessere alternative habe ich grade aber auch nicht zur Hand. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich denke schon, dass es schneller ist, an ein großes Hintergrundbild nur die benötigten Tiles anzuhängen, als jedesmal 32x24 Tiles zu zeichnen. Korrigiert mich wenn ich da falsch liege. Wenn ich also nach oben laufe, brauche ich eine Zeile Tiles aus Feld_Mitte und eventuell aus Feld_Rechts.
Und EBEN das Verschieben bereitet doch die Probleme... |
||
>>nec aspera terrent<< (Auch Widerwärtigkeiten schrecken nicht) |
![]() |
kriD |
![]() Antworten mit Zitat ![]() |
---|---|---|
warum sollte es schneller sein, ein großes bild anzuzeigen (das man sogar noch andauern bearbeiten muss), als kleine bilder, die zusammen eine genausogroße fläche ergeben anzuzeigen? klingt unlogisch.
wenn jetzt dutzende layer übereinander gezeichnet werden müssten, könnte es einen performancevorteil bringen die ganzen layer in ein bild zu zeichenn, da sich ansonsten die tiles überlappen und somit stellen doppelt gezeichnet werden, was bei einem einzelnen bild nicht der fall wäre. aber ansonsten würde ich sagen, das das "normale" anzeigen von tiles schneller ist. lg kriD |
||
Wenn ich du wäre, wäre ich lieber ich! |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nehmen wir doch mal einen Vergleich: Du hast ein Poster und willst rechts ein Stück mehr haben, dafür aber links etwas weg lassen. Schneidest du dafür links etwas weg und klebst rechts eine Spalte ran oder zeichnest du das ganze Poster komplett neu?
Und um zurückzukommen: Warum sollte es schneller sein, jedes Mal 32x24 kleine Tiles zu zeichnen, die zudem noch aus einem Dim-Feld gelesen werden müssen (2 x 768 Arbeitsschritte, Lesen und Zeichnen), statt ein großes Hintergrundbild anzuzeigen (1 Arbeitsschritt) und dieses nur wenn's nötig ist zu bearbeiten? Programmiertechnisch halte ich Einzeltiles für einfacher, aber da sie (meiner Meinung nach) langsamer sind, bin ich den anderen Weg gegangen. Würde mich trotzdem freuen, wenn sich jemand auf meinen Code bezieht, unabhängig der "Performancediskussion" ![]() |
||
>>nec aspera terrent<< (Auch Widerwärtigkeiten schrecken nicht) |
BBPro2 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
seit wann kann man zu einer laufzeitfrage ne "meinung" haben ? ^^
entweder das eine ist schneller oder das andere. das probiert man aus wenn die laufzeit wichitg ist bzw berechnet es mathematisch (was ohne genaurer kenntnisse über die nebenkosten der verwendeten blitzbasic befehle nicht möglich ist aufgrund fehlender informationen) ich würde also zum ausprobieren tendieren - allerdings nur wenn die lz dir überhaupt wichtig ist. bei den heutigen rechnern und dem was du zu programmieren scheinst (keine praktische anwendung nehme ich an, mehr experimentieren (?)) sollte die lz dir vermutlich egal sein wodurch die diskussion redundant wird ![]() zum problem selbst hab ich kA, grad keinen bock den code zu lesen *g |
||
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Meine Meinung bezieht sich darauf, dass es bei früheren Versuchen unter Verwendung von Tiles beim Verschieben geruckelt hat, was bei einem großen Bild nicht der Fall war. Ich habe das also schon ausprobiert.
Allein theoretisch brauche ich bei einer 32x24 großen Karte zwei verschachtelte Schleifen und damit wie gesagt 768 Durchläufe, in denen ich jedes Mal I) aus der Karte lesen II) auf das Einzelbild zugreifen III) es zeichnen muss. I) entfällt bei einem reinen Anzeigen eines großen Hintergrundbildes. Und ansonsten wird der Rest nur einmal gemacht: einmal zugreifen, einmal zeichnen. Die Laufzeit ist mir nicht egal, deswegen habe ich mich ja aufgrund meiner Erfahrung gegen Tiles entschieden. Der Code soll, wenn er fertig ist, ins Codearchiv. Eine praktische Anwendung wird es daher nicht, eher ein weiterer Teil meines gDKs (garrets Developer Kit ![]() |
||
>>nec aspera terrent<< (Auch Widerwärtigkeiten schrecken nicht) |
![]() |
D2006Administrator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es ist selbstverständlich bedeutend langsamer. Wenn das Bild einige Male größer ist als der Sichtbereich muss dennoch immer das komplette Bild gezeichnet werden. Außerdem dauert das zeichnen großer Bilder länger als das kleiner. Und das Verhältnis ist nicht proportional, d.h. wenn man ein Bild in 4 Teile teilt, heißt das nicht, dass das Zeichnen der vier kleinen Bilder genau so lange dauert wie das des großen.
Und mal ab davon, ist der Speicherverbrauch exorbitant höher. Ein Bild von 1024*1024 benötigt schon 4 MB im Speicher. Und wozu benutzt man Tilemaps vorallem: gleichaussehende Felder sind so wirklich nur einmal vorhanden und werden nur mehrfach gezeichnet. |
||
Intel Core i5 2500 | 16 GB DDR3 RAM dualchannel | ATI Radeon HD6870 (1024 MB RAM) | Windows 7 Home Premium
Intel Core 2 Duo 2.4 GHz | 2 GB DDR3 RAM dualchannel | Nvidia GeForce 9400M (256 MB shared RAM) | Mac OS X Snow Leopard Intel Pentium Dual-Core 2.4 GHz | 3 GB DDR2 RAM dualchannel | ATI Radeon HD3850 (1024 MB RAM) | Windows 7 Home Premium Chaos Interactive :: GoBang :: BB-Poker :: ChaosBreaker :: Hexagon :: ChaosRacer 2 |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich meine selbstverständlich ein Bild, das nur genau so groß ist wie die Auflösung / der Sichtbereich. Das Teilen in 4 Karten dient nicht der Geschwindigkeitsoptimierung, sondern um die Unendlichkeit zu verwirklichen.
Wie steht es denn aber mit meinem Argument, dass bei Tiles viel mehr Durchläufe erforderlich sind? Ihr bezieht euch bisher nur darauf, dass das Anzeigen eines großen Bildes langsamer ist. Wenn ich aber Zeit spare, weil ich nur das Nötige und nicht das ganze Bild ändere, relativiert sich das doch, oder? ... Edit 1: Auf die Schnelle habe ich aus meinem Code mal einen Test gemacht. Leertaste schaltet zwischen Einzelbild und Tiles um. Auf den Zugriff aus einem Feld musste ich leider verzichten, weil es da Probleme mit dem durch CreateImage erstellten Tile-Bild gab. Jedoch ist das Zeichnen einzelner Tiles langsamer. Bei mir: Gesamtbild: 0 ms, Tiles: 14 ms Edit 2: Wenn jetzt bei meiner Methode das Lesen und Ändern des großen Bildes länger dauert als das Lesen und Anzeigen der Tiles, gebe ich mich geschlagen ![]() ![]() Edit 3: So und um es noch mal zu ändern: In meinem Code oben dauert das Verschieben der Karte nach Rechts zwischen 0 und 2 ms. Jetzt warte ich auf Gegenbeweise, warum ich aus Sicht höherer Geschwindigkeit Tiles nehmen sollte. Der Punkt für den Speicherbedarf geht natürlich an Tiles, da diskutiere ich auch nicht ![]() Code: [AUSKLAPPEN] ;####################################################################################################
; Zeittest großes Hintergrundbild vs. Tiles ;#################################################################################################### ;#################################################################################################### ; Variablen Global gGraphicsWidth=1024 Global gGraphicsHeight=768 Graphics gGraphicsWidth,gGraphicsHeight,32,2 Const cTILESIZE = 16 ; Größe der Tiles Global max_x_tiles = gGraphicsWidth / cTILESIZE ; Anzahl der maximal gleichzeitig anzeigbaren tiles Global max_y_tiles = gGraphicsHeight / cTILESIZE ; Bilder Global IMG_Background ; Bild, das zusammengesetzt den Hintergrund darstellt IMG_Tiles = CreateImage((cTILESIZE),cTILESIZE) ;das Bild, das die Einzel-Tiles enthält SetBuffer ImageBuffer(IMG_Tiles); Einzelbild mit Farbe füllen Color 0,100,200 For i = 0 To (cTILESIZE - 1) For j = 0 To cTILESIZE - 1 Plot i,j Next Next Color 255,255,255 ;#################################################################################################### ; das eigentliche Hintergrundbild erstellen IMG_Background = CreateImage(gGraphicsWidth, gGraphicsHeight) SetBuffer ImageBuffer(IMG_Background) ; Je nach Verschiebung der Karte (aus Speicherstand geladen) werden Teile aus bestimmten Feldern gebraucht For i = 0 To (max_x_tiles - 1) For j = 0 To (max_y_tiles - 1) DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE, 0 Next Next SetBuffer BackBuffer() ;#################################################################################################### Repeat : Cls t1 = MilliSecs() ;################################################## ; Karte zeichnen If Modus = 0 DrawBlock IMG_Background, 0, 0 ElseIf Modus = 1 For i = 0 To (max_x_tiles - 1) For j = 0 To (max_y_tiles - 1) DrawBlock IMG_Tiles, i * cTILESIZE, j * cTILESIZE Next Next EndIf t2 = MilliSecs() If KeyHit(57) Modus = 1 - Modus ;################################################## ; Ausgabe Text 10,10, "Auflösung: " + gGraphicsWidth + "*" + gGraphicsHeight Text 10,25, "Größe der Einzeltiles: " + cTILESIZE Text 10,40, "Maximale Anzahl Tiles pro Bildschirm: " + max_x_tiles + "*" + max_y_tiles Text 10,70, "Zeit: "+(t2-t1)+" ms" Text 10,100, "Modus: "+Modus Text 100,200, "Leertaste zur Modusänderung" Text 100,220, "0 = Gesamtbild, 1 = Tiles" Flip Until KeyHit(1) End |
||
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn ich mal wild vermute, sind Tiles dazu da, um speichersparend auf das Spiel einzuwirken. Früher war dies notwendig, weil der Speicher doch sehr begrenzt war. Da lag es nahe, sich wiederholende Levelelemente nur einmal im Grafikspeicher abzulegen. Kürzere Ladezeiten bringt sowas auch mit sich. Auch wird der Levelaufbau einheitlicher und strukturierter.
Tiles sind aus heutiger Sicht irgendwie outdated. Es sei denn, du willst ein Spiel machen, dass auch auf älteren Systemen läuft, da ist es schonmal eine nette Herausforderung, die 16mb Grafik-Schranke nicht zu überschreiten. Endlos-Maps wollt ich auch schon immer mal realisieren. Dabei wollte ich wie bei den großen Vorbildern die neuen Bilder immer nachstreamen. Aber leider bekommt man mit BB sowas nicht vernünftig hin, denn dazu bräuchte man meines Erachtens coole Nebenläufigkeit. |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es geht mir hier nicht darum, über Vorteile von Tiles zu sprechen, sondern um eben endlose Maps zu realisieren. Der Code funktioniert vom Prinzip (also dem "Streaming") her schon, nur überlappt es in der Darstellung an einigen Stellen noch.
Wenn also jemand die Güte hätte, sich meinen Code mal anzusehen, statt jetzt noch über die Methode zu diskutieren. Bis auf einen Beweis, dass meins schneller ist, bin ich kein Stückchen weiter ![]() |
||
>>nec aspera terrent<< (Auch Widerwärtigkeiten schrecken nicht) |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
garret
1. Gibt es einen guten Grund dafür, warum du alle Variablen als Global deklarierst? Das ist eine sehr schlechte Angewohnheit, welche man gleich eliminieren sollte. 2. Tiles mit 16x16 machen nicht unbedingt ein besseres Leveldesign aus. Oft werden Tiles so klein gewählt, um die eigene unzulänglichkeit beim pixeln durch hoches Tilesdichte zu kompensieren. Allerdings leidet dadurch das Leveldesign an sich. Denn spätestens dann, wenn man pro bildschirmfüllendes Leveldesign eine gewisse Zeit braucht, wird man auch hier lieber ''mal eben schnell'' daran arbeiten, als sinnvolles filigranes Leveldesign erstellen. Von ganzen Levels mit mehreren bildschirmfüllenden Design mal ganz abgesehen. Ansonsten werden so kleine Tiles nur bei portablen Spielegeräten gebraucht (z.B. Nintendo DS etc...). 3. Dein Testcode zeigt den Unterschied nur sehr schlecht. Deine 0 ms vs. 14 ms würden zeigen, dass das ''Ein-Bild-System'' ja 14x bis unendlich schneller ist. Ein FPS-Test zeigt allerdings ein Verhältnis 1:5. Nimmt man nun nicht mehr 16x16 Tiles, sondern 32x32 Tiles. Dann beträgt das Verhältnis nur noch 4:5 (also 160:200 FPS). Bei 64x64 Tiles beträgt das Verhältnis nur noch 184:200 FPS. Das Problem ist also nicht das Tilesystem an sich, sondern deine Minitiles die nur für Minibildschirme benutzt werden sollten (Siehe auch Punkt 2). 4. Außerdem sparst du dir ja keine doppelt verschachtelte Schleife dadurch, dass du dein ''Ein-Bild-System'' benutzt. Denn dann hast du ja überhaupt keine Kontrolle mehr darüber, wo Kollisionen und andere Sachen vorhanden sind. Bei einem Tilesystem hast du die Informationen direkt und ''für umsonst''. 5. Dein ''Ein-Bild-System''-Test, testet auch keine Updates, die beim scrollen durch die Map notwendig sind. Gerade solche Updates könnten sehr nervig auf den Spieler wirken. Ein Spieler wird lieber ewig auf 30 FPS spielen, als auf 60 FPS wo 3mal in der Sekunde ein Frame ausfällt, weil grad wieder ein Update durchgeführt wurde. Und beim scrollen durch die Map mit 16x16 Tiles, müsste man bei einer Ein-Pixel/Frame-Bewegung 3 bis 4 mal in der Sekunde updaten. - - - Alles in allem: Mir ist es egal wie du deine Map gestalltest. Aber generell würde ich mal behaupten, ein System welches sich über Jahrzehnte bewährt hat und immer noch praktiziert wird, und es als gut bezeichnen. Über andere Systeme würde ich mir nur Gedanken machen, wenn dadurch auch ein typisches und anderes Erscheinungsbild erreicht wird. So wie zum Beispiel beim Spiel ''Soldat'', wo eben mit Polygonen gearbeitet wird. Edit1: Ich nehme an, dass keiner wirklich Lust hat, sich dieses Vorgehen vorzunehmen und den Code entsprechend zu bearbeiten. Ich würde dir einfach mal dazu raten, sich einem Tilesystem mit 32x32er Tiles anzunehmen. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
So wie ich dein Problem verstehe, willst du einfach eine Map realisieren, die sich auf alle 4 Seiten unendlich weit wiederholt - sehe ich das richtig?
In diesem Falle ist die Lösung relativ einfach: BlitzBasic: [AUSKLAPPEN] Const GWIDTH = 800 Das verwendete Tileset ist das, was bei dir im Download beiliegt. Das Prinzip ist so, dass der momentan sichtbare Bereich gezeichnet wird und negative Koordinaten bzw. zu grosse Koordinaten einfach von der anderen Seite her wieder reinkommen. Falls du mehrere Maps aneinander reihen willst, musst du sie halt anfangs in das grosse Array reinladen, um diese Methode verwenden zu können. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ hectic:
1. Global ist wohl wirklich nur eine schlechte Angewohnheit... 2. Die Größe von 16 habe ich gewählt, weil ich später eine feinere Kollision wollte, als immer nur alle 32 Pixel. Der Gedanke ist eben, dass eine 32x32 Spielfigur nicht so eckig mit einem 96x32 Baum kollidieren soll ![]() Da die Tilegröße aber in der Konstanten cTILESIZE festgelegt ist, kann man das im Nachhinein leicht anpassen. Es ging mir also nicht darum, das Tilesystem zu verteufeln, sondern einen Kompromiss zwischen feinerer 16x16-Tilekollision und dessen Anzeige zu finden. Und wenn niemand mal was anderes probieren würde, hätten wir doch nichts zu diskutieren ![]() 3., 4. und 5.: Dass weniger Tiles schneller gezeichnet werden erscheint mir auch logisch. Sehe ich in meinem Test unter Verwendung von 32x32 und 64x64 doch. Allerdings gebe ich zu, dass lediglich die reine Dauer des Zeichnens getestet wird und dies nicht der einzige Faktor ist. @ Noobody: Ich meine unendliche, sich nicht wiederholende Maps, also Hintergründe. Die Verschiebung soll so schnell sein, dass ich meine Figur mit einem Vehikel fahren lassen kann, ohne dass es ruckelt. Eine Frage hätte ich noch zu deinem Code: Das eigentliche Tile wird doch in deiner Funktion InitMap in der Zeile Code: [AUSKLAPPEN] MapData( X, Y ) = ( X/10 + Y/10 ) Mod 16
festgelegt, so dass ich dort den Tiles ihren Wert zuweisen muss, oder? MfG garret P.S. Ohne aufdringlich wirken zu wollen - mir würde wirklich viel daran liegen, wenn ihr euch meine Ablaufautomatik mal ansehen würdet (Link sieben Posts weiter oben). |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
garret hat Folgendes geschrieben: Ich meine unendliche, sich nicht wiederholende Maps, also Hintergründe.
Das musst du ein wenig genauer erklären. Wenn deine Maps sich unendlich weit ausdehnen, aber nicht wiederholen sollen, musst du sie ja ständig neu generieren. Ich glaube aber nicht, dass du das meinst, daher wäre eine besser Erklärung nicht schlecht ![]() Zu deiner Frage zum Code: Ja, das Tile wird in dieser Zeile eingesetzt. Ich hab einfach 10x10 Tiles grosse Blöcke erstellt, damit man die Wiederholung besser sieht (bei einer zufälligen Map ist das ja nicht so einfach zu erkennen). Deine Ablaufautomatik habe ich mir angesehen, aber das Problem bei solchen Systemen ist immer, dass so etwas entweder zu allgemein oder zu spezialisiert gehalten ist. Du hast sicher viel Arbeit reingesteckt, aber normalerweise schreibt man sich so ein System selbst, um es perfekt auf das eigene Projekt zuschneiden zu können. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
garret |
![]() Antworten mit Zitat ![]() |
---|---|---|
Noobody hat Folgendes geschrieben: Das musst du ein wenig genauer erklären. Wenn deine Maps sich unendlich weit ausdehnen, aber nicht wiederholen sollen, musst du sie ja ständig neu generieren. Ich glaube aber nicht, dass du das meinst, daher wäre eine besser Erklärung nicht schlecht
Ich meine eine ganz "normale" Welt, wo die Tiles nicht generiert, sondern z.B. aus einer Datei gelesen werden. Da wiederholt sich ein- und dasselbe Haus mit Brunnen ja auch nicht alle paar Karten. Also im Gegensatz zu einem scrollenden Himmel, wo alle 50 Tiles die gleiche Wolke vorbeizieht ![]() Und zur AA: Sie ist eigentlich so allgemein gehalten, dass man sie in fast jedes Spiel integrieren kann. Das hat bei einem alten Projekt, wo ihr Einsatz nicht von vornherein geplant war, problemlos geklappt und uns viel Arbeit und Zeit gespart. Außerdem ist sie ja individuell erweiterbar oder eben verringerbar, so dass man sie sich selbst spezialisieren kann. Genau DAS ist ja ihr Vorteil. Aber das sollte nicht in diesem Thema besprochen werden, dazu gibt's schon das andere. Das hier war nur Schleichwerbung ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group