# Determine what to draw based on neighbour tiles?

I have a tilemap and I want to add walls to it. I painted 16 images, one for each possible combination. For example:

• A lone wall tile would get a image that has walls around.
• A corner would get either four of the corner images.
• A T intersection would get one of the 4 T intersections.
• etc...

I could make 16 statements but I was wondering if there would be a better way to determine what tile needs to be placed. I have seen some code a long time ago where they used bit comparison for the walls but I don't know if that could be used for this specific problem.

Another option would be to use transparent walls and paint them where necessary then compare these and draw a connection image in the corner since they would overlap.

For clarification I paste my current method here. Which looks amateurish to me.

``````private void setCeilingTexture(Map map, int x, int y) {
if (map.isWall(x - 1, y) && map.isWall(x, y + 1) && map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_open"));
return;
}
//T intersections
if (!map.isWall(x - 1, y) && map.isWall(x, y + 1) && map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_leftclosed"));
return;
}
if (map.isWall(x - 1, y) && !map.isWall(x, y + 1) && map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_topclosed"));
return;
}
if (map.isWall(x - 1, y) && map.isWall(x, y + 1) && !map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_rightclosed"));
return;
}
if (map.isWall(x - 1, y) && map.isWall(x, y + 1) && map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_bottomclosed"));
return;
}

//Single openings
if (map.isWall(x - 1, y) && !map.isWall(x, y + 1) && !map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_leftopen"));
return;
}
if (!map.isWall(x - 1, y) && map.isWall(x, y + 1) && !map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_topopen"));
return;
}
if (!map.isWall(x - 1, y) && !map.isWall(x, y + 1) && map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_rightopen"));
return;
}
if (!map.isWall(x - 1, y) && !map.isWall(x, y + 1) && !map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_bottomopen"));
return;
}

//straight
if (map.isWall(x - 1, y) && !map.isWall(x, y + 1) && map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_leftright"));
return;
}
if (!map.isWall(x - 1, y) && map.isWall(x, y + 1) && !map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_topbottom"));
return;
}
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_single"));

//corners
if (map.isWall(x - 1, y) && map.isWall(x, y + 1) && !map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_topleftopen"));
return;
}
if (!map.isWall(x - 1, y) && map.isWall(x, y + 1) && map.isWall(x + 1, y) && !map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_toprightopen"));
return;
}
if (!map.isWall(x - 1, y) && !map.isWall(x, y + 1) && map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_bottomrightopen"));
return;
}
if (map.isWall(x - 1, y) && !map.isWall(x, y + 1) && !map.isWall(x + 1, y) && map.isWall(x, y - 1))
{
((Wall)map.getTileMap()[x][y]).setCeilingTexture(randomTexture("ceiling_bottomleftopen"));
return;
}
}
``````

Works perfectly, yet there must be a better way then this wall of statements.

• You could use a HashMap or some kind of hashable structure that maps tuples (wall tuples) to their textures. Alternatively, rename the textures to be based on their offsets and then just those for the filenames. Feb 28, 2016 at 20:37

If you just want to improve readability, why not just extract some booleans out for those conditions? Then things would be more readable.

Alternatively, if you want another approach here's what I came up with:

You could do this with some bit masks without too much trouble and it would greatly simplify your code. You essentially have 4 flags here -- one for each "wall".

Let's declare 4 flags for you.

``````public enum Flag {
UP, DOWN, LEFT, RIGHT;
}
``````

Great. Now, we declare a flag:

``````EnumSet<Flag> wallFlags
``````

Create a set based on the walls I'll leave this as an exercise to you. Then, there is clearly a few combinations here you care about, so let's map those out here, we'll create a HashMap:

``````directionMap = new HashMap<Flag, String>();
directionMap.put(Flags.Up,  "myfilenamehere"
...
``````

This may not compile as I haven't worked in Java in a while but it should be close. Of course, you still have quite a bit of boilerplate code here but it becomes immediately obvious to me as a reader now. You can tell what is going on without reading a bunch of ifs that are VERY similar.