Row scrolling for parallax effects

In the last post we looked at what tilemaps are and how they’re used in SF2, and ended with a mention of how multiple layers (or scrolls) of tilemaps can be moved at different amounts to achieve parallax scrolling, creating the illusion of depth.

Elephants overlapping by different amount depending on the camera position.

This really only works for elements that are standing upright, though. There’s no way we can use this effect for horizontal surfaces like floors and ceilings – we’d either need to use a lot more layers which we don’t have, or a huge amount of tiles to represent different perspective angles, which we’d rather not.

For horizontal surfaces like floors and ceilings, SF2 uses another technique called row scrolling (a.k.a. line scrolling).

We saw in the previous post that the CPS1 has three layers of tilemaps which can be scrolled independently: Scrolls 1 through 3. One of these layers is special, and allows for each individual row of pixels to be scrolled horizontally, in addition to the entire layer itself. We can see this effect on the the floor here:

Two different perspectives of the floor: one in the centre, compared with one at the far left of the stage.

This layer is Scroll 2. In SF2 we can think of this as the “main” scroll. The other two scrolls and the sprites are always positioned somewhere relative to this main scroll’s position, and the Z-depth of those scrolls.

We can think of an imaginary line just underneath the feet of our fighters as having a Z-depth of zero. A small amount of floor in front of the fighters has a negative Z-depth, with background elements having some positive Z-depth.

As the camera moves horizontally, elements with a negative Z-depth move more than elements at Z=0, which in turn move more than elements with a positive depth. Elements very far away (in photography and modelling we call this “at infinity”) don’t move at all.

This matches our experience with the real world, for example riding a train and looking out the window a far away mountain. In the space of a minute, the mountain seems not to move at all, nearer features appear, cross our vision and disappear from view, while the fence bordering the railways corridor whizzes past, the only object giving us a true sense of the train’s speed.

Let’s take a look at E Honda’s stage as it is the most interesting. All of the SF2 stages have a floor with parallax scrolling, only a few also have a ceiling, but E Honda’s also has a nice bath in the centre of the stage. Let’s look at how that stage is layered:

The three tilemap layers, Scrolls 1, 2, and 3 from left to right.

We have Scroll 1, with the front surface of the bath, Scroll 2 containing the floor, ceiling and the top surface of the bath, and Scroll 3 with the background.

The three layers combine with the sprites to create the full image shown below. Ken and Ryu’s sprites are anchored to Scroll 2, water dripping from the bath and a small tub are anchored to Scroll 1, which contains the front surface of the bath.

Note that while Scroll 1 is drawn on top of the other layers, the object it contains appears between the floor and the top of the bath. This works, because Scroll 1 moves as if it were located there. The key thing here is that the layer’s priority (which layers it is drawn on top of) and the layer’s displacement are two different things.

Note also that the scrolls don’t have to be layered with 1 on top and 3 at the bottom, it just happens to be this way for E Honda’s stage. Ryu’s stage uses Scroll 1 for drawing the sky, which places it underneath all the others. The clouds in the sky fly past independently of our movement on the stage – parallax isn’t used for it all.

Consecutive rows in Scroll 2 are grouped together depending on which surface they belong two, and each row within that group is displaced by a certain amount to create a shear transformation. I’ve drawn a rectangle around the floor area so its effect can be easily seen:

Three different floor perspectives, the extreme left of the stage, the centre, and extreme right.

In the centre of the stage, the horizontal offset is zero, and the tiles are drawn unmodified. As we move away from the centre of the stage, the rectangle becomes more and more skewed, and the entire layer also scrolls, giving the appearance of a flat horizontal plane behaving as if we were looking at a 3D scene.

Why can’t the front of the bath just go in Scroll 2? Because there are 16 rows of floor pixels that are beyond it. If the bath were in the same layer, it would be sheared along with the floor tiles, which wouldn’t look right. You can see the sheared floor rows disappearing behind the bath here:

The same effect is used on the ceiling and the top of the bath. Nothing remarkable happens with Scroll 3, the most distant, background layer, until the round ends and man holds up his sign. (I used to think it was meant to be some sort of candy bar commercial, but it turns out the kanji says something like “round complete”).

This has been a visual overview of how the CPS1 uses row scrolling in addition to layered tilemaps to create parallax effects. In the next post, we’ll look under the hood at the code that makes all this happen.

