Page 1 of 3

String2Tiles

Posted: Thu Nov 11, 2010 2:21 pm
by kikito
Using arrays for tile-based maps is kind of a pain.

Code: Select all

local tiles = {
  { ' ', ' ', ' ', ' ', ' ' },
  { ' ', ' ', ' ', ' ', ' ' },
  { '1', '*', '*', '*', '2' },
  { '*', ' ', ' ', ' ', '*' },
  { '*', ' ', '0', ' ', '*' },
  { '*', ' ', ' ', ' ', '*' },
  { '3', '*', '*', '*', '4' },
  { ' ', ' ', ' ', ' ', ' ' },
  { ' ', ' ', ' ', ' ', ' ' }
}
The problems I see:
  • There are way too many commas and quotes/apostrophes and {s and }s
  • x and y coordinates are switched: you have to choose between doing map[y][x] instead of map[x][y], or drawing the map 'sideways'
Strings, on the other hand, are easier to 'draw' (type):

Code: Select all

local str = [[
  1***2  
  *   *  
  * 0 *  
  *   *  
  3***4  
]]
... but they are a pain to use! - you can't easily do str[x][y] or similar. You have to rely on regular expressions and other nonsense.

Here's an attempt at taking the best from both worlds: string2Tiles.

Code: Select all

function string2Tiles(str)
  local tiles = {}

  local row_length = #(str:match("[^\n]+"))

  for x = 1,row_length,1 do
    tiles[x] = {}
  end

  local x,y = 1,1
  for row in str:gmatch("[^\n]+") do
    assert(#row == row_length, 'Map is not squared: length of row ' .. tostring(y) .. ' should be ' .. tostring(row_length) .. ', but it is ' .. tostring(#row))
    x = 1
    for tile in row:gmatch(".") do
      tiles[x][y] = tile
      x = x + 1
    end
    y=y+1
  end
  
  setmetatable(tiles, { __call = function(self, x,y) return self[x][y] end })

  return tiles
end
This function:
  • Accepts an easy-to-draw string
  • Transforms it onto a table. The table is 'flexed', so you can index it like this: table[x][y]
  • For more ease of use, it can also be indexed as a function: table(x,y)
Example:

Code: Select all

 -- prints the tiles on the console
local function printTiles(tiles)
  local buffer = {}
  for x,column in ipairs(tiles) do
    table.insert(buffer, "\n { '" .. table.concat(column, "', '") .. "' }")
  end
  print( '{' .. table.concat(buffer, ',\n') .. '\n}' )
end

local str = [[
  1***2 
  *   * 
  * 0 * 
  *   * 
  3***4 
]]

local tiles = string2Tiles(str)

print('string:')
print(str)

print('tiles:')
printTiles(tiles)

print('tiles[5][3]:', tiles[5][3])
print('tiles(5,3):', tiles(5,3))
And here's the output:

Code: Select all

string:
  1***2 
  *   * 
  * 0 * 
  *   * 
  3***4 

tiles:
{
{ ' ', ' ', ' ', ' ', ' ' },

{ ' ', ' ', ' ', ' ', ' ' },

{ '1', '*', '*', '*', '3' },

{ '*', ' ', ' ', ' ', '*' },

{ '*', ' ', '0', ' ', '*' },

{ '*', ' ', ' ', ' ', '*' },

{ '2', '*', '*', '*', '4' },

{ ' ', ' ', ' ', ' ', ' ' },

{ ' ', ' ', ' ', ' ', ' ' }
}
tiles[5][3]: 0
tiles(5,3): 0
]]
I hope this helps. Feel free to comment / add things.

Re: String2Tiles

Posted: Thu Nov 11, 2010 2:36 pm
by zac352
:o Awesome

Re: String2Tiles

Posted: Thu Nov 11, 2010 2:43 pm
by vrld
This looks mighty helpful.
Only two small additions:
For convenience the dimensions could be saved into the tiles table and the __call should check for bounds:

Code: Select all

function string2Tiles(str)
[...]
    tiles.widht = #tiles
    tiles.height = #tiles[1]

    setmetatable(tiles, { __call = function(self, x,y) 
        assert(x > 0 and x <= tiles.width, "Index x="..x.." out of bounds")
        assert(y > 0 and y <= tiles.height, "Index y="..y.." out of bounds")
        return self[x][y]
    end })
    return tiles
end

Re: String2Tiles

Posted: Thu Nov 11, 2010 3:42 pm
by kikito
vrld wrote:This looks mighty helpful.
Only two small additions:
For convenience the dimensions could be saved into the tiles table and the __call should check for bounds:

Code: Select all

