3
\$\begingroup\$

I have a separate list of moveable entities, and then the regular 3D map, represented by a 2D array of stacks of tiles. My problem is that right now, I'm rendering my moveable entities after the map, and so they end up in the right place, but rendering over everything. If I were to render my entity list at the right place, however, in the map rendering process, it would be very slow because I'd have to iterate over the moveable entity list to find one with the correct (x, y) coordinates each tile that's rendered. Here's what my world looks like: enter image description here

Here is a screenshot of a particularly awkward example of this issue. The colonists are positioned (or seem to be) on the right tiles, but they draw in front of trees and hills they are actually behind.

enter image description here

Here's my current moveable entity drawing code:

enter image description here

Apologies for using a screenshot, but I can't paste into this text box for some reason. Anyway, my map drawing code is just a nested for loop over the map, pretty much. How do I merge these two? My drawing library doesn't have a Z-axis function.

\$\endgroup\$
2
\$\begingroup\$

You need a container to hold a reference to each object in the current tile/block.

If your map is made of tiles

Each tile has a height (as in games like Roller Coaster Tycoon or Transport Tycoon). You have a container for each position (x, y) of the map. When an object moves, it is removed from the container at (x, y) and added to the container at (x', y'). The container must be sorted by the altitude which the object is at.

Then, you iterate the tiles. For each tile, render the tile first, then the objects referenced in the container, starting from the object with lower altitude to the object with higher altitude. This is the reason you need to sort the container by the altitude the object is at.

OpenRTC2 uses similar approach, but optimized to use a compact pool for the references of objects.

If your map is made of blocks

Blocks don't have an height, at least not like in Roller Coaster Tycoon or Transport Tycoon, but they are like blocks in Minecraft. The map can have "holes" in it, in this case.

The approach is similar, but there's a container for each block. That is, there's a container for each position (x, y, z) of the map. In most cases, if the object is at (x, y, z), it means there's no block there to render. That is, you will render only a block or only objects for the position (x, y, z). Some cases are special. I see there are some brushes in your game, so maybe a character can enter the brushes, then you render the block first, then you render the character with a sprite where the bottom of the character is not drawn, to give the illusion the bottom part of the character is inside the brushes.

Can be applied to both approaches

You will possibly want to sort the references also by (x, y) position inside the tile/block, since objects can have different positions inside the tile/block, and therefore the order of their rendering is different.

\$\endgroup\$
  • \$\begingroup\$ Okay, yeah this makes sense. The only issue is that this would require erasing the old character when the player moves and a lot more map modification, etc. I was aware I could go this route, but I'm trying to avoid it if possible. \$\endgroup\$ – Christopher Dumas Aug 23 '18 at 18:49
  • \$\begingroup\$ At the beginning of the object_update(), you call a object_remove_from_tile(), then you move the object normally, and at the end of object_update(), when the object already moved, you call object_add_to_tile(). This is how I'm doing with my game. To avoid misunderstanding: objects are in a single pool, and the tiles have their own pool of pointers to the objects. \$\endgroup\$ – Ferreira da Selva Aug 23 '18 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.