Page 1 of 2
Is this a good way to draw a grid based map?
Posted: Thu Jan 23, 2014 8:15 pm
by feelixe
Hello:) I have a game with gridbased map and I'm wondering if my technique of drawing the map is a decent way of doing it and i have a question if that's the case.
So. I have my grid map and i have coordinations(x,y,x2,y2) of the player + screenwidth + (a border). That kind of creates two rectangles. When you step outside the inner rectangle(player + screenwidth) it resets to the middle of the player.
I use the outer rectangle that i get above and draw the grid map within those coordinats to a canvas. I then draw the canvas.
So is this ok? Or is there a technique that's better for the performance.
If so : I wonder how i would handle map updates, say you change a tile, then i would have to refresh the canvas. Is that heavy work for the computer?
Thanks in advance
Re: Is this a good way to draw a grid based map?
Posted: Thu Jan 23, 2014 8:19 pm
by Jasoco
Grids in Lua:
Code: Select all
gridWidth = 50
gridHeight = 30
myGrid = {}
for x = 1, gridWidth do
myGrid[x] = {}
for y = 1, gridHeight do
myGrid[x][y] = {some table or other data, whatever you want each cell to contain}
end
end
Then in order to access a cell's contents, you'd just ask for myGrid[x][y].whatever or whatever.
That is how you make a grid. Nested tables.
Re: Is this a good way to draw a grid based map?
Posted: Thu Jan 23, 2014 8:26 pm
by feelixe
Jasoco wrote:Grids in Lua:
Code: Select all
gridWidth = 50
gridHeight = 30
myGrid = {}
for x = 1, gridWidth do
myGrid[x] = {}
for y = 1, gridHeight do
myGrid[x][y] = {some table or other data, whatever you want each cell to contain}
end
end
Then in order to access a cell's contents, you'd just ask for myGrid[x][y].whatever or whatever.
That is how you make a grid. Nested tables.
Yea, that's how I do it. But doesn't the game run slow if i go through the whole grid with a nested for-loop in the .draw function (and the map is bigger than just a few blocks)
Re: Is this a good way to draw a grid based map?
Posted: Thu Jan 23, 2014 8:51 pm
by micha
feelixe wrote:But doesn't the game run slow if i go through the whole grid with a nested for-loop in the .draw function (and the map is bigger than just a few blocks)
Yes, it will. For drawing a large number of tiles, use a
spritebatch.
As a rule of thumb, you should try to minimize the number of love.graphics.draw-calls. With a spritebatch you can draw the whole map by calling draw only once.
Edit: Have a look at the
tutorial section in the wiki. Fast drawing of maps is covered in
Efficient Tile-based scrolling.
Re: Is this a good way to draw a grid based map?
Posted: Thu Jan 23, 2014 8:52 pm
by Jasoco
You can use a camera system that figures out which tiles are on screen and only loop through those. It's slightly more complicated, but easy if you think about it.
Basically you'd take your camera X/Y divided by your tile size (Also taking any zoom factor into account) and figure out which tiles are on the screen, set the lower X/Y and upper X/Y and only draw/update within those bounds. (Make sure to math.floor any calculations)
Re: Is this a good way to draw a grid based map?
Posted: Fri Jan 24, 2014 6:40 am
by micha
Jasoco wrote:You can use a camera system that figures out which tiles are on screen and only loop through those.
I did it this way, too, some time ago. But then I wondered: Is checking the coordinates in Lua really faster than drawing a tile offscreen? I guess at least when all data is at the GPU, it will figure that the tile is offscreen and then not draw it.
Re: Is this a good way to draw a grid based map?
Posted: Fri Jan 24, 2014 1:55 pm
by kikito
micha wrote:Is checking the coordinates in Lua really faster than drawing a tile offscreen?
No, that's probably slower (it would depend on the complexity of drawing an individual cell though - imagine things like animated cells etc).
But that is not what Jasoko is talking about. He's talking about a map system is able to "draw the tiles that touch a rectangular zone, and ignore the rest".
When you have a 2-d tilemap, this is very easy to do. Here's how you draw all the cells in the map:
Code: Select all
function drawMap(map)
for x=1, #map.columns do
for y=1, #map.columns[x] do
drawTile(map, x,y)
end
end
end
And here's how you draw just a
rectangular zone of that map (in this case specified by the coordinates left, right, top, bottom):
Code: Select all
function drawMapRectangularZone(map, left, right, top, bottom)
for x=left, right do
for y=top, bottom do
drawTile(map, x,y)
end
end
end
Notice how the cells outside of the designated rectangular zone are literally ignored; there's not even an "if" for them.
The screen is an axis-aligned rectangle. (Even when it's "rotated and zoomed out" over your map, it's can still be conscripted to an axis-aligned rectangle using its max & min x & y coords). If you use that rectangle with drawMapRectangularZone, that's
way faster than drawing the whole map and leaving the card deal with the off-screen things.
If you are interested in seeing this in action, the
gamera demo uses this technique (only the rectangles that "touch the screen" - well, the camera's "visible rectangle" are drawn). Here's the relevant function:
https://github.com/kikito/gamera/blob/demo/main.lua#L19
Re: Is this a good way to draw a grid based map?
Posted: Fri Jan 24, 2014 2:25 pm
by micha
This is indeed a neat trick.
Now I am wondering, could I benefit from this trick, if I draw my map with a spriteBatch? I could empty the batch each frame and refill it, using only the visible tiles. That takes time, too. So that must depend on the size ratio of the whole map to the visible part.
Re: Is this a good way to draw a grid based map?
Posted: Fri Jan 24, 2014 3:26 pm
by bartbes
If you clear and refill your spritebatch for every draw call, you're probably losing any gains from it.
Re: Is this a good way to draw a grid based map?
Posted: Fri Jan 24, 2014 9:42 pm
by davisdude
Just a question about the following code.
kikito wrote:Code: Select all
function drawMapRectangularZone(map, left, right, top, bottom)
for x=left, right do
for y=top, bottom do
drawTile(map, x,y)
end
end
end
Say for instance, you have non-tile-based-movement. How then would it be implemented? I guess you would check if the screen is covering the tile at all, then draw it, right? But then that would require you to loop through the tables, wouldn't it?