game_space_world_gen_world_generator.js

import Color from "../../../../util/color/color.js";
import ColorGradient from "../../../../util/color/color_gradient.js";
import NoiseStack from "../../../../util/noise/noise_stack.js";
import NoiseStackLayer from "../../../../util/noise/noise_stack_layer.js";
import NoiseProcess from "../../../../util/noise/noise_process.js";
import NoiseSequence from "../../../../util/noise/noise_sequence.js";
import SimplexNoise from "../../../../util/noise/simplex_noise.js";
import ChunkUnit from "../../chunk/unit/chunk_unit.js";

/**
 * @module WorldGenerator
 * @fileoverview Contains WorldGenerator class.
 */

/**
 * @class
 * Custom generator for worlds.
 */
class WorldGenerator {
    /**
     * Create a new world generator.
     * @param {number} seed Seed to use for generation
     * @constructor
     */
    constructor(seed = 1) {
        //.seed = Math.random() * 4096;
        this.seed = 3047;

        const stack = new NoiseStack([
            new NoiseStackLayer(this.seed, 2, 2, .5),
            new NoiseStackLayer(this.seed, 100, 100, 16, (x, y, val) => {
                if (val > 0.5) {
                    val *= 1.1;
                    if (val > 1)
                        val = 1;
                }

                return val;
            }),
            new NoiseStackLayer(this.seed, 10, 10, 3, (x, y, val) => {
                return Math.pow(val, 2);
            }),
            new NoiseStackLayer(this.seed, 2, 2, 1, (x, y, val) => {
                if (val > 0.5)
                    return Math.pow(val, 2);

                return val;
            })
        ], 4);

        this.noise = new NoiseSequence([
            new NoiseProcess((x, y, val, data) => {
                const v = (Math.pow(data.noise.get(x, y), 2) * 2 - 1) * 6;

                return {
                    x: x + v,
                    y: y + v,
                    val: val
                };
            }, {
                noise: new SimplexNoise(this.seed, 100, 100)
            }),
            new NoiseProcess((x, y, val, data) => {
                return {
                    x: x,
                    y: y,
                    val: stack.get(x, y)
                };
            }),
            new NoiseProcess((x, y, val, data) => {
                return {
                    x: x,
                    y: y,
                    val: Math.pow(val, Math.pow(val, data.noise.get(x, y)))
                };
            }, {
                noise: new SimplexNoise(this.seed + 1, 750, 750)
            })
        ], 1);

        this.gradient = new ColorGradient({}, true);
        this.gradient.set(0, new Color(100, 150, 255));
        this.gradient.set(0.68, new Color(170,189,230));
        this.gradient.set(0.69, new Color(240, 228, 204));
        this.gradient.set(0.72, new Color(112, 163, 88));
        this.gradient.set(0.81, new Color(120, 105, 92));
        this.gradient.set(0.835, new Color(133, 133, 133));
        this.gradient.set(0.89, new Color(120, 120, 120));

        this.oceanGradient = new ColorGradient();
        this.oceanGradient.set(0, new Color(100, 150, 255));
        this.oceanGradient.set(0.1, new Color(81, 92, 189));
    }

    /**
     * Get the height value at a specified position.
     * @param {number} x Position along x-axis
     * @param {number} y Position along y-axis
     * @param {number} scale Scaling for generation
     * @returns {number} Height value
     */
    getVal(x, y, scale) {
        return this.noise.get((x + 1E10) / scale, (y + 1E10) / scale);
    }

    /**
     * Generate and get a chunk unit at a specific position.
     * @param {Chunk} chunk
     * @param {number} x Position along x-axis
     * @param {number} y Position along y-axis
     * @param {number} scale Scaling for generation
     * @returns {ChunkUnit} Chunk unit that was generated
     */
    get(chunk, x, y, scale) {
        const val = this.getVal(x, y, scale);
        let color = this.gradient.get(val);

        const ground = new ChunkUnit({
            chunk: chunk,
            x: x,
            y: y,
            sprite: color
        });

        if (val < 0.68)
            ground.invisible = true;
        else
            ground.canWalkOn = true;

        return ground;
    }
}

export default WorldGenerator;