Early first person RPGs like Wizardry, Bard's Tale, Dark Heart of Uukrul, appear to be 2D representations of a 3D maze. I don't think any of these early games were using polygons or raycasting. Here are a few examples:

Wizardry Gaiden

The Dark Heart of Uukrul

Pool of Radiance

Phantasy Star

How did games like this actually create a "3D" view of the dungeon? Are these tiles clever glues together, sprites that are scaled and stretched, or some other technique? I suspect that there were a few different ways this was done. For example, the Famicom/NES versions of Wizardry has really nice and detailed walls compared to SSI's gold box games which look off.

The one I'm really curious about is Phantasy Star. It's one of the few that animates movement I thought most console games of this era treated the screen as tiles so this effect looks borderline magical. I can't tell how it animates, but it clearly has some compromises (such as inaccurate views to the player's sides) which I think are a byproduct of this technique.

I've found some modern techniques for doing this type of thing, but I'm more interested in the historical techniques used in the 80s and early 90s.

  • 4
    \$\begingroup\$ There isn't one answer to this. There are many different ways it can be done, and they have different restrictions on what kinds of mazes are allowed. I implemented one and it had a weird restriction on where you could put holes in walls. \$\endgroup\$
    – Almo
    Apr 27, 2022 at 18:51

1 Answer 1


(subsequent edit: I understand the games quoted in the OP had more limited movement options meaning this probably isn't the method used, but I'll leave it here as an example of games like Doom and Wolfstein. Also see @2br-2b's answer with video which explains it well)

I'm not sure of the name for it but I have implemented a javascript/html version of how (I understand) early Doom did it. It's effectively wrapping an image of a wall (whatever you want it to look like) onto calculated wall positions. You still need a 'ray' but only in 2D - one doing a 'steeleye span' across the player's view, firing the ray at say 1 degree increments panning left to right so maybe 120 degrees of horizontal view angle- whatever seems appropriate.

Process: Starting at left of observer's field of view, cast a 'ray' out in 2D. This is a position in the 3D space in front of observer, let's imagine at waist height, starting at the observer's position and moving forward until it hits something eg the side of a wall. Imagine firing a ray horizontally at your left-most peripheral vision.

At the point where it hits a wall: we know the position on the wall that it strikes, meaning we know which part of our wall image should be shown.

The 2D-> 3D bit: Get a vertical sliver of the wall image from top to bottom and plonk that on the screen view, scaled to the distance from the observer. Ie from a 2D position we get all of the wall top to bottom for that spot, but just that one vertical sliver.

Now do the same for the the next position (ie not quite leftmost field of view).

Each time you get a whole vertical slice of the image of the wall, so there's no idea of "up and down". The limitations are something like..

  • The height of the wall is usually constant unless some extra programming is added to take that into account (actually this would be pretty easy but might slow things down with extra calculation)
  • The corners in walls are always vertical on the screen, not angled/tilted.
  • So the player can't 'look up' - ie the horizontal angle of their view can't be anything other than .. um .. horizontal, although it'd be possible to 'jump' the wall corners are still vertical on screen.
  • The walls are usually in a maze made of right-angled wall corners, because a diagonal wall would show up in 'steps'. This might not matter if the ray angle increments is small enough though.

To explain further: my HTML/JS version of this placed a DIV at the point where the ray strikes a wall. The screen x-position of the DIV is the ray angle I'm running at the moment (which angle out of the 120 degrees). The screen Y position is always cented vertically. The height is determined by how far away that wall strike was (=original height / distance away * a zoom factor).

The DIV is as wide as I've divided the ray angle increment up by and the height is determined by how far away the strike is.

The image to fill the Div is grabbed from a static wall image, the x position being how far along the wall the strike occurred, and scaled to fit the DIV.

I hope I've explained it well enough to understand!

I expect there are other methods and this might not be a definitive "this is how they all worked" but it's one way of doing it.

  • 1
    \$\begingroup\$ A good demonstration of this can be found here: youtube.com/… . The vid is pretty long (it's part of a tutorial series on how to program a raycast game in Scratch), but it demonstrates the concept quite nicely. \$\endgroup\$
    – 2br-2b
    Apr 29, 2022 at 12:16
  • 1
    \$\begingroup\$ This answer is somewhat accurate for early 3D games like Wolfenstein, Doom, etc. where the player can move and rotate in small increments. But take a look at the screenshots in the examples OP cites - these are wholly 2D games, where the player snaps from tile to tile and makes 90-degree turns. So raycasting every increment along the screen is not required - wall segments only ever appear in a small collection of positions and angles, so they can be stored as sprites and layered with the painter's algorithm with no real-time distortion calculations. \$\endgroup\$
    – DMGregory
    Apr 29, 2022 at 12:23
  • \$\begingroup\$ @2br-2b thanks, that's a great video \$\endgroup\$ Apr 29, 2022 at 12:24
  • 1
    \$\begingroup\$ @DMGregory should that be posted as a separate answer? \$\endgroup\$
    – 2br-2b
    Apr 29, 2022 at 12:25
  • \$\begingroup\$ I'd recommend it, yes. I just have not had time to write one, so feel free to beat me to it! \$\endgroup\$
    – DMGregory
    Apr 29, 2022 at 12:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .