   How do you usually handle tile occlusion in a 2d game?
  I have a 2d sprite based game that uses multiple layers. Each layer contains an array for the layout and also a boolean on whether the layer is occluded or not. Then in my drawing code, I draw the non occluded layers first. Then I draw the players and then I draw the occluded layers.I currently have a sort of square of transparency set up so the 3x3 grid that the player stands in will draw the occluded layers with an alpha of .8f. The 4x4 part is .85f and the 5x5 is .9f. Everything else draws at 1.0f and it gives a neat effect.I'm trying to think of other ways to do this though.One way is whenever the player steps on a tile that is part of an occluded layer, don't draw any part of that layer. I've seen this before in games. You walk behind something and suddenly you can see everything.Another way is where when you step on a tile, only the nearby tiles aren't drawn. Sort of like if you walk behind a tree and only that tree disappears. This is the way that I would like to handle it in my game and I've thought of two ways to do it but both of them has problems.The first way is probably the easiest. All I do is create a layer for every single tree. It wouldn't be a problem for small levels but if I'm creating a 200x200 grid with 50+ trees, it seems like it's kind of a waste. How my code is currently set up, layers are the same size as the map so it would have a 200x200 array filled with -1's minus a little 4x4 patch in the array.Another idea I had was to use recursion. When the player touches a tile, I could hide all of the tiles that are physically touching. One problem with this is if my trees are too close together like in a forest level, then they will all disappear. Another problem is this code would be being executed all the time so I don't think recursion is the most optimal solution.So, what do you usually do?   
