Andrey Listopadov

Game2 W2/4

@gamedev lua tic80 ~3 minutes read

Didn’t have much progress on the Game2 this week. Mostly worked on some additional assets, and rendering the world into an isometric grid.

In the last post, I mentioned that it is very hard to come up with floor tiles that leave enough colors for things to be seen. I didn’t mention it in the previous post, but here are the original tiles I drew for the game to represent the floor and walls:

That’s right, I didn’t plan on using isometry originally. However, this looked blunt and there wasn’t enough space to add any decoration. I could, of course, bump the floor tile size to 4 tiles, but it started to look way too big. Isometry, however, looks decent in my opinion:

The only problem though is how do I draw this?

I created a sample level as a two-dimensional array and a simple projection function to project the world’s coordinates to screen coordinates:

local level = {
  {LW,RW,RW,RW,RW,RW,RW,RW,RW,RW},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, LW,F, F, F, F, F},
  {LW,F, F, F, RW,F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
  {LW,F, F, F, F, F, F, F, F, F},
}

local function isometric_project (x, y, w, h)
  return (x*8)+(y*-8), (x*4)+(y*4)
end

LW is Left Wall, RW is a right wall, and F is floor. All are objects with a single draw method, that knows how to draw the tiles.

I then drew this to the screen with a simple nested loop:

local function load_level (level)
  local ox,oy=x,y
  local offx,offy=120,8
  for y=1,#level do
    for x=1,#level[y] do
      local t=level[y][x]
      if "table" == type(t) then
        local mx,my=isometric_project(x-1,y-1)
        t.draw(mx+ox+offx,my+offy+oy)
      end
    end
  end
end

This gives me the correct result, albeit there’s no special code to draw this with composite tiles, so walls correctly intersect with ordinary tiles:

While this works, there’s a problem. As can be seen in the level array, there are only two kinds of walls - left and right ones. Ultimately, I want to bake this layout into the map, so I can just call map to render the whole level, and get camera culling as I did in the previous game. And it isn’t easy to see the problem with the isometric grid from the app where I drew these tiles, so let me bring a non-isometric grid in the engine:

There are some tiles that right now only take up half of a tile vertically, and some walls are drawn with two tiles and some with three tiles. This means, that I can’t just bake this on a tile-by-tile basis into the map with mset.

Here’s a closer look at the problem in case you didn’t see it:

I, however, only used the two-tiled walls in this picture (marked with a red grid), so because of that I can’t bake this into a map, as the tiles I used don’t match the map grid. Still thinking about how to approach this, as there’s also a second problem - entities should be able to stay behind the walls, so in reality I can’t bake this all to the map, probably only the floor tiles, and I will have to draw the walls separately. Or via a second map call. I mean, I can draw it just like I do now, but this nested for loop bothers me way too much. When I will add entities and have bigger levels I fear this will become really slow.

There are probably ways of doing this easied than what I try to do, but this is just how I roll.

Additionally, I drew even more items, and I decided that for every single-tile item I will draw a bigger one for the equipment menu:

Hopefully, I will figure out the isometry and have time to implement this.