Tile_maps unter Draw3D richtig umgesetzt ?

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Dottakopf

Betreff: Tile_maps unter Draw3D richtig umgesetzt ?

BeitragMi, Sep 09, 2009 12:55
Antworten mit Zitat
Benutzer-Profile anzeigen
HI Blitzer!


In meinem Post habe ich eher ein Anliegen, als eine technische Frage.
Ich bin seit kurzem Draw3D einsteiger und möchte die mitgebrachte 3D Power von Draw3D in meinem 2D RPG nutzen. Da Draw3D den Koordinatenursprung in der Mitte hat und nicht links oben habe ich mir eine Funktion geschrieben die die 3D koordinaten auf "links-oben" umrechnet, damit ich mit meiner Tile Map bzw. Arrys keine Probleme bekomme. ( Beispiel: negative pixel position umgerechnet auf negative tile position, und abgefragt in einem arry = MAV.)

Die Funktion ist eigentlich total simel. Ich füttere die Funktion mit meinen "gedachten alten 2D positionen ursprung links oben" und diese Funktion spuckt dann die umgerechnete "reale" Draw3D Position aus.

Das ganze funktioniert auch recht wunderbar, aber ich wollte euch einfach mal Fragen, ob ich Tile maps total falsch oder viel zu umständlich unter Draw3D realisiere.. Vielleicht gibts ja einen viel simpleren /schnelleren weg das zu machen.

Naja wäre toll wenn Ihr mal einen Blick drauf werfen könntet: (evt. auch eure FPS zahlen und co.)

Hier die Funktion die die Umrechnung macht
Code: [AUSKLAPPEN]

;errechnet die verschiebung vom mittleren koordinatenursprung in die linke ecke oben bzw. zurück
;mode gibt an was genau umgewandelt werden soll
;mode = 1   x tile koordinate wird in 3D pixelkoordinate umgewandelt
;mode = 2   y tile Koordinate wird in 3D Pixelkoordinate umgewandelt
;mode = 3   3D Pixelkoordinate(x) in x tile koordinate umwandeln
;mode = 4   3D Pixelkoordinate(y) in y tile koordinate umwandeln
Function new2Dpos(pos%,size%,mode%)
Select mode
      Case 1
         Return ((pos%*size-SCREEN_WIDTH/2)+size/2);x tile Posi to 3DPixel
      Case 2
         Return ((pos%*size+SCREEN_HEIGHT/2)-size/2);y tile Posi to 3DPixel Posi
      Case 3
          Return (SCREEN_WIDTH/2)/size + Floor(pos/Float(size));3DPixel Posi to x tile Posi
      Case 4
          Return (SCREEN_HEIGHT/2)/size - Ceil(pos/Float(size));3DPixel Posi to y tile posi
   End Select
End Function


ist eigentlich recht simpel in der hand habung, möchte ich z.B. meine Mausposition in eine Tileposition umwandeln muss ich nur schreiben.
Code: [AUSKLAPPEN]

tile_x =   new2Dpos( mousex3D , tile_size , 1 )
tile_y =   new2Dpos( mousey3D , tile_size , 2 )




Um die Funktion richtig testen zu können, habe ich einen mini Map Editor geschrieben.
Das ganze gibts auch hier gezippt.
https://www.blitzforum.de/upload/file.php?id=6754 (ca 680 KB)


Und hier nur der Source: (leider unschöne umbrüche)
Code: [AUSKLAPPEN]

;Geschrieben in IDIAL
Graphics3D 1024,768,0,2
SetBuffer BackBuffer()

Local Timer=CreateTimer(60)
Local Camera=CreateCamera()
CameraClsColor Camera,64,64,64

Include "Includes\Draw3D2.bb"
DrawInit3D(Camera)
Origin3D(1024,768)

;--------------------------------------------------------------- Const -------------------------------------------------------------------
Const SCREEN_WIDTH% = 1024
Const SCREEN_HEIGHT%= 768

;--------------------------------------------------------------- Locals ------------------------------------------------------------------
Local TILECOUNT_X%=2;tiles im tile_set
Local TILECOUNT_Y%=2

;--------------------------------------------------------------- Globals -----------------------------------------------------------------
Global TILE_SIZE%=32
Global CURRENT_TILE%=1


;---------------------------------------------------------------  ARRY --------------------------------------------------------------------
Dim tile_map(50,50)