Quote:Original post by afsd42The first way is probably the easiest. All I do is create a layer for every single tree. It wouldn't be a problem for small levels but if I'm creating a 200x200 grid with 50+ trees, it seems like it's kind of a waste. How my code is currently set up, layers are the same size as the map so it would have a 200x200 array filled with -1's minus a little 4x4 patch in the array.That certainly is a waste, yes.Quote:Another idea I had was to use recursion. When the player touches a tile, I could hide all of the tiles that are physically touching. One problem with this is if my trees are too close together like in a forest level, then they will all disappear. Another problem is this code would be being executed all the time so I don't think recursion is the most optimal solution.This has nothing to do with recursion - recursion is simply an implementation detail (either way, I don't see why you would need to use recursion for this).Now, why don't you just make one occluded layer that contains all those objects (I assume that you mean a layer that's on top of the player), check which tiles are touched by the player, and render those - and the ones surrounding them - with a different alpha?   ;Quote:Now, why don't you just make one occluded layer that contains all those objects (I assume that you mean a layer that's on top of the player), check which tiles are touched by the player, and render those - and the ones surrounding them - with a different alpha?Yes I mean a layer drawn over top of the player. I'm currently doing occlusion like you describe. I'll draw a little something which will hopefully make sense:= = = = = = = = == 7 7 7 7 7 7 7 == 7 5 5 5 5 5 7 == 7 5 3 3 3 5 7 == 7 5 3 X 3 5 7 == 7 5 3 3 3 5 7 == 7 5 5 5 5 5 7 == 7 7 7 7 7 7 7 == = = = = = = = =The X represents the player. All the tiles with an = sign would be drawn with 1f alpha. The 7's are drawn with .9f. The 5's are drawn with .85f and the 3's as well as the X are drawn at .8f. It only affects occlusion layers as well so the regular layers are drawn normal. What this does is when the player starts getting closer to a tile that is occluded, it will gradually get more transparent. The effect is alright but it isn't really what I'm looking for in my game.What I would rather have would be for all the tiles that are touching to be occluded. So if I have a 4x4 image of a tree on an occluded layer, the entire image disappears. I don't want the entire layer to disappear though. So if an occluded layer were to have 3 or 4 trees, when the player touches on of the tiles, only the tree they are touching should disappear.The way I currently draw is by looping through the two dimensional array and going from left to right. If I did this, and the player was touching the tile from the right side, then it would have already drawn the 3 tiles to the left. I'll assume before drawing the layer, I would need to check where the player is, and store that point in some kind of collection object. However, after I have that point, I don't see any other way to find all the tiles that are touching without using recursion? Hopefully I'm just overlooking something though..(One negative that I guess I would just have to work around is that I couldn't have two trees side by side because it would read the tiles as one single thing.)   ;  i did this same thing and used a different layer for each object. wasn't fun. you should write a method that recursively finds tangent cells on the same top layer.   ;Quote:Original post by afsd42What I would rather have would be for all the tiles that are touching to be occluded. So if I have a 4x4 image of a tree on an occluded layer, the entire image disappears. I don't want the entire layer to disappear though. So if an occluded layer were to have 3 or 4 trees, when the player touches on of the tiles, only the tree they are touching should disappear.First of all, I think you mean occluding layers, not occluded.So, you have a few trees, and whenever the player gets close to one, the whole tree image should become more transparent, based on how close the player is to it, right? Let's get something straight here: those trees consist of multiple tiles, right (4x4)? That top layer contains some tree sprites, but also a lot of empty tiles, right?Quote:The way I currently draw is by looping through the two dimensional array and going from left to right. If I did this, and the player was touching the tile from the right side, then it would have already drawn the 3 tiles to the left.Ah! First check for collisions, then draw. It's rather obvious that you need to know those things beforehand. On a sidenote, an easy optimization would be to only check those tiles and images that are visible on the screen. Those outside the screen rectangle don't need to be checked.Quote:I'll assume before drawing the layer, I would need to check where the player is, and store that point in some kind of collection object.You already know where the player is... How else do you know where to draw him?Quote:However, after I have that point, I don't see any other way to find all the tiles that are touching without using recursion? Hopefully I'm just overlooking something though..Recursion usually means that a function is calling itself. So I don't see a connection there. You can simply loop through some tiles and check for collisions, although it's likely possible to calculate what tiles the player is touching, because you're working with a grid.Quote:(One negative that I guess I would just have to work around is that I couldn't have two trees side by side because it would read the tiles as one single thing.)If that tree layer has lots of open space, then you might as well just place those tree sprites on the map freely, without using a tilemap system. Tilemaps are efficient, but they also restrict you in terms of positioning.   ;Quote:First of all, I think you mean occluding layers, not occluded.Yeah I mean the layers that get drawn over top of everything.Quote:So, you have a few trees, and whenever the player gets close to one, the whole tree image should become more transparent, based on how close the player is to it, right? Let's get something straight here: those trees consist of multiple tiles, right (4x4)? That top layer contains some tree sprites, but also a lot of empty tiles, right?Well I'd rather the whole tree just become transparent at once rather than have some parts of the tree more transparent than others. And yes, the top layer contains lots of empty tiles. I'll write more about this lower down.Quote:Ah! First check for collisions, then draw. It's rather obvious that you need to know those things beforehand. On a sidenote, an easy optimization would be to only check those tiles and images that are visible on the screen. Those outside the screen rectangle don't need to be checked.As far as checking collisions though, is there any way to do it besides recursion or iterating through it left to right + up to down and right to left + down to up? I already did the optimization too.Quote:Recursion usually means that a function is calling itself. So I don't see a connection there. You can simply loop through some tiles and check for collisions, although it's likely possible to calculate what tiles the player is touching, because you're working with a grid.I don't think a couple for loops could do this at all. At least not without doing several passes through the entire array.I don't like recursion but I went ahead and wrote a function to find the connected tiles. I spent a good hour thoroughly testing it and following flow to ensure that it doesn't go all stupid on me and backtrack. I'm pleased with the result so far too.http://img39.imageshack.us/img39/9190/occlusion.jpgAll it does is check the current tile and it stores it in a list if it's good. Then the function checks the tile above it, below it, to the left and to the right. If those are valid, it calls the function with their coordinates as a parameter. And so on and so on.Quote:If that tree layer has lots of open space, then you might as well just place those tree sprites on the map freely, without using a tilemap system. Tilemaps are efficient, but they also restrict you in terms of positioning.I'm not sure what you mean by placing them freely? I thought about making another class just for layers that I want to occlude, like trees. Instead of using the same size grid as the entire map, it could be 4x4 or whatever and I could also store the upper left x & y coordinate so I know what part of the map it goes on. This would certainly save space but I also have a custom editor and if I did this, then I would still be stuck with way too many layers. The initial drawing might not be so bad but if I had to scroll through 50+ layers just to figure out which layer held the tree I was looking at in the editor and I wanted to delete, I wouldn't be too happy.   ;Quote:Original post by afsd42Well I'd rather the whole tree just become transparent at once rather than have some parts of the tree more transparent than others. And yes, the top layer contains lots of empty tiles. I'll write more about this lower down.Sounds like those trees would indeed better be treated as separate (single) sprites, not as parts of a tilemap (in which they would get chopped up into several sprites/tiles).Quote:As far as checking collisions though, is there any way to do it besides recursion or iterating through it left to right + up to down and right to left + down to up? I already did the optimization too.Whatever approach you take, it usually involves iterating through some list or container of objects, or through some other data structure. That's nothing to worry about. Now, when you're working with thousands of objects, then high-level optimizations become relevant, but otherwise, a basic approach usually suffices.Quote:I don't like recursion but I went ahead and wrote a function to find the connected tiles. I spent a good hour thoroughly testing it and following flow to ensure that it doesn't go all stupid on me and backtrack. I'm pleased with the result so far too.Ah, so, what you're doing is checking what tiles are connected to the ones the player is touching (ignoring empty tiles) and then treating those as one single 'element' for the purpose of hiding it. That wasn't entirely clear to me yet, but now it makes sense why that would mess up situations with multiple trees next to each other - and why you were thinking of recursion.Well, if you intend to keep using tilemaps for this (which personally, I wouldn't, see below), your best bet is probably adding a second tilemap that contains grouping information. It shouldn't be used for rendering, only for looking up what tiles are 'connected' with the ones the player is touching.Quote:I'm not sure what you mean by placing them freely? I thought about making another class just for layers that I want to occlude, like trees. Instead of using the same size grid as the entire map, it could be 4x4 or whatever and I could also store the upper left x & y coordinate so I know what part of the map it goes on.You're close, but not quite there yet. Why don't you discard the idea of using tilemaps for such trees, and use a single sprite per tree instead? As I said, tilemaps are efficient, but also restrictive. Some games just use loosely placed images, stitched together manually, instead of positioning tile images on a rigid grid.Put into a textual form, a tilemap does this:Starting at 0, 0, paint a tile every 32 pixels,4 rows of 4 tiles each. These are the tiles, in this order:tree_0.png, tree_1.png, tree_2.png (yadda yadda yadda)Freely placing sprites could be described as following:Paint tree.png at 45, 96Paint tree.png at 108, 220So, if every tree consists of a single sprite, you only need to check what trees the player is touching, and adjust the transparency of those tree sprites. You may need to add support for this in your custom tool, though. I certainly would not treat every sprite as a separate layer. You'll want something that allows you to place multiple sprites/objects on a single layer.   