Best way to manage multi-tile item on isometric map

Hi,

I’m using Qiso to manage an isometric map with items (buildings) covering one tile. Everything works fine.

Now I need to make some buildings cover sevral tiles (e.g. 2x3). I had a few thoughts but wanted to check if there was a better approach…

  1. In my sqlite3 database: I currently have X and Y coordinates for each building, those now become the origin of the building (e.g. top-left). I thought of adding two columns with xSize and ySize representing the number of tiles occupied (from origin) in the building properties.
  2. Avoiding collision when placing buildings on the map. I need to find a way to say “this tile is occupied”, that’s easily done when checking X and Y (origin) but what would be the best way to check if the tile is taken by a multi-tile building?
  3. Representation on the map: I guess I need a larger image which will cover several tiles. That should be straight forward.

Thanks

J@V0

Personally I’d just break the buildings up into multiple sprites, i.e. a building that covers a 2x2 tile would simply become 4 separate sprites. Subject to how you’re creating the graphics, this shouldn’t be difficult to produce. Remember that the engine will layer foreground tiles over the top of background tiles so any ugliness in the resulting chops should be hidden away anyway.

This way, all you need to do is script your building placement code to drop the appropriate sprites into each individual tile, and then your basic X,y check on the tiles you’re about to drop new sprites onto should return whether there’s already building there or not.

Good point, that seems like a good way to go. However, how can I connect 4 sprites to one building in my database? Today I have a building ID and ONE tileID but in that case I will need to have 4 tileIDs…

I’d do it by splitting the database into two tables. One to define a building with ID and X,Y placements on the map, and one to define building pieces with references back to the buildings ID and then X,Y positions relative to the buildings X,Y.

For example, a 2x1 size building one have two records in tblBuildingSprites, like so:

fldID 1, fldBuilding 1, fldX 1, fldY 1
FldID 2, fldBuilding 1, fldX 2, fldY 1

Then in the building table you might position that building somewhere in the middle of a map:

fldID 1, fldX 40, fldY 16

The result would be two sprites, positioned at 40,16 and 41,16. I.e. their buildings origin X + their own X, by their buildings origin Y + their own Y.

The origin doesn’t even need to be the top left corner, because you could have a sprite positioned at -1,-1 for example, and 40±1 would drop it into 39.

It’d also mean that your buildings can be of any size, any shape, and even consist of sprite pieces shared amongst other buildings.

Fantastic! Thanks a lot!

I’ve managed to implement this but there is still something fishy with the rendering.

As you stated, the engine should layer foreground tiles over the top of background tiles so any ugliness in the resulting chops should be hidden away but I have experienced a strange result. Adding a building (split into 8 sprites) on top of a background layer (grass) will not render properly the building. The building is added to layer “building”.

I’ve made an experiment without the grass and the building is rendered properly (see lower part on the snapshot).

Can you see what is wrong?

Hmm, that does look odd!

The way it’s showing the top half of each grass tile above the other images might be a clue. Qiso does some magic mask file autocreation when setting up the display as part of the character movement stuff, because characters need rendering between foreground and background layers appropriately while traversing between tiles. Those half sprites look to me like the result of some of this masking kicking in…

Is it at all possible that your map somehow has characters positioned over those tiles? I believe you originally tried to use the character system for the buildings, so I’m thinking some of this code might still be in play somewhere.

If this is indeed what’s happening, it’s likely that your sprites within Tiled still have their keep-above-characters, hide-tile-on-enter, or show-tile-on-enter properties set. A ctrl+f of the exported lua file for those properties should confirm.

I’m not using any or the character handling function in my code and my sprites are added to the building layer via the following command:

qiso.addToTile(tile.x, tile.y, buildingProperties.tileId, "building")

I’m attaching my map file if that helps. The problem is with the “airports3” tileset but the other tilesets have not been split into several tiles.

I don’t see any obvious issues with your map file. Seems my earlier thinking was wrong - there definitely aren’t any old properties hiding in here. Your layer orders look good too.

Looking again at the screenshot, I’m thinking now that it’s actually the way you’ve chopped those sprites up that’s the problem, in which case it’s likely I’ve just explained how this part works poorly!

In Tiled, layers are per-map so anything rendered within the second layer will overlay anything rendered in the first layer, i.e. Tiled is drawing everything in your ground layer from the top of the screen down, and then drawing everything in your buildings layer from the top of the screen down. So in Tiled, something rendered on the building layer in the middle of the screen will overlap something rendered on the ground layer just one tile below it. Is this making sense?

In Qiso though, layers are per-tile, not per-map. Like Tiled, Qiso starts at the top of the screen and works its way down, but it iterates every layer of the tile at the top, draws each sprite, then moves on to the next tile. The primary reason for this is so that you can have things like a tall building on one tile that overlaps the tiles further up the screen from it, but also have something like a grass with ‘sticky up bits’ overlapping the base of that building on the tiles directly after it. Notice how the sample grass tiles provided cover the bottom of the sample walls provided?

So, this in mind, it looks like your current sprite slices are horizontal. Slice them vertically instead and you should see better results.I.e. each sprite wants to be the width of the tile it’s on, but give them a canvas of say… 4x that size, so that the full height of the completed building shows. If you want to send me the original unsliced version of that white building I’ll slice it up for you to show what I mean - I feel like my explanation is making this sound more complicated than it actually is! Feel free to private message the file if you’d rather not post it publicly here.