;karte aus data feld laden
Restore mapdata
For y = 0 To 17
   For x = 0 To 17
      Read tile_map(x,y)
   Next
Next



;---------------------------------------------------------------- Grafik ------------------------------------------------------------------
Global TILE_SET=LoadImage3D("gfx\tile_set.bmp",1,1,0);tiles aus tile_set lesen/schneiden
For y = 0 To TILECOUNT_Y-1
   For x = 0 To TILECOUNT_X-1
      GrabImage3d(TILE_SET,x*32,y*32,32,32)
   Next
Next






;///////////////////////////////////////////////////////////////  MAIN LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Repeat
Cls



            draw_map()
            set_tiles()





WaitTimer(Timer)
RenderWorld
Clear3D()


   show_infos()

   ;fps ermitteln.....
   loops = loops+1
   If MilliSecs() - fpstime > 1000 Then
      fpsrate = loops
      loops = 0
      fpstime = MilliSecs()
   End If
   ;..................
   
Text 0,0,"fps "+fpsrate
Flip 0
Until KeyHit(1)
;//////////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




;zeichnet alles
Function draw_map()

               ;zeichnet die karte
               For x = 0 To 17
                  For y = 0 To 17
                     If tile_map(x,y)<>0 Then DrawImage3d(TILE_SET,new2Dpos(x,TILE_SIZE,1) ,new2Dpos(-y,TILE_SIZE,2) ,0,0,1,tile_map(x,y))
                  Next
               Next
      
      
      
      
               plot3d(TILE_SET,0,0,2);markiert nur punkt 0 0 (kleiner fixpunkt)

End Function



;errechnet die verschiebung vom mittleren koordinatenursprung in die linke ecke oben bzw. zurück
;mode gibt an was genau umgewandelt werden soll
;mode = 1   x tile koordinate wird in 3D pixelkoordinate umgewandelt
;mode = 2   y tile Koordinate wird in 3D Pixelkoordinate umgewandelt
;mode = 3   3D Pixelkoordinate(x) in x tile koordinate umwandeln
;mode = 4   3D Pixelkoordinate(y) in y tile koordinate umwandeln
Function new2Dpos(pos%,size%,mode%)
Select mode
      Case 1
         Return ((pos%*size-SCREEN_WIDTH/2)+size/2);x tile Posi to 3DPixel
      Case 2
         Return ((pos%*size+SCREEN_HEIGHT/2)-size/2);y tile Posi to 3DPixel Posi
      Case 3
          Return (SCREEN_WIDTH/2)/size + Floor(pos/Float(size));3DPixel Posi to x tile Posi
      Case 4
          Return (SCREEN_HEIGHT/2)/size - Ceil(pos/Float(size));3DPixel Posi to y tile posi
   End Select
End Function


;simples tile setzen
Function set_tiles()
      If MouseHit(2) Then CURRENT_TILE = CURRENT_TILE+1
      If CURRENT_TILE>4 Then CURRENT_TILE=1
      If MouseDown(1) Then tile_map(new2Dpos(mousex3d,TILE_SIZE,3), new2Dpos(mousey3d,TILE_SIZE,4)) = CURRENT_TILE
End Function



;zeigt die werte die die funktion zurück gibt
Function show_infos()
   Text 600,0,"Linke Maus um Tiles zu setzen"
   Text 600,15,"rechte Maus um das aktuelle Tille zu wechseln"
   Text 600,45,"maus tile_x position " + new2Dpos(mousex3d,TILE_SIZE,3)
   Text 600,60,"maus tile_y postion  " + new2Dpos(mousey3d,TILE_SIZE,4)
   Text 600,75,"----------------------------------"
   Text 600,90,"maus reale tile position x" + mousex3d/32
   Text 600,105,"maus reale tile position y" + mousey3d/32
End Function








.mapdata;18x18
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1


;~IDEal Editor Parameters:
;~F#58#70#7F#88
;~C#Blitz3D




Eure Meinung dazu oder Tipps wäre mir echt wichtig, da ich jetzt darauf meinen ganzes RPG stützen möchte.
Danke für eure Hilfe!!


Gruß
Dottakopf
Rechtschreibfehler gelten der allgemeinen Belustigung!

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMi, Sep 09, 2009 14:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast doch die Draw3Dz.bb von mir bekommen. Diese hat einen Koordinatenursprung links/oben wie von dir gewünscht. Du solltest allerdings nur noch in dieser DRAWOFFSET auf ''0'' stellen. Sonst hast du eine unscharfe Ausgabe der einzelnen Tiles.