Row scrolling for parallax effects

What are tiles and scrolls?

[This post is a prologue to an upcoming post about parallax scrolling in Street Fighter 2]

Most games of the SF2 era were tile-based, meaning the graphics weren’t drawn in individual pixels, but with square tiles of pixels. This helped reduce the RAM that would be required to store individual pixels (often in multiple layers) and also reduce work for the CPU to update animations.

The Capcom Play System hardware which SF2 ran on uses three different tile sizes: 8×8, 16×16, and 32×32. Background graphics are displayed these tiles in three layers, each using one of these tile sizes, and the layers can be arranged in any order from foreground to background; transparent areas in one layer reveal the layers beneath it. These are called scrolls.

On top of these three scroll layers is the object layer, where sprites such as the playing characters, projectiles, some stage animations, as well as the energy gauge and score display. Tiles in the object layer are 16×16 pixels.

Let’s take a look at a diagnostic screen in SF2 which lets us look at individual tiles:

Some of Ryu’s tiles, each 16×16 pixels, numbered with a unique ID. I’ve displayed them all separated by gaps so you can see how big one tile is.

Often, the tiles are stored in ROM in a natural order as they are above so it’s easy to visualise the fully assembled image, but they don’t need to be. As far as the graphics hardware is concerned, each tile is selected by its identifier, and can be placed next to any other tile.

Many of the tiles are reused for different animation frames. For example, if Ryu’s legs look the same whether he’s standing or throwing a short punch, each of those tiles can be reused for that frame. This saves space in the tilemap ROMs. Background graphics especially are designed to exploit this, usually feature large areas of the same tile, or group of tiles, repeating.

Each pixel in a tile is assigned one of sixteen indexed colors, with the last color always being transparent. The graphics hardware looks this indexed color up in a palette, which determines the red/green/blue components of the pixel color, which is then finally drawn on-screen. In this way, tiles can be reused in different colors. This is used a lot for Ryu and Ken, who differ only in tiles containing their faces, and the color of their uniform.

Let’s take a look at that:

Some tiles of Ryu throwing a Hadouken. We can also some tiles of Ken’s head, but they don’t look right, because we’re displaying these tiles with Ryu’s palette.
Exactly the same tiles, but with Ken’s palette. Now Ryu’s head doesn’t look right, but those tiles won’t be used with this palette.

SF2 Championship Edition, which allowed fights between two of the same character also used this effect so each of them could be distinguished.

Additionally, each tile can be flipped horizontally or vertically. For example, a player facing left uses exactly the same tiles and if they were facing right, only flipped.

This is why Sagat’s eye-patch changes from one eye to the other when he turns around, and why a Shoryuken is thrown with a left arm when facing left, and vice versa. To do otherwise would have required a different set of tiles depending on which way the player was facing, which would have complicated the animation engine also.

Now let’s talk about the scroll layers used for the background. One limitation with these is that each layer is arranged in a single large grid. Tiles drawn this way can’t be moved around by individual pixels like the sprites can, so there’s a limit to what kind of animations that can be used there.

In SF2, animations in the background layers are constrained to simple sequences of a few repeating frames, such as these elephants, which move their trunks up and down, but don’t otherwise move around relative to the other tiles in the same layer. If they did, it’d need be by a multiple of 8, 16, or 32 pixels depending on what layer they were in.

However, each of the scrolls themselves can be moved with one-pixel resolution. The most noticeable use of this is seen as we move left and right along the stages, which – apart from the bonus stages – are wider than the screen.

But a more subtle effect (well, it was subtle for me, whose attention was mostly drawn to fighting, and usually losing) involves moving the scrolls by a different amount relative to each other, to achieve parallax scrolling and create the illusion of depth, or 2.5D:

Both players are near the middle of the stage, note the three elephants
Near the extreme left, note the elephants are starting to overlap each other

Another example of parallax can be seen on the floor. Note the orange rug changes perspective as we move across the room. This effect can’t be achieved with tiles alone, or at least not without creating lots of them for all of the different perspective angles.

This is a graphics effect on the CPS1 called line-scrolling (or row-scrolling), which involvs each individual row of pixels being translated left/right by a certain amount, and will be the topic of my next post. Until then!

What are tiles and scrolls?