How would I efficiently make fake tile shadows?

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:

And I want it to have shadows like this:

阴影

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

部分

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?


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):

  • Set this bit if the north, west and northwest neighbors are all green.
  • Set this bit if the north, east and northeast neighbors are all green.
  • Set this bit if the south, west and southwest neighbors are all green.
  • 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.


    我会尝试这样的事情:

    struct surroundingTiles
    {
        static bool blockNE;
        static bool blockN;
        static bool blockNW;
        static bool blockW;
        static bool blockSW;
        static bool blockS;
        static bool blockSE;
        static bool blockE;
    }
    foreach(object tile in floor)
    {
        if(currentTile.surroundingTiles.blockW && currentTile.surroundingTiles.blockNW && currentTile.surroundingTiles.blockN)
            useTexture(currentTile, shadowSEtexture);
    }
    
    链接地址: http://www.djcxy.com/p/10918.html

    上一篇: 命令模式来传递应用程序的活动方法?

    下一篇: 我将如何有效地制作假瓦片阴影?