function string2Tiles(str)
[...]
    tiles.widht = #tiles
    tiles.height = #tiles[1]

    setmetatable(tiles, { __call = function(self, x,y) 
        assert(x > 0 and x <= tiles.width, "Index x="..x.." out of bounds")
        assert(y > 0 and y <= tiles.height, "Index y="..y.." out of bounds")
        return self[x][y]
    end })
    return tiles
end
Mmm ... very good idea!

Re: String2Tiles

Posted: Thu Nov 18, 2010 12:51 pm
by arquivista
Oh, only now noticed this interesting post. That's was very good function idea that could help some people, Thx kikito and vrld
For the value of it you should add this to Snippets Wiki.

btw, just an suggestion, why you don't wrap it with a loading/save function to plain txt?

Re: String2Tiles

Posted: Thu Nov 18, 2010 12:55 pm
by kikito
arquivista wrote:btw, just an suggestion why you don't wrap it with a loading/save function to plain txt?
But... it is already plain text! Not sure of what you mean.

Regarding the wiki, my plan is creating a better tile tutorial. The 3 ones that are there are too confusing.

But I'll wait until 0.7 goes out.

Re: String2Tiles

Posted: Thu Nov 18, 2010 1:06 pm
by arquivista
kikito wrote: But... it is already plain text! Not sure of what you mean.

Regarding the wiki, my plan is creating a better tile tutorial. The 3 ones that are there are too confusing.

But I'll wait until 0.7 goes out.
You probably right. Just was thinking in instead of load a .lua file with

Code: Select all

local str = [[
  1***2  
  *   *  
  * 0 *  
  *   *  
  3***4  
]]
have imbued a straight/clean loading/saving function without the variable table name and "limits" markers.

Code: Select all

1***2  
 *   *  
 * 0 *  
 *   *  
 3***4
Thanx, I agree with that tiles tutorials were a bit confusing (at least when I started and didn't knew which to head on). BTW do you will apply "translate" on them? I haven't see till now examples with that.

Re: String2Tiles

Posted: Thu Nov 18, 2010 1:31 pm
by kikito
arquivista wrote:

Code: Select all

1***2  
 *   *  
 * 0 *  
 *   *  
 3***4
Oh. Well, I'm not sure about that. You see, normally when you load maps you want to load more stuff than just the tiles.

For example, enemy locations. Triggers. That kind of thing (explained better on this forum post). You would need a tiles.txt file for the tiles themselves, and a map.lua file pointing to that tiles.txt file. And this setup would probably confuse newbies.
arquivista wrote: Thanx, I agree with that tiles tutorials were a bit confusing (at least when I started and didn't knew which to head on). BTW do you will apply "translate" on them? I haven't see till now examples with that.
Yeah, for a tutorial translate is the thing to use. A more advanced solution would involve translate + drawing only the tiles that fit on the screen.

I'd probably separate it into two tutorials - Tilemap loading & drawing, and then scrolling.

Re: String2Tiles

Posted: Thu Nov 18, 2010 2:20 pm
by arquivista
kikito wrote: Oh. Well, I'm not sure about that. You see, normally when you load maps you want to load more stuff than just the tiles.

For example, enemy locations. Triggers. That kind of thing (explained better on this forum post). You would need a tiles.txt file for the tiles themselves, and a map.lua file pointing to that tiles.txt file. And this setup would probably confuse newbies.
Ah,ok, I aware of that complications and understand your reasons and dillemas. I just was trying to left things concise to a generic string2tiles table with map/one table only. I for example prefer to separate content types. Why? Cause of other "complications" when keeping all the data in same file because we will load things we don't want sometimes. For example that you have different "levels/dungeons" but the tile info is common to all dungeons so is not necessary load all that basic/common again and because is increasing file size too. Also things in that way must be so well organized that we dont suffer the risk of loading data that will erase like for example altered properties of a terrain/objects during gameplay. Is the fear and danger of reload/reset some unwanted data that was changed meanwhile.
kikito wrote:
Yeah, for a tutorial translate is the thing to use. A more advanced solution would involve translate + drawing only the tiles that fit on the screen.

I'd probably separate it into two tutorials - Tilemap loading & drawing, and then scrolling.
Thx, all of us will thank that! :)

Re: String2Tiles

Posted: Fri Nov 19, 2010 10:28 pm
by arquivista
kikito sorry to post this here because is a bit off-topic but is a doubt related with your string2Tiles. I know that this could seem so basic... ermm...
well, I was trying to quickly use your example program that use console and prints. I'm on mac and using console to see messages it's not friendly. There is a way of use "print" commands directly in app window without have to transform them all to love.graphics.print and have to put coordinates (instead of "flow" the text as in a console/terminal)?

thanks.