TileMap mit Draw3D

Übersicht BlitzBasic Beginners-Corner

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

M0rgenstern

Betreff: TileMap mit Draw3D

BeitragMo, Jan 18, 2010 20:14
Antworten mit Zitat
Benutzer-Profile anzeigen
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:

user posted image

Lg, M0rgenstern

Nicdel

BeitragMo, Jan 18, 2010 20:16
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 20:25
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 21:03
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 21:26
Antworten mit Zitat
Benutzer-Profile anzeigen
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.... Wink

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

BeitragMo, Jan 18, 2010 21:41
Antworten mit Zitat
Benutzer-Profile anzeigen
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

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Jan 18, 2010 21:51
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 22:11
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 22:20
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 18, 2010 22:34
Antworten mit Zitat
Benutzer-Profile anzeigen
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)

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Jan 18, 2010 23:05
Antworten mit Zitat
Benutzer-Profile anzeigen
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. Wink

- - -

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

BeitragFr, Jan 22, 2010 22:56
Antworten mit Zitat
Benutzer-Profile anzeigen
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

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, Jan 23, 2010 0:26
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jan 23, 2010 15:02
Antworten mit Zitat
Benutzer-Profile anzeigen
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

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, Jan 23, 2010 15:34
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jan 23, 2010 18:14
Antworten mit Zitat
Benutzer-Profile anzeigen
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

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, Jan 23, 2010 20:57
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Jan 24, 2010 18:52
Antworten mit Zitat
Benutzer-Profile anzeigen
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.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSo, Jan 24, 2010 22:21
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jan 25, 2010 0:54
Antworten mit Zitat
Benutzer-Profile anzeigen
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 )

Local Counter1 = MilliSecs()
For X = 0 To 1000
For Y = 0 To 1000
Array( X, Y ) = Rand( 0, 100 )
Next
Next
Counter1 = MilliSecs() - Counter1

Local Counter2 = MilliSecs()
For Y = 0 To 1000
For X = 0 To 1000
Array( X, Y ) = Rand( 0, 100 )
Next
Next
Counter2 = MilliSecs() - Counter2


Local Counter3 = MilliSecs()
For X = 0 To 1000
For Y = 0 To 1000
Local Temp = Array( X, Y )
Next
Next
Counter3 = MilliSecs() - Counter3

Local Counter4 = MilliSecs()
For Y = 0 To 1000
For X = 0 To 1000
Temp = Array( X, Y )
Next
Next
Counter4 = MilliSecs() - Counter4

Print "Nonlineares Auslesen: Schreiben " + Counter1 + "ms, lesen " + Counter3 + "ms"
Print "Lineares Auslesen: Schreiben " + Counter2 + "ms, lesen " + Counter4 + "ms"
WaitKey()
End

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 Wink

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

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group