1
\$\begingroup\$

I'm trying to figure out an optimal solution to creating the illusion of a circular room within a 2D world.

Odin Sphere(Video Example) does this well. As you walk along the X axis the room will eventually wrap around and you'll be back at your original location.

My thought process was to have the level separated into sections and if the player passes a certain point on the X Axis have the initial sections position move to the opposite side.

I'm not sure how to handle enemy or other objects within the section though, if the level section is moved and they're active I'm worried they might fall through the world or other strange behaviors.

Anyone have experience implementing something similar to this?

\$\endgroup\$
1
\$\begingroup\$

One solution is to mod the character/camera position by the dimensions of the room. For example if the room is 2000 units large & the character is at position 1995 & tries to walk in the +X direction 8 units, then you would have the following:

xPosition = xPosition + update;   // apply the update
xPosition = xPosition % roomSize; // use mod to wrap around
// xPosition is now at position 3

The other consideration is how to visually transition across the edge of the room. Using just the above, the character would teleport from one location to the other. If the room fits on a single screen, that's probably fine as the background would stay in place. If it doesn't fit on the same screen, then I would divide the room into chunks & again use mod to determine which sections to render. For example, let's say you have the following:

  • screen is 1280px wide
  • full room is 6000px wide
  • the sections of the room are 750px wide
    • note: this means that it takes 8 sections (indexed 0 to 7) to represent the entire room
  • the character is at position 5900
  • the view should be centered on the character
  • the coordinates start with 0 on the left & increase as you move to the right

First you'll need to find the left & right extents of the viewing area:

screenLeft  = xPosition - (screenWidth / 2);  // 5260
screenRight = xPosition + (screenWidth / 2);  // 6540

Next, determine which sections would need to render. Note, we only need the integer part, so you can either use integer division, the floor function or a cast to remove the decimal portion. In my example, I'm assuming integer division:

leftmostSection  = screenLeft  / sectionWidth; // 7.013333 -> start at section 7
rightmostSection = screenRight / sectionWidth; // 8.72     -> go up to section 8

But there's no section 8! What we really need to do is wrap around to the section 0 (the first section). Rather than using a bunch of conditional logic, you can again use the % operator:

leftmostSection  = (screenLeft  / sectionWidth) % sectionCount; // 7
rightmostSection = (screenRight / sectionWidth) % sectionCount; // 0

Now you have enough info to know which sections (and enemies thereof) to draw to get a wrap around room. Visually, it would be something like this:

enter image description here

For future reference: When dealing with positive numbers, mod (often represented with the % symbol) gives the remainder after applying division. However, there's more than one way to interpret the notion of modulus & remainders when negative numbers are involved. The C# documentation for % explains their implementation; note that it does not give the canonical modulus, it gives the remainder & there's a difference between the two.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.