Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I efficiently make fake tile shadows?

Tags:

c#

block

So I'm making a tile based game and I'd like to add some fake shadows to the tiles. It's kinda hard to explain so I'll do it with pictures:

Let's say this is my tile world:

world

And I want it to have shadows like this:

shadows

Because the world is tile based, I can split all the shadow parts into separate images:

parts

But now I have no idea how I would bring this to code. Well, actually I do have ideas, but they're incredible tedious and they don't work optimally.

I've tried a massive if-statement...

bool ul = adjacentBlocks[0, 0] == Block.Type.Rock; //Upper Left
bool um = adjacentBlocks[1, 0] == Block.Type.Rock; //Upper Middle
bool ur = adjacentBlocks[2, 0] == Block.Type.Rock; //Upper Right

bool ml = adjacentBlocks[0, 1] == Block.Type.Rock; //Center Left
//bool cm = adjacentBlocks[1, 1] == Block.Type.Rock; //CURRENT BLOCK - NOT NEEDED
bool mr = adjacentBlocks[2, 1] == Block.Type.Rock; //Center Right

bool ll = adjacentBlocks[0, 2] == Block.Type.Rock; //Lower Left
bool lm = adjacentBlocks[1, 2] == Block.Type.Rock; //Lower Middle
bool lr = adjacentBlocks[2, 2] == Block.Type.Rock; //Lower Right

if (ml) { texture = "Horizontal"; flipX = false; flipY = false; }
if (mr) { texture = "Horizontal"; flipX = true;  flipY = false; }
if (um) { texture = "Vertical"; flipX = false; flipY = false; }
if (lm) { texture = "Vertical"; flipX = false; flipY = true; }
if (ml && ul && um) texture = "HorizontalVertical";
//More if statements I can't be bothered to write
if (ul && um && ur && ml && mr && ll && lm & lr) texture = "Full";

And a massive lookup table...

var table = new List<TextureBlockLayout>
                                        {
                                            new TextureBlockLayout("Horizontal", false, false, new[,]
                                                                                         {
                                                                                             { true, true, false },
                                                                                             { true, true, false },
                                                                                             { true, true, false }
                                                                                         }),
                                            new TextureBlockLayout("Horizontal", true, false, new[,]
                                                                                         {
                                                                                             { false, true, true },
                                                                                             { false, true, true },
                                                                                             { false, true, true }
                                                                                         }),
                                            new TextureBlockLayout("Full", false, false, new[,]
                                                                                         {
                                                                                             { true, true, true },
                                                                                             { true, true, true },
                                                                                             { true, true, true }
                                                                                         })
                                        };

But either I'm doing something wrong or they just refuse to work at all. Any ideas?

like image 248
Dlaor Avatar asked Jul 03 '12 22:07

Dlaor


Video Answer


1 Answers

Each tile has eight neighbors. Each neighbor has two possible states. Map the states of the neighbors into bits in a byte, and use the byte as an index into a 256-element lookup table.

Yes, this is the "brute force" solution, and you might be able to get by with a much smaller table using some cleverer approach. But 256 elements isn't that much (you can easily load it from a data file), and the nice thing about this approach is that it's completely general — you can have all the 256 tiles look subtly different if you like.


OK, taking a closer look at the way your example tiles are shaded, it looks like you really only need four bits (and thus a 16-element table):

  1. Set this bit if the north, west and northwest neighbors are all green.
  2. Set this bit if the north, east and northeast neighbors are all green.
  3. Set this bit if the south, west and southwest neighbors are all green.
  4. Set this bit if the south, east and southeast neighbors are all green.

Even some of these 16 tiles are still rotated / mirrored versions of each other, but it may be easiest to store the orientation in the table alongside the tile index rather than trying to calculate it in the code.

like image 158
Ilmari Karonen Avatar answered Sep 22 '22 01:09

Ilmari Karonen