In this article I describe "pseudo-3D" display algorithm for tile-based games. See, for example, http://www.jnethack.org for actual code/screenshots. Let us assume that we have 32X32 tilesets. In the pseudo-3D mode, object/monster/feature at dungeon position (x,y) is displayed at (32*x - 16*y ,32*y) in the screen. Each 3D-tiles have dimension 48X64. Most of 3D-tiles can be generated from the original 32X32 tiles. Here I explain how to generate them:

floor(lava, ice, water surface, etc): One can slant the original 32X32 tile and generate 3D-version of them as below:

monster/item: One can simply place 32X32 tile in the middle of 48X64 tile. One can also create larger tile for dragons and such.

wall: Tiles for walls need to be re-drawn such as below:

Wall tiles for NetHack can be found in this under the folder "BXXX".


Let us consider how to draw the enclosed 16X32 area in the following figure:

In the case A, the area is affected by tiles of (x,y),(x,y+1), and (x+1,y+1). Here I present a pseudo-code to draw this region:
bg1 = background(x,y);
fg1 = foreground(x,y);

bg2 = background(x,y+1);
fg2 = foreground(x,y+1);

bg3 = background(x+1,y+1);
fg3 = foreground(x+1,y+1);

copy_tile( bg1, 16,32, 16,32, screen_x, screen_y);
copy_tile( fg1, 16,32, 16,32, screen_x, screen_y);

if( fg1 != empty ) 
  copy_tile_translucent( bg2, 32,0, 16,32, screen_x, screen_y);
else
  copy_tile( bg2, 32,0, 16,32, screen_x, screen_y);

copy_tile( fg2, 32,0, 16,32, screen_x, screen_y);

if( fg1 != empty || fg2 != empty )
   copy_tile_translucent( bg3, 0,0, 16,32, screen_x, screen_y);
else
   copy_tile( bg3, 0,0, 16,32, screen_x, screen_y);

copy_tile( fg3, 0,0, 16,32, screen_x, screen_y);

copy_tile( tile, source_x, source_y, width_x, width_y, dest_x, dest_y) copies width_x X width_y area starting at (source_x, source_y) in the 48X64 tile to the screen. copy_tile_translucent() does the same thing with translucency, so that items/monsters behind the wall remain visible. For the case B, it is almost the same.

In NetHack, there are no fg/bg distinction in the tile information so one need to extract the information through back_to_glyph(x,y) macro.