Animal Crossing has a unique way of scrolling the world map: When the character moves down, the the world rolls around and over at the top, like it's stuck to a cardboard tube:
This video shows how it moves.
How can I create this effect?
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It only takes a minute to sign up.Sign up to join this community
Seems like it's just taking a "flat world" and mapping to cylindrical coordinates. Essentially wrapping the world on a cylinder. I did something similar with a flat world, but I wrapped it onto a sphere:
The way I did it for a sphere is similar to the way you'd do it for a cylinder. Choose a suitable radius (ρ or "rho" in cylindrical coordinates) for your world. For each vertex, take the XZ coordinates of your world (assuming Y is height), then covert to cylindrical coordinates using the XZ and radius plus Y. If you don't add the Y, you'll get a flat cylinder. Then convert back to Cartesian coordinates to draw in game.
I was experimenting a bit after playing Deathspank, which has a similar effect. Though I never delved into it enough to see if it could be tuned to work super well, one possibility is to just modify items in your vertex shader based on depth. A function mapping cos(depth) to a Y axis modification works. You can adjust it such that the world not only drops off in the distance but also if it closer than some depth, making the world feel especially round. You can do the same for X axis value to make it seem more spherical. I'm unsure if this is how such games actually do it; my experiments gave unsatisfactory results but I didn't play with the ratios much, so it may have been as simple as changing the rate of falloff to make it better.
You want to go from a planar world, to a cylindrical one.
A rotation around the x axis (in homogeneous coordinates) looks like this:
| 1 0 0 0 | Rx = | 0 ca -sa 0 | | 0 sa ca 0 | | 0 0 0 1 |
ca = cos(angle) and sa = sin(angle)
To calculate the angle, look at the image. The pi/2 cancels out and you are left with:
angle = offset_from_character.z - radius
Also, look at the image. The angle of the projected point is dependent on the horizontal distance from character, the distance from the sphere is dependent on the vertical.
new_position = character_position - vec3(0,radius,0) + Rx * vec3(0,radius+_old_position.y,0)
be sure to cull things that are over the horizon, otherwise the whole world will wrap around.
Disclaimer: I haven't tested this and I am no mathematics expert, but the answer is something like this. Someone please correct me if I am wrong.