Die DrawSGG liesse sich auch mir relativ wenigen Handgriffen kompatiebel zu der Draw3Dz.bb machen.

Edit1: Wenn man vom Editor absieht, kannst du auch eine Map einzeichnen und dann das Surface über ClearOff3D aus der ''Löschliste'' entfernen. Somit bleibt es in der Welt bestehen und man kann dann innerhalb der Map sich mit der Umpositionierung der Kamera bewegen. Man muß nur darauf achten, dass man das WorldPivot beim leden der Tiles einstellt und die Anzahl Tiles pro geladener Textur im Idelfall um etwa 32x32 betragen. Dafür spart man sich das einzeichnen der Tiles per Laufzeit im Programm.

Edit2: Ich hab mir jetzt mal dein Code genauer angesehen und feststellen müssen, dass einige das ''Problem'' mit dem Koordinatenursprung irgendwie sehr schwer nehmem. Im Grunde ist es ganz einfach, man benötigt nichts anderes als nur bei der Darstellung ein X/Y-Offset. Der Rest bleibt im Grunde gleich. Um nun noch über einen Editor ein Tile aus einem Array auswählen zu können, kann man auf die Draw3D-Button-Funktion zurück greifen. Diese ist nicht nur sehr schnell (habe ich mit einer Riesenmap getestet), sondern auch sehr präzise (habe ich ebenfall durch ewig viele Tests durchzogen). Der ganze Code reduziert sich fast auf die Hälfte und ist zudem einfach zu verstehen/verändern. Mit der Draw3D2 arbeitest, dann kannst du zudem auch auf die nervige Grab-Schleife verzichten und dir das automaisch durch GrabAnimImage3D erledigen lassen.

Code: [AUSKLAPPEN]
Const SCREENWIDTH%=1024
Const SCREENHEIGHT%=768

Graphics3D SCREENWIDTH,SCREENHEIGHT,0,2
SetBuffer BackBuffer()

Local Timer=CreateTimer(60)
Local Camera=CreateCamera()
CameraClsColor Camera,64,64,64

Include "Includes\Draw3D2.bb"
DrawInit3D(Camera)
Origin3D(1024,768)

Const TILESIZE%=32

Const MAPSIZE%=17
Const XOFFSET%=TILESIZE/2-512
Const YOFFSET%=TILESIZE/2-192

Dim TileMap(MAPSIZE,MAPSIZE)

Global CurrentTile%=0
Local X,Y

Restore MapData
For Y=0 To MAPSIZE
   For X=0 To MAPSIZE
      Read TileMap(X,Y)
   Next
Next

Local TileSetMain=LoadImage3D("gfx\tile_set.png",1,1,0)
Global TileSet=GrabAnimImage3D(TileSetMain,TILESIZE,TILESIZE,0,4,1,1)




Repeat
   ;Kein CLS bei 3D-Programmen notwendig!!
   
   If MouseHit(2) Then CurrentTile=(CurrentTile+1) Mod 4
   
   Draw_Map()
   
   WaitTimer(Timer)
   RenderWorld
   Clear3D()
   Flip 0
Until KeyHit(1)




Function Draw_Map()
   
   Local X,Y
   
   For X=0 To MAPSIZE
      For Y=0 To MAPSIZE
         DrawImage3D(TileSet,XOFFSET+X*TILESIZE,YOFFSET+Y*TILESIZE,1,0,1,TileMap(X,Y))
         If MouseDown3D=1 Then TileMap(X,Y)=CurrentTile
      Next
   Next
   
End Function




.MapData
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1


Ich hab mir erlaubt ein paar Variablennamen zu ändern. Irgendwie hat mich die zum Teil ewige GROßSCHREIBWEISE bei NICHT Konstanten verwirrt, worauf ich dann losging und alles umbenannte und dabei auch ein ''_'' in diesen gelöscht.

Die Map sieht nun so aus, dass das erste Tile einer Tilemap ein komplett transparentes sein sollte. Daher erstellst du dir am besten eine neue Tilemap gespeichert als PNG.

Dottakopf

BeitragMi, Sep 09, 2009 19:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Hectic für deine Hilfe! Finde ich Großartig das du mir mit so viel geduld weiterhilftst.

