1
\$\begingroup\$

There seems to be a lot of posts about endlessly scrolling backgrounds on one axis, but not much for a 2-axis solution. As Josh Petrie suggested, I'm posting my approach as an answer to see if anyone can improve on it.

Game Requirements:

I'm creating a 2D game for iOS using SpriteKit and Swift, but this paradigm could work for any touch-screen platform. The game involves a player sprite exploring an infinite field of outer space from a top-down 2D perspective. They drag their finger on the screen to move with scrolling behavior similar to panning a map in the Google Maps or Apple Maps apps.

The player should be able to scroll in any direction along the X and Y axes indefinitely. The texture of the 2D space terrain could be generated and drawn programmatically. Or it could take a limited number of textures made by an artist and recycle those images repeatedly to produce the endless terrain.

Planets and other objects will be added to the map, so there will have to be a way to add these into the terrain as well. Initially, these objects can appear at random, but with a frequency that feels natural (i.e. you can't have too many planets or too few). Later, the location of planets will need to be retained so the player can revisit them. So a mapping system will have to be implemented eventually, and that data stored in memory. For now, that is not necessary but a solution that future-proofs against that necessity is preferred.

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

My Infinite Terrain Approach:

I have started with an approach that favors completing this task as soon as possible at the cost of performance optimization.

  1. Create an invisible node with a physics body and add a gesture recognizer. When players swipe the screen, it moves the invisible node.
  2. Make a textured sprite and add it as a child of the invisible node. The textured sprite is a one of several pre-made tiles that can be repeated to produce the endless terrain.
  3. Start with one central tile, then write a spawnTiles() function that surrounds the first tile on all sides with new tiles. You can call this function for any new tile to surround that tile with more new tiles. But since this will cause tiles to overlap with other tiles, you need a way for the tiles to know if another tile already exists on all of its sides.
  4. Add a small physics body that protrudes from each side of your tiles to act as a "sensor". When a sensor makes contact with another sensor, you know there is a another tile on that side. In the screenshot below, the green squares are sensors that lie on an open edge; the red squares are sensors that are contacting another sensor. (In production these sensors would be invisible).

    Screenshot of test

  5. Keep calling the spawnTiles() method until the screen is completely textured with a significant buffer beyond the frame of the screen. Now players can scroll the terrain and have the illusion that their player sprite is moving through space.

  6. Continuously measure the distance from each tile to the center of the screen. When the edge of the terrain is too close to the center of the view, generate new tiles along the edges so the player never sees any holes in the terrain. If a tile gets too far from the view, destroy that tile to conserve memory.

Analysis:

This is my first SpriteKit game project and I am still getting familiar with the API and libraries. This approach seemed like the quickest way to the terrain working. I expected the iPhone 6 & 7 series (my target platforms) would be sufficient to absorb the extra overhead. However, this feels like a clunky and inelegant approach. It also appears to be rather processor-intensive.

When I ran the scene pictured above in the iPhone 7 simulator, the debugger showed that the CPU was holding at just under 100%. Granted, I'm currently using an arbitrary 1500 × 2668 texture for the tiles which is much larger that I would end up using once I move beyond prototyping.

Still, this approach uses a lot of physics bodies which seems unnecessary and I believe are rather expensive. The whole idea of creating additional objects to detect the tile edges also seems like a very kludgy way to do things. I feel like there must be a better way to handle this sort of two-axis scrolling.

In summation, here are what I see as the pros and cons of this approach.

PROS

  • Super fast & easy to get the scrolling behavior working
  • Easy to tweak the scrolling behavior by adjusting physics body properties

CONS

  • Greater overhead due to extra physics bodies
  • Every tile requires six additional node objects to act as sensors
  • Dealing with the physics body interactions and juggling the sensor nodes creates additional complexity, potentially leading to technical headaches (as my Stack Overflow post illustrates)
\$\endgroup\$
  • \$\begingroup\$ Good to see you found a path forward. \$\endgroup\$ – ErnieDingo Jun 20 '18 at 20:27

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.