TileMap mit Draw3D
Übersicht

![]() |
M0rgensternBetreff: TileMap mit Draw3D |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey Leute.
Ich bin grade dabei Code für ne Tilemap zu programmieren. Ich benutze dabei Draw3D und hab jetzt ein Problem. Ich hab die TIlemap ganz normal geschrieben und dann auf 3D umgeschrieben. Aber jetzt sieht alles ziemlich verschoben aus. Ich weiß nur nicht woran das liegt (hab mit Tilemaps auch noch kaum Erfahrung). Hier ist mal der Code: Code: [AUSKLAPPEN] AppTitle "StrategieGame"
Include "Includes\Draw3D.bb" Graphics3D 1024,768,0,2 SetBuffer BackBuffer() SeedRnd MilliSecs() Local Timer=CreateTimer(60) Global Camera=CreateCamera() CameraClsColor Camera,5,5,5 DrawInit3D(Camera) Origin3D(1024,768) Dim Map(6,6) Restore map1 For x = 0 To 6 For y = 0 To 5 Read Map(x,y) Next Next Global Tiles = loadimage3d("gfx\Tiles\TileSet1.png", 1) Global TileFrame TileFrame = grabimage3d(Tiles, 0, 0, 32, 32) grabimage3d(Tiles, 32, 0, 64, 32) grabimage3d(Tiles, 64, 0, 96, 32) grabimage3d(Tiles, 96, 0, 128, 32) Repeat For x = 0 To 6 For y = 0 To 6 drawimage3d(TileFrame, x*32, y*32, 0, 0, 1, Map(x,y)) Next Next WaitTimer(Timer) RenderWorld Clear3D() Flip 0 Until KeyDown(1) .map1 Data 0,0,0,0,0,0,0 Data 0,1,1,1,0,0,0 Data 0,1,1,1,0,0,0 Data 0,1,0,2,2,2,0 Data 0,0,0,3,3,3,0 Data 0,0,0,1,3,2,0 Data 0,0,0,0,0,0,0 Und hier ein BIld von dem PRoblem: Lg, M0rgenstern |
||
![]() |
Nicdel |
![]() Antworten mit Zitat ![]() |
---|---|---|
Was erwartest du? Falls die Map oben links sein sollte, liegt das einfach daran, dass das Koordinatensystem von Draw3D seinen Ursprung bei 0,0 hat. | ||
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7 |
![]() |
Goodjee |
![]() Antworten mit Zitat ![]() |
---|---|---|
die letzten beiden parameter von grabimage3d sollten vermutlich immer 32,32 sein...deine tiles sind schließlich immer gleich groß | ||
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/ |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja, aber der vorletzte Parameter ist die x2 Koordinate.
Das ist x1, y1, x2, y2 @Nicdel: Es geht eher darum, dass die Tiles ineinander verschoben sind, wie man auf dem Bild sehen kann. Lg, M0rgenstern |
||
![]() |
Abrexxes |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi, ich würde gerade bei Tiles nicht mehr mit Draw3D anfangen. Draw3D2 besitzt nämlich für sowas gleich verbesserte Funktionen und ist Pixel genau. Wie ich in der letzten Beta sehen konnte hat hectic sogar einen mini Tile Editor (siehe Code) bei denn Beispielen dabei.
Also noch etwas warten und alles wird gut.... ![]() cu Code: [AUSKLAPPEN] Graphics3D 1024,768,0,2
SetBuffer BackBuffer() Local Timer=CreateTimer(58) Local Camera=CreateCamera() CameraClsColor Camera,64,64,64 Include "..\Includes\Draw3D2.bb" DrawInit3D(Camera) ;Konstantenzuweisungen Const TILESIZE=64 Const XMAPSIZE=39 Const YMAPSIZE=29 Const XOFFSET=-480 Const YOFFSET=-352 Const XWALL=1535 Const YWALL=1151 ;Fonttextur laden und Schreibfähig machen Local Font=FontRange3D(LoadImage3D("..\Fonts\KarmaticArcade(3os4p).png",2,2,0,-100)):SetFont3D(Font,1,1,-4,0) ;Bilder laden und graben Local LoadedImage=LoadImage3D("..\Data\tilemap.png",1,2,0,-10) Local GrabedImage=GrabAnimImage3D(LoadedImage,TILESIZE,TILESIZE,1,4) Local Glow=LoadImage3D("..\Data\Glow.png",2,2,0,-20) ;Variablendeklarationen Local Xi,Yi,XPos=512,YPos=512,XRtv,YRtv ;Map-Array dimensionieren Dim Map(XMAPSIZE,YMAPSIZE) ;Zufallsmap erstellen For Yi=0 To YMAPSIZE For Xi=0 To XMAPSIZE Map(Xi,Yi)=Rand(1,3) Next Next ;Hauptschleife While Not KeyHit(1) ;Maus-Mapbewegung If MouseDown(3) Then XPos=XPos-MouseXSpeed3D YPos=YPos-MouseYSpeed3D End If ;Cursor-Mapbewegung XPos=XPos+(KeyDown(205)-KeyDown(203))*2 YPos=YPos+(KeyDown(200)-KeyDown(208))*2 ;Bewegungsgrenzen If XPos<0 Then XPos=0 If YPos<0 Then YPos=0 If XPos>XWALL Then XPos=XWALL If YPos>YWALL Then YPos=YWALL ;Array Schrittmacher XRtv=Floor(XPos/TILESIZE) YRtv=Floor(YPos/TILESIZE) ;Map zeichnen For Yi=0 To 12 For Xi=0 To 16 If Map(Xi+XRtv,Yi+YRtv)>0 Then DrawImage3D(GrabedImage,XOFFSET-(XPos Mod TILESIZE)+Xi*TILESIZE,YOFFSET-(YPos Mod TILESIZE)+Yi*TILESIZE,Glow,0,1,Map(Xi+XRtv,Yi+YRtv)) If MouseOver3D Then Text3D(Font,MouseXOld3D+20,MouseYOld3D,(Xi+XRtv)+" "+(Yi+YRtv),0) If MouseDown3D=1 Then Map(Xi+XRtv,Yi+YRtv)=1 If MouseDown3D=2 Then Map(Xi+XRtv,Yi+YRtv)=2 Next Next ;Positionsinfo anzeigen Text3D(Font,-128,-192,"<#ff0>cursor</#> or <#f00>middle mouse</#> to move map",0) Text3D(Font,-128,-224,"XPos : "+XPos,0) Text3D(Font,-128,-256,"YPos : "+YPos,0) ;Draw3D2-Standardinfo anzeigen Text3D(Font,-460,+340,"Draw3D2 V.1.0",0) Text3D(Font,+460,+340,"Time: "+CurrentTime(),2) Text3D(Font,0,-340,"EXAMPLE · <#fc4>CREATE 2D TILEMAP</#> · EXAMPLE",1,0,Sin(MilliSecs())) ;Standardabschluss WaitTimer Timer RenderWorld Clear3D() Flip 0 Wend End |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sorry Abrexxes, aber das hilft bei meinem Problem grade gar nicht weiter.
Ich durfte mir zwar auch schon die Beta besorgen, aber das Projekt für das ich die Tilemap brauche ist noch komplett in Draw3D. Danke für deine Bemühungen, aber gibts denn niemanden der mir ganz einfach sagen kann wo der Fehler ist? Lg, M0rgenstern |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem hat Goodjee gut erklärt. Wenn du Tiles für eine Tilemap grabst, dann sollte jedes Tile gleich groß sein. Und genau das sind sie bei dir nicht. Die letzten beiden Parameter von GrabImage3D müssen bei dir also 32,32) sein.
Nicdel hat auch ein sinnvollen Beitrag geschrieben, indem du natürlich wegen der Nullposition=MitteBildschirm die Map entsprechend verschieben musst. Und damit du gar nicht erst damit anfängst mit Y=-Y zu rechnen, kannst du (muß aber nicht) gleich deine Data-Zeilen umdrehen. So das die erste Zeile die letzte, die zweite die vorletzte ... ist. Also: Data 0,0,0,0,0,0,0 Data 0,0,0,1,3,2,0 Data 0,0,0,3,3,3,0 Data 0,1,0,2,2,2,0 Data 0,1,1,1,0,0,0 Data 0,1,1,1,0,0,0 Data 0,0,0,0,0,0,0 Edit1: Aber wie ich zu jeder Tilemap sage, egal ob 2D oder 3D. Erstell dir ein billigen Editor. Der ist mit wenigen Zeilen Code gemacht und erlaubt dir schnelles Ändern bei größeren Maps. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also, jetzt hab ich glaub ich wirklich Mist gebaut.
Sorry wegen dem GrabImage. War mein Fehler. Wenn m,an das richtig macht, dann funktioniert das mit dem Ausrichten auch. Aber jetzt hab ich -x und -y geschrieben und jetzt steht die tilemap nicht nur aufm kopf sondern wenn ich die data an einer Stelle änder, z.B. am Rand, dann hat sich aufm Bild in der Mitte was geändert. @hectic: Zu dem Mapeditor will ich ja grade hin. Aber dazu muss ich die Map erstmal richtig anzeigen lassen. Lg, M0rgenstern EDIT: Der Fehler von wegen alles verschiebt sich hab ich gefunden. Hatte eine For SChleife fürs array nur bis 5 net bis 6. Aber meine Map steht komplett auf dem Kopf oder so. Kann ich das irgendwie umrechnen? Sonst muss man so verquer denken. (Momentan stehts auf (-x)*32 und y*32) Sorry, war falsch rum Lg, M0rgenstern |
||
![]() |
Goodjee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Code: [AUSKLAPPEN] For x = 0 To 6 For y = 0 To 5 Read Map(x,y) Next Next ich würde sagen hier musst du die beiden schleifen vertauschen...immerhin willst du yweise auslesen |
||
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/ |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sorry, aber ich versteh grade nur noch Bahnhof.
Ich blick einfach nicht durch, warum das nicht geht. Bin ich grade wirklich zu blöd dafür? Lg, M0rgenstern (Ohne Draw3D Befehle hab ichs hinbekommen) |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ein 2D-Array ist im Grunde auch nur ein linearer Speicher irgendwo im RAM. Und so ein Speicher liesst man am schnellsten aus, wenn der Nachfolgewert hinter dem zuvor gelesenem ausgelesen wird. Auch diesem Grund sollte man jede X/Y-verschachtelte-Schleife in folgender Reihenfolge machen:
Code: [AUSKLAPPEN] For y = 0 To 5
For x = 0 To 6 Read Map(x,y) Next Next Und das ganz unabhängig von rein 2D oder der Draw3D. Das hat ganz einfach was mit dem Aufbau eines 2D-Arrays zu tun. ![]() - - - Zu dem Editor. Ich bin grad irgenwie richtig müde, und hab entsprechend keine Lust extra ein Code zu schreiben. Aber gerade mit der Draw3D kann man wegen den einfach zu deklarierende Buttons einen Editor mit noch weniger Aufwand erstellen. Dazu einfach jedes Tile beim zeichnen mit Button=1 oder von mir aus mit Button=GlowImageHandle deklarieren und anschliessend über If MouseDown3D=1 Then Map(X,Y)=NeueTileNummer prüfen und ggf. das entsprechende Tile umschreiben. Ein Ansatz davon kannst du von Abrexxes Post einsehen. Bei einer statischen - nicht skrollenden Map - sparst du dir die dort eingesetzte Varieble XRtv und YRtv. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey Leute.
Also ich habs jetzt geschafft die Map in der Mitte vom Koordinatensystem zu platzieren. Indem ich for x = -3 to 4 geschrieben hab. Sieht ganz gut aus. Aber leider steht das Dim Feld immernoch auf dem Kopf. Gibts ne Möglichkeit das ganze so umzurechnen, dass wenn ich im Dim Feld ein Tile abänder das Tile dann später nicht gespiegelt angezeigt wird sondern genau an der Stelle? Das ist nämlich mein Problem im Moment. Lg, M0rgenstern Wäre echt nett. EDIT: Hier ist noch der Code: Code: [AUSKLAPPEN] AppTitle "StrategieGame"
Include "Includes\Draw3D.bb" Graphics3D 1024,768,0,2 SetBuffer BackBuffer() SeedRnd MilliSecs() Local Timer=CreateTimer(60) Global Camera=CreateCamera() CameraClsColor Camera,5,5,5 DrawInit3D(Camera) Origin3D(1024,768) Dim Map(7,7) Restore map1 Const XOffset = -(1024/2) Const YOffset = -(768/2) For x = -3 To 4 For y = -3 To 4 Read Map(x,y) Next Next Global Tiles = loadimage3d("gfx\Tiles\TileSet1.png", 1) Global TilesNorm = LoadAnimImage("gfx\Tiles\TileSet1.png", 32, 32, 0, 4) Global TileFrame TileFrame = grabimage3d(Tiles, 0, 0, 32, 32) grabimage3d(Tiles, 32, 0, 32, 32) grabimage3d(Tiles, 64, 0, 32, 32) grabimage3d(Tiles, 96, 0, 32, 32) Repeat WaitTimer(Timer) Cls For x = -3 To 4 For y = -3 To 4 DrawImage3D(TileFrame, (x)*32, (y)*32, 0, 0, 1, Map(x,y)) ;DrawImage(TilesNorm, (x*32), (y*32), Map(x,y)) Next Next RenderWorld Clear3D() Flip 0 Until KeyDown(1) .map1 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 Data 0,0,0,0,0,0,0,0 |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Dein -3 to +4 verursacht ein Array out of Bounds oder wie auch immer so eine Fehlermeldung gemeldet wird. Ehrlich verstehe ich nicht, warum sich so viele mit den Koordinatensystem so schwer machen. Es ist wirklich 1:1 nicht anders, als es bei 2D auch ist.
Bei einer 2D-Tilemap wird ein X/Y-Offset benötigt, damit beim pixelfeinen scrollen links/oben keine Lücken entstehen. Aus diesem Grund muß das X/Y-Offset jeweils minus der Tilesize sein. Bei der Draw3D ist lediglich dieses X/Y-Offset ein anderer. Also nur der Wert. Sonst ändert sich absolut nichts. Auch die ''gespiegelte'' Y-Achse kann vernachlässigt werden, da nun das Array auch so gespeichert wird. Das Feld 0,0 ist dann eben links/unten. Der Rest kommt dann von allein. Auf Data-Zeilen würde ich gänzlich verzichten. Aber zumindest diese manuel einzutragen. Wenn ich also unbedingt Data-Zeilen haben möchte, würde ich mir ein billigen Exporter zu schreiben, dessen Textzeilen ich dann nur ins Projekt pasten muß. Aber für das bessere Management bevorzugt man i.d.R. Leveldateien die geladen werden. Ist aber auch Geschmackssache. - - - Eine Grundregeln: Eine verschachtelte X/Y-Schleife wird zuerst mit For Y... dann mit For X... bearbeitet. Das hat einmal den Grund, dass es Zeilenweise geschieht. Also so, wie man es auch aus dem lesen aus einem Buch herraus der Fall wäre. Aber der Hauptgrund ist einfach, dass der Speicher in dieser Reihenfolge schneller ausgelesen werden kann. Bei größeren Tilemaps macht es sich sogar deutlich bemerkbar. - - - Damit nun die Spannung nicht zum überlaufen gebracht wird, hab ich mir mal die Mühe gemacht, dein Code einmal zu überarbeiten. Die Data-Zeilen hab ich weg geschmissen und stattdessen eine Lade/Speicher-Routine erstellt. Mit F1 kann man ein gespeicherten Leven laden, mit F2 kann man die aktuelle Map abspeichern. Noch komplett mit statischem Dateinamen. Aber das kannst du dann ja machen, falls Inderesse besteht. Code: [AUSKLAPPEN] AppTitle "StrategieGame"
Include "Includes\Draw3D.bb" Graphics3D 1024,768,0,2 SetBuffer BackBuffer() SeedRnd MilliSecs() Local Timer=CreateTimer(58) Global Camera=CreateCamera() CameraClsColor Camera,5,5,5 DrawInit3D(Camera) Origin3D(1024,768) Dim Map(7,7) Const XOFFSET = -256 Const YOFFSET = -192 Global Tiles = LoadImage3D("gfx\Tiles\TileSet1.png", 1) Global TileFrame = GrabImage3D(Tiles, 0, 0, 32, 32) GrabImage3D(Tiles, 32, 0, 32, 32) GrabImage3D(Tiles, 64, 0, 32, 32) GrabImage3D(Tiles, 96, 0, 32, 32) Repeat For y = 0 To 7 For x = 0 To 7 DrawImage3D(TileFrame, (x)*32+XOFFSET, (y)*32+YOFFSET, 1, 0, 1, Map(x,y)) If MouseDown3D=1 Then Map(x,y)=1 If MouseDown3D=2 Then Map(x,y)=Rand(0,3) Next Next ;F1=LOAD If KeyHit(59) Then Datei = ReadFile ("level.dat") For y = 0 To 7 For x = 0 To 7 Map(x,y)=ReadByte(Datei) Next Next CloseFile Datei Print "LOAD" Delay 1000 End If ;F2=SAVE If KeyHit(60) Then Datei = WriteFile ("level.dat") For y = 0 To 7 For x = 0 To 7 WriteByte Datei,Map(x,y) Next Next CloseFile Datei Print "SAVE" Delay 1000 End If WaitTimer(Timer) RenderWorld Clear3D() Flip 0 Until KeyDown(1) |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey Hectic.
Vielen Dank, das ganze funktioniert super. Ich bin es auch schon am Umschreiben, damit es noch besser passt etc. Könntest du mir aber bitte nochmal erklären wie du auf das X und YOffset kommst? Deine Erklärung oben hab ich nicht verstanden und ich versuch halt größere Maps zu erstellen. ALso, wodurch errechnet sich das Offset genau? Lg, M0rgenstern |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Was willst du denn da berechnen? Ein Offset ist ein Ausgleichwert um es passend zu machen. Als Beispiel: Wenn du ein Quecksilberthermometer hast und einfach zuviel Quecksilber eingefüllt hast, dann stimmt ja die anzeige nicht mehr. Was man dagegen tun kann ist entweder immer wieder Quecksilber abfüllen oder man verschiebt einfach die Skalla. Und genau so eine Verschiebung ist ein X/Y-Offset beim Programmieren. Diese wird bei pixelscrollenden Maps auch bei 2D benötigt. Man zeichnet also eine Map, und passt diese dann an die Bildschirmposition an. Vor dem Berechnen solcher Offsets ist es oft einfacher es durch ausprobieren anzugleichen.
Aber ausrechnen für die Draw3D(2) geht auch: XOFFSET=-(Bildschirmbreite+XTILESIZE)/2 Bzw. je nachdem wie die Map gezeichnet wird könnte auch folgendes richtig sein: XOFFSET=-(Bildschirmbreite+XTILESIZE)/2+XTILESIZE - Oder einfach mal OFFSET bei Googles oder Wikipedia eingeben. Wikipedia sagt: in der Technik (engl. offset für Regelabweichung, Versatz) ein konstanter additiven oder subtraktiven systematischer Fehler einer Zustandsgröße oder eines Messwertes |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke Hectic.
Ich habs jetzt verstanden. Hab jetzt auch durchgeblickt, dass ich den Offset wert auch zum Scrollen nutzen kann. Ich hab noch eine Frage: Du meintest, ich soll nach dem y Wert durch die Map gehen (Also in den For Schleifen). Jetzt hab ich aber gemerkt, dass ich dadurch nur den x Wert kleiner als den Y Wert stellen kann. D.h. Wenn derX Wert für die MapGrösse Größer wird als der YWert dann bekomm ich ne Fehlermeldung. Würde es denn viel an meiner Map ausmachen, wenn ich das ganze nach X Durchgehen würde? Denn der x Wert sollte im allgemeinen Größer als der Y Wert sein, da der Bildschirm ja auch breiter ist. Lg, M0rgenstern |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
1) Das OFFSET ist nicht zum scrollen der Map da. Da wäre nicht nur die Variablenbezeichnung falsch, sondern die Map schon grundlegend falsch aufgebaut. Eine Map die scrollen kann, wird so gezeichnet, dass stets immer nur der sichtbare Teil gezeichnet wird. Der übrige Teil wird gar nicht erst gezeichnet. Genau so ein scrolling hat Abrexxes weiter oben als beigelegten Beispielcode der Draw3D2 gepostet. Das OFFSET ist wirklich nur zur Positionierung der Map an den Bildschirmverhältnissen und wird pauschal zu jedem Tile hinzuaddiert. Das hättest du aus dem Einzeiler aus Wikipedia auch auslesen können (konstante Regelabweichung).
2) Wenn du die beiden Schleifen X und Y tauscht, ist es wohl klar, dass du die Zielgrößen beider Schleifen auch tauschen mußt. Aber dazu sei gesagt, dass dein Array im ersten Post falsch zu den Data-Zeilen eingelesen wird. Wenn deine Map in X 20 und in Y nur 15 Elemente hat. Dann wird folgender Code dazu benötigt: Code: [AUSKLAPPEN] Map(19,14)
For y = 0 To 14 For x = 0 To 19 Map(x,y)=??? Next Next So eine Logik ist Grundwissen. Ohne das blind zu können, solltest du erst gar nicht an eine pixelweise scrollbare Map auch nur denken. Eine Map einfach nur zu verschieben ist nicht das, was man unter scrollen versteht. 3) Wenn du zuerst X und dann eine Y -Schleife schreibst, würde es nicht viel in deiner Map ausmachen. In so einer kleinen Map, wird diese sogar kaum messbar sein. Aber so ein ''Workaround'' zeigt nur, dass du nicht gewillt bist offensichtlich falsches richtig zu machen. Und wenn du schon bei 5 Zeilen Code so ein Problem mit hast, dann frag ich mich wirklich, wie es bei einem richtigem Projekt sein würde. Ich kann dir wirklich nur dazu raten, sich erst gar nicht falsches anzugewöhnen. Bei einer ISO-Map wäre dies sogar komplett falsch dargestellt... |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Okay, tut mir leid.
Das ganze kam jetzt wohl falsch rüber. Oben hieß es, dass ich alles nach Y durchgehen muss. Und daran hab ich mich jetzt aufgehangen. Die DataZeilen hab ich ja sowieso schon abgeschafft. Ich werde mir das heute Abend nochmals genauer angucken, hatte dazu am Wochenende nicht wirklich die Gelegenheit. Das mit dem Offset hab ich JETZT verstanden. Tut mir leid, es sollte nicht falsch rüberkommen. Wie gesagt, ich habs jetzt schon eher verstanden und werde das ganze nochmal überarbeiten. Lg, M0rgenstern Vielen Dank. |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nagut, Goodjee hat ein Beispiel gepostet und leider den geposteten Code nicht bereits korrigiert gepostet. Sondern nur darauf hingewiesen das es noch getauscht werden muß. Also noch einmal: Beispielsweise ein 2D-Array (also: Map(x,y)) liegt nach wie vor mehr oder weniger linear im RAM vor. Als physikalisch ist auch ein RAM in 2D aufgebaut. Aber das nützt nicht zu wissen, da man darüber selbst keine Kontrolle hat. Der Abruf über die Werte eines RAM erfolgt aber linear. Wenn nun BlitzBasic ein 2D-Array belegt, dann reserviert es einen Speicherbereich von X*Y*4 Bytes linear im RAM. Da aber alle modernen Prozessoren und Speicherkontroller so aufgebaut sind, dass sie ein einmal ausgelesenen Wert aus dem Speicher, automatisch davon ausgehen das der nächste Wert unmittelbar +4 Bytes sein müsste (Mit sehr viel% Wahrscheinlichkeit). So lesen sie bereist die nächsten Werte aus dem langsamen RAM in den viel schnelleren L2 bzw. L1 Chache. Wenn nun der Prozessor den nächsten Wert haben will, sagt der Speicherkontroller gleich ''schau hier, hab ich schon für dich vorbereitet'', und der Prozessor freud sich, weil dieser nicht ewige Tackzyklen darauf warten muß. Und logischer Weise ist ein 2D-Array so aufgebaut, dass es, wenn man von X und Y ausgeht, so die Daten ablegt, dass Zeilenweise die Werte aus dem Feld ausgelesen werden. Also würden X und dann Y -For/Next-Schleifen dem wiedersprechen, indem sie logischer Weise das ganze Spaltenweise auslesen. Da kommt als die Anfrage vom Prozessor nicht mit der Wahrscheinlichkeitsrechnung der RAM-Kontrollers überein. Das heisst im Klartext: Der Prozessor muß auf jeden Wert warten, weil der Kontroller immer die falschen Werte im L2 oder L2 -Chache abgelegt hat.
Um also den RAM trotz 2D-Array linear abzufragen, muß das Kontrukt nun so aussehen: Code: [AUSKLAPPEN] For y = 0 To YAnz
For x = 0 To XAnz Wert=Map(x,y) Next Next Y gibt den Startwert von 0 vor, dann kommt X komplett von 0 bis 19 (gleich 20 Speicherzellen zu je 4 Bytes). Dann erst springt Y ein Wert weiter. Der Zugriff auf dem RAM verläuft also intern in etwa so: Wert=PeekInt(Bank,(X+Y*DimX)*4 ) - - - Für scrollbare Maps sollte man sich für eines von zwei möglichen entscheiden: Die Map scrollt immer nur ganze Tiles weit. Das sieht zwar nicht so schön aus, ist aber sehr einfach zu programmieren. Selbst die Mausposition lässt sich nahezu 1:1 mit einem kleinen Teiler auf die Map übertragen. Die Map scrollt pixelgenau. So eine Map ist schon deutlich komplizierter zu berechnen. Auch die Mausposition darauf zu berechnen ist nicht sehr leicht. Gerade wenn man das noch nie gemacht hat, wird es problematisch. Bei der Draw3D zumindest kannst du auf die komplizierte Mausabfrage verzichten, und das alles über die Buttons machen. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich verstehe nicht, warum man bei Tilemaps auf lineares Auslesen achten sollte. Was du sagst, stimmst durchaus - wenn man das Array linear ausliest, wird der Prozess dank Caching natürlich schneller im Vergleich zum nicht-linearen Auslesen. Allerdings ist der Unterschied wirklich nur bei sehr grossen Datenmengen spürbar. Hier mal ein Beispiel BlitzBasic: [AUSKLAPPEN] Dim Array( 1000, 1000 ) Bei einem Array, das mehr als eine Million Elemente besitzt und bei dem alle Elemente abgearbeitet werden, habe ich hier beim Schreiben 1 Millisekunde Unterschied und beim Lesen 4 Millisekunden. Das macht natürlich einiges aus, wenn man sehr zeitkritischen Code hat, bei dem viel Daten abgearbeitet werden sollen (beispielsweise eine Funktion, die grosse Bilder in einem Array in Echtzeit bearbeiten soll). Bei einer Tilemap, bei der meistens gerade mal um die 500 Elemente bearbeitet werden, unbedingt auf einer linearen Abarbeitung zu bestehen und nicht-lineares Auslesen effektiv als 'offensichtlich falsch' zu bezeichnen, ist einfach nur unangebracht. Ironisch wird es, weil du ein paar Posts später für die Berechnung der Mausposition auf der Karte das Buttonfeature der Draw3D vorschlägst. Zuerst einmal müsste man die Buttonabfrage für jedes gezeichnete Tile ausführen (was ja das saubere Trennen von Input und Output verunmöglich) statt nur ein einziges Mal eine Koordinatenberechnung. Ausserdem ist diese Funktion meines Wissens nach für beliebige gezerrte und gedrehte Vierecke gedacht - eine Tilemap besteht aber aus quadratischen Tiles mit konstanter Kantenlänge. Mit der Funktion geht man sozusagen mit Kanonen auf Spatzen los und verschenkt freudig Rechenzeit, die man mit einer halben Stunde vor einem Blatt Papier, um die Mausberechnung hinzukriegen, sparen könnte ![]() Ich will dich keinesfalls persönlich angreifen, aber wenn du wirklich auf Optimierung bis ins Kleinste bestehst, tu es konsequent. Ansonsten lass einfach den Code, solange er funktioniert und nicht grade sehr grob Ressourcen verschwendet. Wenn man nicht besonders sattelfest im Programmieren ist, freut man sich einfach darüber, wenn der Code funktioniert und macht sich nicht gross Gedanken um die paar Hunderdstel an Millisekunden, die flöten gehen. |
||
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 |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group