Auf die wirklich einfache Lösung mit dem Offset hätte ich wirklich selber kommen können und warum ich die Globals auf Großgeschrieben habe weis ich nicht, das habe ich noch nie gemacht gehabt.

Das mit dem Surface klingt super interesannt, das wäre ja eine hammer speed optimierung!
Leider bin ich da in diesem Gebiet absolut nicht fit, ich weis leider noch nicht einmal genau was ein surface ist(stelle mir dieses als ein einzelnes für sich geschlossenes objekt vor) Embarassed (google ergebnisse sind lustig.. surface piercings Laughing ). Auch wüsste ich nicht wie man einen "worldPivot" setzt und verwaltet, auch wenn ich weis was ein Pivot ist.

Des weiterem stelle ich mir die Frage ob es dann noch möglich ist in dieses Surface etwas in die einzelnen Layer zu zeichnen. (z.B. ein soldat der unter einer hängebrücke steht/bewegt).

Auch verwirrt mich der Zugriff über die Button Funktion auf ein Tile in der Tilemap. Ich habe mir die mitgelieferten Beispiele zur Gui angesehen(Menu.bb). Scheinbar beziehen sich die Befehle ( MousePit3D , MouseOver3D , Mousehit3d) immer auf das zuletzt erstelle Element. Das ist aber nur sinnvoll wenn ich weis was das letze element war, und dass ist bei meiner Tilemap doch unbekannt?(vorallem bei x Layern).


Meinen Zugriff auf einzelne tiles im Tileset erhalte ich ,wie üblich, durch diese codezeile:
Code: [AUSKLAPPEN]

If MouseDown(1) Then TileMap(mousex3d/32-XOFFSET/32+1,mousey3d/32-YOFFSET/32+1) = Current_tile


Also danke nocheinmal für deine Hilfe! Wenn das mit dem surface inclusive layer usw. funtzen würde wäre das einfach geil.

Gruß
Dottakopf
Rechtschreibfehler gelten der allgemeinen Belustigung!

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMi, Sep 09, 2009 20:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Da du anscheinend mit IDEal arbeitest, werden dir die Parameter einer jeden Funktion auf der Statuszeile angezeigt. Das Worldpivot ist der vorletzte Parameter von LoadImage3D in der Draw3D2. Da kann man statt ''0'' auch ein Bezugsentity angeben. In den meisten Fällen wäre es dann ein freistehendes Pivot im 3D-Raum. Dann kann man mit der Kamera um das Teil rumfliegen und bewegt sich also nicht mehr als HUD-Element mit der Kamera mit.

Da du nun jedem Surface (das ist unter Blitz3D mindestens jede geladene Textur) ein eigenes ''Order'' vergeben kannst, kannst du auch die Zeichenreihenfolge auch so wählen, dass jede Ebene sich unterschiedlich verhält. Also auch dann, wenn immer neu eingezeichnete Objekte (z.B. Spieler) sich unter bestimmte Sachen aufhalten sollen. Beachte aber, dass eine große Tilemap welche über mehrere Surfaces festgesetzt wird (mit ClearOff3D) dann auch viel Grafikspeicher verschlucken. Es lohnt sich also nur in bestimmten Fällen. Wenn du dir da unsicher bist, dann macht die Tilemap wie gewohnt, ist kein Problem. Wirklich.

Mit den Buttons beim Tile-Editor habe ich nun in deinem Code es so gemacht, dass jedes Tile ein Button ist. Wenn nun mit der Maus da drückend drüber gefahren wird, werden die entsprechenden Tiles geändert. Das umrechnen kann man sich hierbei sparen, da die Arrayposition ja bereits vorliegt, da eben das selbe Tile ja gerade gezeichnet wurde. Mit einem Geschwindigkeitstest habe ich ein Versuch gemacht und festgestellt, das der rechen-Mehraufwand sehr gering ist. Von daher sehe ich da kein Problem jedes Tile in einem Editor als Button zu deklarieren, damit man sich ein eigenes Umrechnen mit den Offsets spart.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Dottakopf

BeitragMi, Sep 09, 2009 21:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Ah danke jetzt leuchtet mir so einiges ein. Sehr aufschlussreiches Posting!

Nochmal danke für deine Mühe!

Gruß
Dottakopf
Rechtschreibfehler gelten der allgemeinen Belustigung!

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group