Let me generate that for you

Note: This post was originally published in September 2015

More than a decade ago, back when I was about 13-14, I created an online browser and text-based game. Built with crude PHP (barely version 5.0 if I remember correctly). The name of the game was Vega: Intergalactic (previously Anacal) and its goal was to dominate the universe. All new players started with just a single planet, and they needed to extract resources, build ships, colonize other planets, and engage in wars or alliances. With about 150 active players (players who logged in at least once a day), I thought it to be quite a success.

Then, based on feedback from some very bright, friendly and competent players I wanted to build version two, so to speak. But as these things go, I never did, and pretty soon the idea of a text-based game was obsolete, if it wasn't already.

I tried several times to restart this project, but never really did. I had design and game play documents written and all. So, I thought, why not try it again? But this time with technologies not yet available a decade ago; full-duplex client-server communication, 2D or even 3D maps of clusters of stars, and more. And it would be even better if this world was procedurally generated; no hard-coded 'levels' or anything like that, but repeatable noise and an essentially infinite universe.

Procedural generation

I looked into procedural generation several times in the past, but never really did anything with it. Of course I decided to change that, and build a very simple 'generator' wrapper around the excellent simplex-noise Node.JS module. That module generates simplex noise, and improved version of Perlin noise.

The result was vesuvius; a small 'points map' generator using simplex noise. Its operation is simple; create a generator with a seed value, set some options, and generate the map.

Vesuvius

Vesuvius supports 2D and 3D simplex noise (just like simplex-noise, the module it uses). It simply checks the value of all coordinates within the box (see boxSize below), and if the value exceeds the threshold, the coordinates are added to an array. When all points in the box are checked, it returns the map of coordinates.

You can install vesuvius through npm:

npm install vesuvius  

Next, require the Generator in your module and create a Generator instance with a specified seed (an integer, 4443 below):

var Generator = require('vesuvius').Generator;  
// Instantiate a Generator without options...
var generator = new Generator(4443);

// And add them later
generator.dimensions(3);  
generator.boxSize(10);  
generator.threshold(0.75);  
// Or you can instantiate the Generator with options directly
var generatorOptions = {  
    "dimensions": 3,
    "boxSize": 10,
    "threshold": 0.75
};

var generator = new Generator(4443, generatorOptions);  

Then all you have to do is to generate the map:

var map = generator.generate();  

This would result in an array something akin to the one below (truncated).

[
    {"x":0,"y":2,"z":3},
    {"x":0,"y":2,"z":6},
    {"x":0,"y":5,"z":8},
    {"x":0,"y":6,"z":1},
    {"x":0,"y":7,"z":0},
    {"x":0,"y":9,"z":4},
    {"x":1,"y":0,"z":3},
    {"x":1,"y":0,"z":4},
    {"x":1,"y":1,"z":2},
    {"x":1,"y":1,"z":8}
]

On-the-fly and JIT generation

I originally envisioned this to be the basis of the game's star generation, each point exceeding a certain threshold resembling a star. The downside of using this module is, the values are in essence still pre-generated, something I wished to avoid. (This would probably take noise generation to happen both on the server and client in a Just-In-Time (JIT) way)

Regardless, some might find this little module of some use, as it's also a good example of how one can use simplex noise.

Be sure to check out the module! Any tips or advice can always be mentioned in the project's GitHub issues :)

comments powered by Disqus