Grid-based spirals

Good for placing objects around a grid cell! Like this:

A spiral spanning a 9x9 square grid. Points are numbered and lines show the path.
(try a newer browser for an interactive demo!)(enable JavaScript for an interactive demo!)
(click to interact)
Click/tap to select point

You give the function a grid XY and it tells you where the next point should be to have it go in a spiral.

Story time

Once upon a time, before I was known for much of anything, I used to do all sorts of odd jobs, including plugins for Minecraft servers.

The tasks usually involved making various plugins work together or extending plugins to do something new. Small work, small pay.

At one point, some peeps I knew were making a new server based on Skyblock, a game mode where you start on a tiny flying island and use "renewable" resources (like wood logs or items that drop from naturally spawning creatures) to build yourself a base and generally progress.

They faced a few challenges with an existing plugin, one of which was the plugin's placement of islands - a part of the appeal in playing this mode online is seeing other people do their thing on their island nearby,

A simple drawing depicts a person is standing on a classic Skyblock island and waving towards a nearby island. There, another person is jumping and waving their hands.
(note: distance not to scale)

but the plugin both placed islands too far apart and in no apparent pattern, which meant that most of the times a player would only have one "neighbour", and that would usually be an abandoned island as the mode does take some patience.

In my implementation, the islands were placed closer by in this kind of spiral pattern, and abandoned islands would eventually be recycled to make space for new ones, so the players would always see something happening around them.

As larger server networks caught on the Skyblock trend, the server became a much smaller community and eventually shut down, but some ideas remain.

The code

So it's just this, really (in JS):

function spiralNext(x, y) {
    var r = Math.max(Math.abs(x), Math.abs(y));
    if (y == r) {
        // bottom edge, going right
        return { x: x + 1, y: y };
    } else if (y == -r) {
        // top edge, going left until we hit the top-left corner
        if (x != -r) return { x: x - 1, y: y };
    }
    if (x >= 0) {
        // right edge, going up
        return { x: x, y: y - 1 }; 
    } else {
        // left edge, going down
        return { x: x, y: y + 1 };
    }
}

There might be a cleaner way to write this.

Diamond/rotated?

This one's better in terms of distance to the center:

A diamond-shaped spiral inside a 9x9 area. Points are numbered and lines show the path.
(try a newer browser for an interactive demo!)(enable JavaScript for an interactive demo!)
(click to interact)
Click/tap to select point

And the code looks slightly nicer!

function spiralNext(x, y) {
    var r = Math.abs(x) + Math.abs(y);
    if (y == r) return { x: x + 1, y: y };
    if (x > 0) {
        if (y > 0) {
            return { x: x + 1, y: y - 1 };
        } else {
            return { x: x - 1, y: y - 1 };
        }
    } else {
        if (y < 0) {
            return { x: x - 1, y: y + 1 };
        } else {
            return { x: x + 1, y: y + 1 };
        }
    }  
}

And that's about it.

Thanks for reading!

Related posts:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.