Jump to content
  • Advertisement
Sign in to follow this  
suliman

How to mark roof for show/hide?

This topic is 956 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!
Im doing a top-down tilebased game in c++. Players can enter houses in which case roofs should be hidden (so you can see the enterior of the house. Right now i simply do:

 

if player is standing on a ground-tile that has a roof (player is inside a house) skip drawing ALL roof tiles.

 

I would like to only skip drawing the roof of that SPECIFIC building (not skip ALL roofs). Any clever way to do this? I need to find all "touching" roof-tiles and mark these for "hide"?

 

I could mark all those tiles with an unique ID when I place the building and hide/show based on that, but i would prefer a more flexible solution (if there are any).

 

Thanks!
Erik

Share this post


Link to post
Share on other sites
Advertisement

Put a sensor, that is a rectangle of a tile size if you want. Place this sensor near the door, since the player can only enter from there. When the player passes over the sensor, the sensor will act like a light switch, turn on / off light, but in this case, turn on / off the roof.

if ( sensor.detect == true ) {
    building.roof.visible = !building.roof.visible;
}
Edited by Ordnas

Share this post


Link to post
Share on other sites

but the problem is how do i find all roof-tiles belonging to that building? Buildings are not classes, they are just a section of the map that happens to have roof painted on those tiles.

 

I need like a spreading search to find all adjacent roof-tiles which are not 0 (meaning no roof for that tile).

Share this post


Link to post
Share on other sites
I've just solved this problem in my own game by having camera detect the best view distance (camera z position) based on what's directly above the player.

Trace a line vertically upwards from the player characters head (in my case just using the up vector) for a maximum height, in my case I chose 250 "units" in height. If you don't encounter any collision on your line trace before you get to 250 units, then your camera height is 250 units plus the players z coordinate. If you encounter a collision, e.g. a building roof, cave roof, tunnel, etc, then the cameras height above the player is the height of that obstruction minus a few pixels, also plus the players z coordinate.

This means you can always see something. Note though that if the roof is very low your field of view will also be very low so be aware of this when you design your level geometry.

This is a good solution as it will even work with multi storey buildings etc, without needing to add any metadata to your map.

Have fun!

Share this post


Link to post
Share on other sites

I haven't yet implemented this in my game, but I intend to solve this by using rectangles to define a building's region, and using the rectangles to mask out anything from layers above the player, and then inverting the mask to darken areas outside the building.

Share this post


Link to post
Share on other sites
The most fool-proof and reliable solution is to have a second "tile" map that just identifies the building covered by the roof tiles. All the tiles making up your Item Shop may then be marked as building 1 while all the tiles making up your Inn are marked as building 2 and so on. Open air is marked as not being a building, e.g. "building 0".

If the player is standing in a tile that has a building - that is, the building tile map has a non-zero value in it - then do not draw the ceiling tiles that match that building number.

This is also far more flexible than the other solutions. You can very easily mark up all building, you can split a single building into multiple areas (e.g. the hallway could be marked as 1 while the dining room is marked as 2, even though they're the same "building" conceptually). You can paint non-rectangular building easily. You aren't limited to trigger zones and hence will have fewer builds and an easier time modifying levels. You can mark camera-facing wall tiles in isometric views just like you can mark roofs.

It can be made even more flexible with very little work, too. If you want to have adjoining buildings where you see part of it in one place and all of it in another, making the building tilemap store bitmasks instead of ids; the logic then is to hide any overlay tile whose masks intersects with the mask of the tile the player is in.

If you have multi-story buildings, just split up each story its own set of tilemaps. Disable all rendering of any tiles on any layer at or above the player's layer matching the current building id.

Share this post


Link to post
Share on other sites
@Sean and @Servant, these are good solutions but they are kind of art heavy.

In my case my game is entirely developed just by me, and it is quite a large game so to fit it all in and release it I need to be smart in making the game identify most things itself without them having to be defined by an artist or programmer.

If you have a dedicated team of artists or a very simple level design you can manually mark out all your ceiling tiles etc, defining bitmasks for tile types etc.

It seems also that creating this game as a tile based isometric game generates much more art overhead, but this is usually the case with hand drawn isometric art...

Share this post


Link to post
Share on other sites

Mine's not art heavy (no new art needs to be created), it is "developer heavy", in that the developer has to decide what locations to mark, but it'd be very little effort (depending on your map editing tools), and take very little memory. You'd store a few rects (four ints), I would guess it'd be about 4 to 20 bytes per house - less than a single KB for a large village. Virtually nothing. You could compact it further with short ints if necessary. Honestly not an area I'd focus memory optimization on, it's small enough with too little gains already.

 

From the rects you'd:

A) Detect if the player is within one set of rects (one building) vs another set

B) Generate a stencil mask or screen-space alpha mask from the 

C) Use the mask to prevent (roof/whatever) overdraw of the building (or just a single room, if you prefer) that you are in.

D) Use the inverse of the mask to darken everything outside of the building - not entirely black, but say, 50% darker.

 

As mentioned, I haven't implemented this in my game yet, but I don't seen any reason why it'd be an excessive memory hog or performance bottleneck, other than the costs of the mask buffer.

Share this post


Link to post
Share on other sites

I would suggest to find all roof tiles adjacent to the roof tile above the player via a simple flood fill style algorithm. Easy to implement and will only hide all tiles which touch other roof tiles which are connected to the roof tile above the player. If you want to separate roofs which have no spacing in between you would need to add additional criteria for the neighborhood check (e.g. same roof tile set or something similar).

But the easiest to do would be to ensure a space of at least one non-roof covered tile between two houses..

 

 

See here for the algorithm: https://en.wikipedia.org/wiki/Flood_fill 

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!