As you may know, I am working on an isometric game (https://gitlab.com/hansonry/opengetgold). In this game it is possible for your player to go behind level features. So I wanted there to be a way to view the player and its surroundings behind level features.

One of the things I needed to do in order to accomplish this was to only render things that were behind the player. This seemed like it should be easy enough, but it turns out it actually was very challenging.

The Problem

To start off with, lets go over some basics. Below you will see the coordinate system I am using for the game. Note that not all games will use this same coordinate system.

There are a couple of comparisons that you can do that will give you a way to cull away isometric blocks.

Using these operations I thought I could easily find a simple solution to removing everything in front of the player.

Well, right out of the gate I had problems. Consider the level below:

The simple solution (I thought) would be something like the x + z comparisons method.

Well that kinda worked, but there are a lot of issues. for example on the left and right corners there are culled tiles that didn’t need to be culled. In the middle there is a tile that should be culled, but it was not.

I tried every combination of if statements that I could think of and they all had strange edge cases. I tried to pull out the big guns and attempt to flood fill the map where the player could be. Turns out I would remove too much in some cases.

The Solution

After thinking about it for a day I came up with a new (I think) algorithm. I call it the Ryan’s Isometric Seek Culling or RISC for short. I am sure someone else has already come up with this so if they have please let me know so I can correct this post.

The algorithm basically plots a left and right path going a way from the player. Each step along the path a token is dropped. At every step the path tries to head closer to the camera along the x or z axis. If they can’t then they will try to keep going in their original direction but away from the camera. If they can’t get closer or farther from the camera while heading their the path is done. All blocks between the camera and the marks should be cleared.

The pseudo code:

# 1. Drop tokens on the map. You can start by going left or right # the order doesn't matter. make an empty token set # 1.a. Drop tokens while going left set x and z to player location loop until stuck or (x, z) out of range { add token to the token set at (x, z) if (x, z + 1) is not a block { z = z + 1 continue the loop with the new position } if (x - 1, z) is not a block { x = x - 1 continue the loop with the new position } stop the loop you are stuck } # 1.b. Drop tokens while going right set x and z to player location loop until stuck or (x, z) out of range { add token to the token set at (x, z) if (x + 1, z) is not a block { x = x + 1 continue the loop with the new position } if (x, z - 1) is not a block { z = z - 1 continue the loop with the new position } stop the loop you are stuck } # 2. Clear all blocks between the camera and each tile for each token in the token set { for each block in the block list { if(block.x - block.z == token.x - token.z and block.x + block.z > token.x + token.z) { remove block from the block list } } }

The result of the algorithm is below:

As you can see it isn’t 100% perfect but it gets the job done well for the purpose of creating a rendering for an XRay view. You can see my C code implementation here: https://gitlab.com/hansonry/opengetgold/blob/master/src/isorenderer.c There is a lot of other things going on, but I see no reason to copy myself.

See also