Just wanted to add to this thread for anybody else who stumbles here looking for help with the same issue. Rémy has gotten this working now, using vertically sliced images as per my above post. My two paragraphs on the difference between how Tiled renders the layers and how Qiso renders them is the key.

Personally I’d just break the buildings up into multiple sprites, i.e. a building that covers a 2x2 tile would simply become 4 separate sprites. Subject to how you’re creating the graphics, this shouldn’t be difficult to produce. Remember that the engine will layer foreground tiles over the top of background tiles so any ugliness in the resulting chops should be hidden away anyway.

This way, all you need to do is script your building placement code to drop the appropriate sprites into each individual tile, and then your basic X,y check on the tiles you’re about to drop new sprites onto should return whether there’s already building there or not.

Good point, that seems like a good way to go. However, how can I connect 4 sprites to one building in my database? Today I have a building ID and ONE tileID but in that case I will need to have 4 tileIDs…

I’d do it by splitting the database into two tables. One to define a building with ID and X,Y placements on the map, and one to define building pieces with references back to the buildings ID and then X,Y positions relative to the buildings X,Y.

For example, a 2x1 size building one have two records in tblBuildingSprites, like so:

fldID 1, fldBuilding 1, fldX 1, fldY 1
FldID 2, fldBuilding 1, fldX 2, fldY 1

Then in the building table you might position that building somewhere in the middle of a map:

fldID 1, fldX 40, fldY 16

The result would be two sprites, positioned at 40,16 and 41,16. I.e. their buildings origin X + their own X, by their buildings origin Y + their own Y.

The origin doesn’t even need to be the top left corner, because you could have a sprite positioned at -1,-1 for example, and 40±1 would drop it into 39.

It’d also mean that your buildings can be of any size, any shape, and even consist of sprite pieces shared amongst other buildings.

Fantastic! Thanks a lot!

I’ve managed to implement this but there is still something fishy with the rendering.

As you stated, the engine should layer foreground tiles over the top of background tiles so any ugliness in the resulting chops should be hidden away but I have experienced a strange result. Adding a building (split into 8 sprites) on top of a background layer (grass) will not render properly the building. The building is added to layer “building”.

I’ve made an experiment without the grass and the building is rendered properly (see lower part on the snapshot).

Can you see what is wrong?

Hmm, that does look odd!

The way it’s showing the top half of each grass tile above the other images might be a clue. Qiso does some magic mask file autocreation when setting up the display as part of the character movement stuff, because characters need rendering between foreground and background layers appropriately while traversing between tiles. Those half sprites look to me like the result of some of this masking kicking in…

Is it at all possible that your map somehow has characters positioned over those tiles? I believe you originally tried to use the character system for the buildings, so I’m thinking some of this code might still be in play somewhere.

If this is indeed what’s happening, it’s likely that your sprites within Tiled still have their keep-above-characters, hide-tile-on-enter, or show-tile-on-enter properties set. A ctrl+f of the exported lua file for those properties should confirm.

I’m not using any or the character handling function in my code and my sprites are added to the building layer via the following command:

qiso.addToTile(tile.x, tile.y, buildingProperties.tileId, "building")

I’m attaching my map file if that helps. The problem is with the “airports3” tileset but the other tilesets have not been split into several tiles.

I don’t see any obvious issues with your map file. Seems my earlier thinking was wrong - there definitely aren’t any old properties hiding in here. Your layer orders look good too.

Looking again at the screenshot, I’m thinking now that it’s actually the way you’ve chopped those sprites up that’s the problem, in which case it’s likely I’ve just explained how this part works poorly!

In Tiled, layers are per-map so anything rendered within the second layer will overlay anything rendered in the first layer, i.e. Tiled is drawing everything in your ground layer from the top of the screen down, and then drawing everything in your buildings layer from the top of the screen down. So in Tiled, something rendered on the building layer in the middle of the screen will overlap something rendered on the ground layer just one tile below it. Is this making sense?

In Qiso though, layers are per-tile, not per-map. Like Tiled, Qiso starts at the top of the screen and works its way down, but it iterates every layer of the tile at the top, draws each sprite, then moves on to the next tile. The primary reason for this is so that you can have things like a tall building on one tile that overlaps the tiles further up the screen from it, but also have something like a grass with ‘sticky up bits’ overlapping the base of that building on the tiles directly after it. Notice how the sample grass tiles provided cover the bottom of the sample walls provided?

So, this in mind, it looks like your current sprite slices are horizontal. Slice them vertically instead and you should see better results.I.e. each sprite wants to be the width of the tile it’s on, but give them a canvas of say… 4x that size, so that the full height of the completed building shows. If you want to send me the original unsliced version of that white building I’ll slice it up for you to show what I mean - I feel like my explanation is making this sound more complicated than it actually is! Feel free to private message the file if you’d rather not post it publicly here.

Just wanted to add to this thread for anybody else who stumbles here looking for help with the same issue. Rémy has gotten this working now, using vertically sliced images as per my above post. My two paragraphs on the difference between how Tiled renders the layers and how Qiso renders them is the key.