#random #map #world #generator #generation #wasm #command-line-tool

bin+lib world-map-gen

Command line tool and library to generate random game world maps for both Rust and WebAssembly

2 releases

0.1.1 May 18, 2019
0.1.0 Jan 25, 2019

#959 in Game dev

MIT license

70KB
1.5K SLoC

Random World Map Generator

crates.io npm version documentation CI on Linux and macOS CI on Windows

world-map-gen is a CLI tool and library for Rust and WebAssembly. It provides functionality to generate a random world map for games like a retro tactical simulation game. A generated map consists of cells. Each cell has its altitude and kind (sea, town, plain, forest, mountain, ...).

Try it on browser by visiting project page or on your terminal by installing CLI app.

Screenshot:

Example of generated 120x120 map in 3D

screenshot of 3D map

Example of generated map in 2D

screenshot of 2D map

Example of generated map in terminal (iTerm2)

screenshot of map in terminal

This project is my personal practice to create a Rust library which works fine as both normal Rust library and WebAssembly library, which is a bit more practical than awesome Rust+Wasm tutorial.

I leaned the algorithm to generate world maps from this small book and implemented it (with small improvements).

Installation

Try random map generation at project page

gh-page of this project is a demo page for showing how this package works. The demo site is constructed with TypeScript, WebAssembly (thanks to wasm-pack, wasm-bindgen) and webpack. The source code of the page is in www/ directory.

As Rust library

This library is shipped as a crate. It can be installed with cargo package manager.

Please add a dependency in your project's Cargo.toml and run cargo build.

world-map-gen = "0.1"

Rust compiler supporting Rust 2018 edition is necessary.

As WebAssembly library

This library built as WebAssembly is shipped as npm package.

npm install --save world-map-gen

The package contains optimized .wasm binary, .js JS file to glue between Wasm and JS, and .d.ts type definition file to use this package with TypeScript.

As command line tool

Using cargo, please build CLI tool from source.

cargo install world-map-gen

It builds ~/.cargo/bin/world-map-gen.

Usage

Rust library

Rust library provides some modules to handle a world map as one board filled up with cells.

  • land: land::Land struct represents each cell in a board
  • board: board::Board struct represents one world map. The struct is JSON serializable with serde_json
  • draw: Helper to draw a board to terminal or as JSON
  • gen: A random world map generator to build board::Board struct. It provides algorithms for 3 kinds of resolutions; low, middle, high
  • error: Error type which may be returned from a map generator

Please read the documentation for more details. And CLI code is a good live example to know the usage.

extern world_map_gen;

use world_map_gen::RandomBoardGen;

// Create generator instance with default random number generator
let mut generator = RandomBoardGen::default();

// Generate 40x40 random world map. Map resolution (low, middle, high) is automatically
// determined by its width and height here.
//   - Low: width and height are less than 15
//   - Middle: width and height are less than 120
//   - High: Otherwise
let board = generator.gen_auto(40, 40);

// Iterate each cells per row
for (i, row) in board.rows().enumerate() {
    println!("Row: {}", i);
    for cell in row {
        // cell is a world_map_gen::land::Land instance

        // Lands are categorized with kind (e.g. Sea, Plain, Forest, Mountain, ...)
        println!("Kind: {:?}", cell.kind);

        // Each cell as its altitude. For example, sea's altitude is lower and mountain's is
        // higher
        println!("Altitude: {}", cell.altitude);
    }
}

WebAssembly library

www/ directory is a good live example to show how to use this package in TypeScript and WebAssembly. It is hosted at gh-pages.

The npm package contains world_map_gen.wasm and world_map_gen.js. The world_map_gen.js is an entry point. Bundler which support WebAssembly like webpack handles the .wasm file properly when your code imports world-map-gen package.

import { Generator, LandKind } from 'world-map-gen';

// Generate a new random map generator
const gen = Generator.new();

// Generate random 200x200 map
const board = gen.gen(200, 200);

for (let x = 0; x < board.width(); x++) {
    for (let y = 0; y < board.height(); y++) {
        // Get cell of specific position
        const cell = board.at(x, y);

        // Get land kind like Sea, Forest, Mountain, ...
        console.log('Kind:', cell.kind, 'at', x, y);

        // Check the cell is town
        console.log('  town?:', cell.kind === LandKind.Town);

        // Get altitude of the cell
        console.log('  Altitude:', cell.altitude);

        // Get color code of the cell as #rrggbb format
        console.log('  Color:', cell.color_code());

        // Get land legend
        console.log(' Legend:', cell.legend());
    }
}

// Get JSON representation of board
console.log(JSON.parse(board.as_json()))

Let's say this code is put as a file index.js.

As the entry point of your application, please ensure to use dynamic import. It is necessary because all .wasm code must be imported asynchronously.

import("./index")
  .catch(e => console.error("Error importing `index.js`:", e));

world-map-gen package also contains world_map_gen.d.ts for working with TypeScript. You don't need to write type definitions of APIs. TypeScript compiler automatically detects the .d.ts file.

Please ensure to use esNext for module resolution of TypeScript compiler. It translates TypeScript's import statements into ES Modules and webpack will handle them later.

{
  "compilerOptions": {
    "module": "esNext",
    // ...
  },
  // ...
}

CLI tool

Please read world-map-gen --help output to know the interface.

Each cell is represented with ██. And ANSI 256 colors are used for cell colors. Some terminal may not work properly. I'm testing this CLI tool on iTerm2.

By default, it gets terminal's width and height and uses entire terminal screen to show map. You may need to make font size smaller temporarily to show larger maps. Map's resolution is automatically determined from width and height by default. And you can specify them by command line options. And --json outputs a randomly generated map as JSON.

USAGE:
    world-map-gen [FLAGS] [OPTIONS]

FLAGS:
    -a, --altitude    Show altitude instead of squre as cell mainly for debug
        --help        Prints help information
    -j, --json        Output JSON-serialized result to stdout
    -V, --version     Prints version information

OPTIONS:
    -h, --height <INTEGER>       Board height in number of cells
    -r, --resolution <STRING>    Resolution of world map [possible values: low, middle, high]
    -s, --seed <INTEGER>         Seed for random number generator
    -w, --width <INTEGER>        Board width in number of cells

Development

Makefile provides useful scripts to develop this repository.

For debugging Wasm package from browser, please build this package with wasm-pack and --features wasm_debug.

License

Distributed under the MIT License.

Dependencies

~2–12MB
~140K SLoC