How to program action game in a wrapping world? (2D torus)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
nadomodan
Prole
Posts: 4
Joined: Fri Feb 15, 2019 11:24 pm

How to program action game in a wrapping world? (2D torus)

Post by nadomodan »

Imagine simple top-down arena shooter, bump.lua for collision, tile map made in Tiled or proceduraly generated, standard stuff except the edges of the map are connected, kind of like in Asteroids.
This game seems to have implemented it pretty well https://benjamin-soul.itch.io/voidrun, look at the second .gif, notice that singular ground tile sticking out of water in one of the pools, you can see it at the bottom first, then when player goes north you can see it at the top, the world loops seamlessly. How would you implement this in game? I've searched through reddit posts, forums and articles but couldn't find any solution, everyone suggest the same naive implementation that only works in something very simple like Asteroids, as in: when object goes out of map bounds, teleport it to the other side, they also suggest drawing everything 4 or even 9 times to make it visible through the "loop" when near the edge of the map, also checking collisions extra 4 times to account for all the wrapping directions, well, you can probably see how it's not going to work well, all the edge cases you have to individually code for etc etc.
Here's one example, illustrated
Image
Green is floor, light blue is impassable water, grey is mountains (obstructs enemy vision). Yellow is player with their camera viewport selected, since the map wraps around they should be able to see the white square. Red and orange don't have a clear line of sight for each other if you compute it normally since the mountain blocks it but they should be able to see each other, looking the other way through the edge of the map. Red and orange also see the player, they can't pathfind to player if it was a normal map with impassable edges but since it loops they should be able to reach player by going south.

I feel like there is some way to program a system that elegantly and automatically handles all this but I just can't figure out how to do it, I have played Voidrun, kept running in one direction, looping around the world and the enemies perfectly follow and shoot at me, there are no obvious gaps or connected edges while playing, it's seamless.
https://twitter.com/benjamin_soule_/sta ... 0998666241
https://twitter.com/benjamin_soule_/sta ... 5538442240
https://twitter.com/benjamin_soule_/sta ... 9649017861
Even those segmented worm enemies work perfectly, no way you could get it to work cleanly with the hacky "drawing everything multiple times and checking collisions multiple times in all directions" method since that doesn't cover pathfinding, line of sight, aiming and shooting etc. How?
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: How to program action game in a wrapping world? (2D torus)

Post by ReFreezed »

My suggestion would be exactly like the suggestions you've already gotten: do everything 4 or 9 or however many times necessary. There's no magical solution. From each individual character or object's perspective, it looks like there are more other objects than there technically are, so you have to treat everything like that in the code - like there are more objects than there actually are.

You'll just have to adapt the code (e.g. there might be an array of 5 actual objects) so that the idea of what's happening in the game world looks true (e.g. it looks like there's an infinite number of objects, no matter what the reality is or any code actually says). Obviously it's not feasible to collision check or render an infinite number of objects, but with limitations (maybe characters can only "see" things one "world length" away in any direction) and optimizations (e.g. only check collisions with "wrapped" objects when you're close to a border) you can get away with doing things only a few times.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by pgimeno »

I wanted to add a few things to what ReFreezed has said. You may not have considered worlds smaller than the screen, but if you did, they would indeed look infinite, as he noted, like this toroidal Sokoban clone: https://tic80.com/play?cart=1441 . That's how objects in the world see the rest of the world, rather than through the tiny window that you let people see.

I wrote Thrust II Reloaded with wrapping in mind, like the original did. Indeed I drew everything twice in my case, because the T2R world's topology is a cylinder rather than a torus (top and bottom are bounded and don't wrap around) and big enough to not have to worry about more than two copies. That's simpler, but still there were some challenges and I had to fix several wrapping-related bugs (especially the disappearance of some objects during the crossing of the wrapping line). You face bigger challenges.

In your case, the biggest challenge is going to be the libraries. The graphics, not so much. I'm not sure if there's a pathfinding library that supports toroidal graphs; maybe Jumper supports different topologies, but not built-in. As for collisions, I'm afraid you need to have all objects 9 times in the Bump world, and keep them up-to-date somehow (probably via query and repositioning). That, or modify Bump (or make your own) to add support for wrapping.
User avatar
BrotSagtMist
Party member
Posts: 604
Joined: Fri Aug 06, 2021 10:30 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by BrotSagtMist »

Wrap everything into modulo.
Like Tile[X%Screensize]
Consider that the real position of objects doesnt matter at all that way.
A block being at 1500 will collide with a block at 500 as long as the collision math includes a modulo 1000.
obey
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by pgimeno »

@BrotSagMist Can you give a very simple example of what you just said? Something like the typical rectangle-rectangle intersecting test, using modulo everywhere. Because I'm having trouble understanding how e.g. comparisons would work on coordinates with the modulo applied.
User avatar
BrotSagtMist
Party member
Posts: 604
Joined: Fri Aug 06, 2021 10:30 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by BrotSagtMist »

I only used this for tiles and point objects, rectangles will make this complicated again.
obey
JimOfLeisure
Prole
Posts: 9
Joined: Wed Dec 29, 2021 8:01 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by JimOfLeisure »

You could alternately allow the player and enemies to have infinite coordinates and relocate parts of the map. The map would always have to be bigger than the viewport, of course.

If you need e.g. long-tailed enemies to wrap around, their tails could be drawn with a modulus function, but if you need to check collisions you'd need to modulus the potential colliding wrapping entities, too.

For my bumpy road simulation/game I'm procedurally generating a rolling surface. There are just a handful of ground objects, and their coordinates are destroyed when offscreen to the left and recreated to exist on the right.

If I had a repeating terrain I could just translate the coordinates instead of regenerating.

Not the best code ever, but if you want to see it: https://github.com/JimOfLeisure/bumpy-r ... ground.lua . Ground:load() creates the ground sections, and new_ground_section() generates the polygon and physics object for the new ground. In this case it's procedurally generated based on the X coordinate, but again this could just move an existing shape to new coordinates, too. The Grount:update() function checks to see if a section is far enough to the left to be 'moved' to the right.
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by darkfrei »

ReFreezed wrote: Sat Jan 01, 2022 1:49 pm There's no magical solution.
Maybe some shader for it?
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by grump »

darkfrei wrote: Wed Jan 12, 2022 9:28 pm
ReFreezed wrote: Sat Jan 01, 2022 1:49 pm There's no magical solution.
Maybe some shader for it?
Hah, you fools! There is a magical solution, and it was SHADERS all along!
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to program action game in a wrapping world? (2D torus)

Post by pgimeno »

I hope darkfrei was being sarcastic, but with Poe's law, you never know :)
Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests