0

EDIT: I've tried this with Perlin Noise with no success, then with Voronoi diagrams, and now I'm editing the question to reflect the issues I had with Perlin Noise, trying again.


I'm developing a game in Unity and trying to build a map generator that is capable of creating random maps like the Earth, on a 2D tilemap. The map should contain 2 types of tiles (let's call them grass and ground), while the grass should be the "main" tile, and there should be islands of ground on top of the grass.

This was already asked here. My purpose is to create something like the second picture in the question (that picture is showing water and grass, but it doesn't really matter).

This blog post suggested a simple way to fill a map (2d array) with Perlin Noise values (float numbers between 0-1), which I did. Eventually each value was rounded to 0 or 1 to present a grass or ground tile.

What I can control now is the frequency of the noise, but it's not enough.

The map generated by the code below: (frequency of 0.3) enter image description here

The problems with this method:

  1. No randomness. I know Perlin Noise is NOT a random function, so how can I add random factors to generate a different map each time?
  2. How can I control the number of islands (e.g.: with a factor that can determine "more islands" or "less islands", not an approx. number)?
  3. How can I control the size of each island (again, with a factor. I don't care about exact size)?

My code: (C#)

using System;
using UnityEngine;
using UnityEngine.Tilemaps;
using Random = UnityEngine.Random;

namespace TankMayhem {

    public class GroundTilemapGenerator : MonoBehaviour {

        private const string TilesPath = "Tiles";
        private Tilemap tilemap;
        private TileBase[] possibleTiles = new TileBase[2];

        private void Awake() {
            tilemap = GetComponent<Tilemap>();
            var tiles = Resources.LoadAll<Tile>(TilesPath);

            possibleTiles[0] = Array.Find(tiles, tile => tile.name == "ground");;
            possibleTiles[1] = Array.Find(tiles, tile => tile.name == "grass");

            int i;
            int j;
            int[, ] map = new int[tilemap.size.x, tilemap.size.y];

            const float Frequency = 0.3f;
            PerlinNoiseCave(map, Frequency);

            float[] probabilities = new float[2];

            foreach (var position in tilemap.cellBounds.allPositionsWithin) {
                i = position.x;
                j = position.y;

                var tile = possibleTiles[map[i, j]];
                tilemap.SetTile(position, tile);
            }
        }

        private static int[, ] PerlinNoiseCave(int[, ] map, float frequency) {
            for (int i = 0; i < map.GetUpperBound(0); i++) {
                for (int j = 0; j < map.GetUpperBound(1); j++) {
                    // Generate a new point using Perlin noise, then round it to a value of either 0 or 1
                    map[i, j] = Mathf.RoundToInt(Mathf.PerlinNoise(i * frequency, j * frequency));
                }
            }
            return map;
        }
    }
}
lihail
  • 59
  • 7
  • 1
    Are you dead-set on using Voroni diagrams for this? Because I would do this with Perlin Noise and control the ratio of grass to soil by picking the cutoff value between one and the other. But I don't want to claim that this isn't possible to do with Voroni diagrams. I don't have enough experience with them to judge that. – Philipp Mar 27 '20 at 11:22
  • Well I've tried with Perlin Noise but there were 2 problems: 1. The generated maps were not of islands but more of single tiles as I said. 2. I didn't manage to add random element to the map generation. So I've switched to Voronoi. So far it's better, but not perfect yet. – lihail Mar 27 '20 at 11:29
  • It sounds like you were using a mix of frequencies of noise too high for your needs. Bringing this down to fewer, bigger, blobbier islands should be just a matter of tuning your noise parameters. Adding an offset or re-shuffling your permutation table can add randomization. I'd second Philipp that noise looks like what you want, and you should consider editing your question to show your problems with using noise so we can help you solve them. – DMGregory Mar 27 '20 at 11:37
  • But if you want help with your voronoi implementation, you should show us your code. It looks like you still have a bug in the code that determines the nearest cell, leading to those diagonal artifacts. – DMGregory Mar 27 '20 at 12:11
  • Maybe. Added the code. – lihail Mar 27 '20 at 14:32
  • I'd really prefer to try and optimize/fix the current code with Voronoi, because I already tried Perlin, and rewriting the map generation code for the third time would be a bummer :/ – lihail Mar 27 '20 at 14:37
  • Like @DMGregory said, it sounds like you just had the scale wrong in your Perlin implementation. You should just be able to use your first code-set, and just tweak that single value. – Josh Eller Mar 27 '20 at 17:08
  • Code should always be shared inside your question itself, not via an external link that can rot. – DMGregory Mar 27 '20 at 17:10
  • Thank you for your input guys. Edited the question to show the Perlin Noise I'm having. Please look at it again :) – lihail Mar 28 '20 at 21:40
  • @DMGregory could please you explain what you meant in the 3rd comment? The only noise parameter I have is the frequency. Josh what do you mean by scale? – lihail Mar 30 '20 at 11:08
  • Don't forget to search for existing Q&A that covers your topic. Josh is also talking about the frequency. – DMGregory Mar 30 '20 at 11:10
  • @DMGregory that helped A LOT, thanks! Eventually I didn't manage to answer the questions I asked, but what I've managed to achieve is good enough. – lihail Mar 31 '20 at 14:51

0 Answers0