Search code examples
c2dparallaxallegro

Pseudo 3D walls (top-down raycasting, sort of)


See, I'm not posting code because I need logic, math, algorithms. Well:

I'm trying to achieve a 3d-looking visual for a top-down tile map using layers and parallax scrolling. The thing is: At the moment I simply set different "speeds" for each layer. But that would only work with some very specific camera positions, also, it makes so that the blocks have virtually an infinite height (as they will "increase in height" until they are out of the camera's FOV).

Is there a better (should be) to achieve the effect? Oh, and I'm using C with Allegro 5.

I thought about limiting each layer's offset, but I have no idea how.

My current method:

That's my current code for the layer "speed" (it repeats for up, down, left and right, changing coordinates):

if (key[ALLEGRO_KEY_UP])
    camera_y[0] -= 1;
    camera_y[1] -= 2;
    camera_y[2] -= 3;

Then I run a loop to draw the map with the tiles relative to the current layer's offset.

By the way, that's the desired effect (example with 3 layers):

Effect


Solution

  • For parallax scrolling, layers that scroll faster must be correspondingly larger:

    Scaled

    You can use unscaled tiles stacked on top of each other, offset by a fixed fraction of the distance from the center of the tile to the center of the viewport,

    Unscaled

    but the tops will not be continuous (unless the bottoms overlap). If all layer tiles are hand-drawn or rendered images, this is not an issue.

    If the walls are box-shaped, and you have images of the top and each of the four sides, you can draw them in almost 3D,

    Walled

    where at most two sides of each box wall is drawn, skewed.

    In all cases:

    If the center of the viewport is at world coordinates (xc, yc), point (x, y, z) maps to coordinates (x', y') relative to the center of the viewport:

    x' = (x - xc) × (z + z0) / z0

    y' = (y - yc) × (z + z0) / z0

    where z0 is a constant that determines the "size" of the parallax or depth effect.