pythonperlin-noise

Chunks not connected


Here is my code:

def generate(octaves):
    global world, xpix, chunkSize #set globals (for other references in the rest of the script etc)
    chunkSize = (12, 12)
    xpix, ypix = chunkSize[0], chunkSize[1]
    world = []
    noise1 = PerlinNoise(octaves=octaves, seed=seed) #make noise
    
    for i in range(xpix): # make list for drawer to use
        row = []
        for j in range(ypix):
            noise_val = noise1([(i / xpix) + chunkCoordX * xpix, (j / ypix) + chunkCoordY * ypix])

            if noise_val <= .05:
                tiletoplace = tileclassdata.water
            elif noise_val <= .13:
                tiletoplace = tileclassdata.sand
            else:
                tiletoplace = tileclassdata.grass
            placed_tile = classes.tile(tiletoplace, i, j)
            row.append(placed_tile)
        world.append(row)

I am trying to make the chunks I generate connect. For example:

I could have a chunk at 1,-4 and one at 0,-4. But this is what they'd look like:

Chunk at 1,-4

Chunk at 0, -4

I would like them to connect so that I can get things like islands generating across chunks instead of just have random blobs scattered around my game's map.

I have tried refactoring the sum for working out the chunks position in the perlin-noise map but I have not been able to devise a sum that figures it out.


Solution

  • Quick and dirty example of the idea in the comments:

    import numpy as np
    from scipy import ndimage
    import seaborn as sns
    
    def generate_landscape(field_size: int, flatness: int, magnitude=255):
        """ Generates an islandish landscape, given:
    
        Args:
            field_size: size of the resulting numpy array
            flatness: very large number will result in a completely flat terrain;
                1 will result in every spot being drawn at random
        """
        field = np.random.binomial(1, 1 / flatness, size=(field_size, field_size)) \
            * np.random.randint(low=0, high=magnitude, size=(field_size, field_size))
        mask_size = max(int(flatness ** 0.5), 1)
        return ndimage.gaussian_filter(field, mask_size)
    
    sns.heatmap(generate_landscape(32, 10))
    

    Example output:

    enter image description here

    After that, I'd take a desired water/sand %%, calculate quantiles and apply the threshold.