Tilemap find by index

Advanced game related topics
OgreVorbis
User
User
Posts: 14
Joined: Thu Jan 16, 2020 10:47 pm

Tilemap find by index

Post by OgreVorbis »

So this is a relatively common question, but with all my searching, none of the answers sufficed. It's :oops: to admit that I can't figure this out. It seems simple.

So I have a tilemap png file. Its tiles are 32x32 and has 8 columns and 133 rows. I have the index number of each tile (the index starts at upper left and goes across and down - like expected). I need to turn that index number into the coords (x, y). I'm using ClipSprite. The vars are obvious and they are words.

Code: Select all

ClipSprite(0, (Mod(TileNumber, TileMapWidth / 32) * 32) - 32, [no idea what], #TileWidth, #TileHeight)
That's probably not even close to correct. I was at it for long enough that my brain started to frost over and I couldn't think anymore.
User avatar
Mijikai
Addict
Addict
Posts: 1027
Joined: Sun Sep 11, 2016 2:17 pm

Re: Tilemap find by index

Post by Mijikai »

Give this a try

Code: Select all

Procedure.i ClipTile(Tile,Index.i,TileMapWidth.i)
  Protected x.i
  Protected y.i
  y = Index / TileMapWidth
  x = Index - (y * TileMapWidth)
  ProcedureReturn ClipSprite(Tile,x << 5,y << 5,32,32)
EndProcedure
OgreVorbis
User
User
Posts: 14
Joined: Thu Jan 16, 2020 10:47 pm

Re: Tilemap find by index

Post by OgreVorbis »

Mijikai wrote: Wed Aug 18, 2021 1:19 pm Give this a try
First off, x is always zero. Why are you doing that second operation?
I'm not sure how you arrived at that. It doesn't work.
User avatar
NicTheQuick
Addict
Addict
Posts: 817
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Tilemap find by index

Post by NicTheQuick »

It goes like this:

Code: Select all

#TileWidth = 32

Procedure.i ClipTile(Tile, Index.i, TileMapWidth.i)
	Protected x.i
	Protected y.i
	x = (Index % (TileMapWidth / #TileWidth)) * #TileWidth
	y = (Index / (TileMapWidth / #TileWidth)) * #TileWidth
	Debug "(" + x + ", " + y + ")"
EndProcedure

For i = 0 To 10
	ClipTile(0, i, 256)
Next
Of course you can optimize it a bit if you like.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
chi
Addict
Addict
Posts: 861
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Tilemap find by index

Post by chi »

My two cents

Code: Select all

CompilerIf #PB_Compiler_Debugger = 0
  MessageRequester("", "Enable the debugger...")
CompilerEndIf

Procedure ClipTile(index, tc=8, tw=32, th=32)
  Static tmp.RECT
  tmp\left   = tw * ((index - 1) % tc)
  tmp\top    = th * Round((index - 1) / tc, #PB_Round_Down)
  tmp\right  = tw
  tmp\bottom = th
  ProcedureReturn tmp
EndProcedure

tiles      = 69

columns    = 8
tileWidth  = 32
tileHeight = 32

CreateImage(0, tileWidth * columns, tileHeight * Round(tiles / columns, #PB_Round_Up))
StartDrawing(ImageOutput(0))
  For i=1 To tiles
    *tile.RECT = ClipTile(i, columns, tileWidth, tileHeight)
    Box(*tile\left, *tile\top, *tile\right, *tile\bottom, RGB(Random(255), Random(255), Random(255)))
  Next
StopDrawing()

ShowLibraryViewer("Image", 0)
CallDebugger
Et cetera is my worst enemy
User avatar
Mijikai
Addict
Addict
Posts: 1027
Joined: Sun Sep 11, 2016 2:17 pm

Re: Tilemap find by index

Post by Mijikai »

OgreVorbis wrote: Thu Aug 19, 2021 7:29 am
Mijikai wrote: Wed Aug 18, 2021 1:19 pm Give this a try
First off, x is always zero. Why are you doing that second operation?
I'm not sure how you arrived at that. It doesn't work.
The second operation is multiplying by 32 (TileSize) by shifting its faster than normal multiplication.

The code works here is an example:

Code: Select all

EnableExplicit

Procedure.i ClipTile(Tile,Index.i,TileSize.i,TileMapWidth.i,*X.Integer,*Y.Integer)
  Protected x.i
  Protected y.i
  y = Index / TileMapWidth
  x = Index - (y * TileMapWidth) 
  *X\i = x * TileSize
  *Y\i = y * TileSize
  ProcedureReturn ClipSprite(Tile,*X\i,*Y\i,TileSize,TileSize)
EndProcedure

Procedure.i Sprite(Index.i,Color.i)
  Protected x.i
  Protected y.i
  If CreateSprite(Index,133 * 8,8 * 8)
    If StartDrawing(SpriteOutput(Index))
      DrawingMode(#PB_2DDrawing_Outlined)
      For y = 0 To 7
        For x = 0 To 132
          Box(x * 8,y * 8,8,8,Color)
        Next
      Next
      StopDrawing()
      ProcedureReturn #True  
    EndIf
    FreeSprite(Index)
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.i Main(Index.i)
  Protected exit.i
  Protected x.i
  Protected y.i
  If InitSprite()
    If OpenWindow(0,0,0,1920,1080,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
      If OpenWindowedScreen(WindowID(0),0,0,1920,1080)
        SetFrameRate(60)
        Sprite(0,$FFFFFF)
        Sprite(1,$222222)
        Repeat
          Repeat
            Select WindowEvent()
              Case #PB_Event_CloseWindow
                exit = #True
              Case #Null
                Break
            EndSelect
          ForEver
          ClearScreen($0)
          DisplaySprite(1,120,200)
          ClipTile(0,Index,8,133,@x,@y)
          DisplaySprite(0,120 + x,200 + y)
          StartDrawing(ScreenOutput())
          DrawText(200,420,"Tile Index: " + Str(Index))
          DrawText(200,440,"Tile Offset: " + Str(x) + " x " + Str(y))
          DrawingMode(#PB_2DDrawing_Outlined)
          Box(120,200,133 * 8,8 * 8)
          LineXY(120 + x + 4,100,120 + x + 4,400)
          LineXY(10,200 + y + 4,1600,200 + y + 4)
          StopDrawing()
          FlipBuffers()
        Until exit
      EndIf
      CloseWindow(0)  
    EndIf  
  EndIf
  ProcedureReturn #Null
EndProcedure

Main(500)

End
OgreVorbis
User
User
Posts: 14
Joined: Thu Jan 16, 2020 10:47 pm

Re: Tilemap find by index

Post by OgreVorbis »

NicTheQuick wrote: Thu Aug 19, 2021 10:01 am It goes like this:

Code: Select all

#TileWidth = 32

Procedure.i ClipTile(Tile, Index.i, TileMapWidth.i)
	Protected x.i
	Protected y.i
	x = (Index % (TileMapWidth / #TileWidth)) * #TileWidth
	y = (Index / (TileMapWidth / #TileWidth)) * #TileWidth
	Debug "(" + x + ", " + y + ")"
EndProcedure

For i = 0 To 10
	ClipTile(0, i, 256)
Next
Of course you can optimize it a bit if you like.
That works perfectly. Thank you. BTW I didn't know you could use % in PB, I thought it was Mod().
In terms of optimize, do you mean like a lookup table? That way it doesn't have to run the calculation on every loop.

As a side note. I think I'm going to GrabSprite after the first draw and render the background tiles as one sprite. I'd assume greater speed. Then only the upper layers will draw separate tiles.
OgreVorbis
User
User
Posts: 14
Joined: Thu Jan 16, 2020 10:47 pm

Re: Tilemap find by index

Post by OgreVorbis »

Mijikai wrote: Thu Aug 19, 2021 12:19 pm
The second operation is multiplying by 32 (TileSize) by shifting its faster than normal multiplication.
No, not that operation. The X =
You get 0 every time for X.
User avatar
J. Baker
Addict
Addict
Posts: 2124
Joined: Sun Apr 27, 2003 8:12 am
Location: USA
Contact:

Re: Tilemap find by index

Post by J. Baker »

www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef

Mac: 10.13.6 / 1.4GHz Core 2 Duo / 2GB DDR3 / Nvidia 320M
PC: Win 7 / AMD 64 4000+ / 3GB DDR / Nvidia 720GT


Even the vine knows it surroundings but the man with eyes does not.
Post Reply