Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Following up on my previous post, I found a wonderful port of LibNoise for XNA. I've been working with it for about 8 hours straight and I'm tearing my hair out - I just can not get maps to tile, I can't figure out how to do this.

Here's my attempt:

            Perlin perlin = new Perlin(1.2, 1.95, 0.56, 12, 2353, QualityMode.Medium);
        RiggedMultifractal rigged = new RiggedMultifractal();

        Add add = new Add(perlin, rigged);

        // Initialize the noise map
        int mapSize = 64;
        this.m_noiseMap = new Noise2D(mapSize, perlin);
        //this.m_noiseMap.GeneratePlanar(0, 1, -1, 1);

        // Generate the textures

        this.m_noiseMap.GeneratePlanar(-1,1,-1,1);
        this.m_textures[0] = this.m_noiseMap.GetTexture(this.graphics.GraphicsDevice, Gradient.Grayscale);

        this.m_noiseMap.GeneratePlanar(mapSize, mapSize * 2, mapSize, mapSize * 2);
        this.m_textures[1] = this.m_noiseMap.GetTexture(this.graphics.GraphicsDevice, Gradient.Grayscale);

        this.m_noiseMap.GeneratePlanar(-1, 1, -1, 1);
        this.m_textures[2] = this.m_noiseMap.GetTexture(this.graphics.GraphicsDevice, Gradient.Grayscale);

The first and third ones generate fine, they create a perlin noise map - however the middle one, which I wanted to be a continuation of the first (As per my original post), is just a bunch of static.

How exactly do I get this to generate maps that connect to each other, by entering in the mapsize * tile, using the same seed, settings, etc.?

share|improve this question

1 Answer 1

Here's how I've been handling it.

1: use the same generator. This is not really optional. You need the same noise function if you want to generate seamless noise between textures, chunks, etc. The seed and other variables should NOT be modified outside of the initial startup.

2: Continue on with incrementing the X/Y/Z in relation to your first texture.

For example... lets say you are creating 2 64x64 pixel textures side by side. Your first texture is going to look something along the lines of...

for(int y = 0; y < 64; y++)
    for(int x = 0; x < 64; x++)
        noiseArray[y * 64 + x] = generator.GetValue(x, y, 0);

Now... we have that generated but what happens for our second texture? Simple! Just continue boosting x and y.

noiseArray[y * 64 + x] = generator.GetValue(x, y + 64, 0);
//this texture is to be placed at y++ from first one

Now.. that's all well and good but especially if you need large maps, this may not be your best approach. Personally I'd consider each texture as taking up 1 coord. Therefor each pixel, block or however you want to think of it inside that texture is going to be 1/Dimensions.X or 1/Dimensions.Y

Simply alter your noise function (or output returned from it) so that it will accept these much smaller increments.

Hope that helps.

Here's a very, very basic bit of code I whipped up for a noisemap test in XNA.

    Texture2D One, Two;
    Point Dimensions = new Point(500, 500);
void GenerateHeightmaps()
    {
        generator = new GeneralTerrain(new Random().Next(int.MaxValue / 2));
        One = GenerateTexture(new Vector3(0, 0, 0));
        Two = GenerateTexture(new Vector3(0, 1, 0));
    }
    Texture2D GenerateTexture(Vector3 worldLocation)
    {
        Color[] noise = new Color[Dimensions.X * Dimensions.Y];
        for (float x = 0; x < Dimensions.X; x++)
            for (float y = 0; y < Dimensions.Y; y++)
            {

                int cval = GenerateHeight(worldLocation,
                    new Vector2(x, y));
                noise[(int)(y + x * Dimensions.Y)] = new Color(cval, cval, cval);
            }
        Texture2D text = new Texture2D(GraphicsDevice, Dimensions.X, Dimensions.Y);
        text.SetData(noise);
        return text;
    }
    int GenerateHeight(Vector3 worldLocation, Vector2 blockLocation)
    {
        Point loc = new Point((int)(blockLocation.X + worldLocation.X * Dimensions.Y),
            (int)(blockLocation.Y + worldLocation.Y * Dimensions.Y));
        return generator.GetData(loc.X, loc.Y);
    }




    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin();
        spriteBatch.Draw(One, Vector2.Zero, Color.White);
        spriteBatch.Draw(Two, new Vector2(Dimensions.Y + 1, 0), Color.White);
        spriteBatch.End();
        base.Draw(gameTime);
    }

And the Simple GeneralTerrain class to configure the generator

public class GeneralTerrain
{
    Perlin generator;
    public GeneralTerrain(int seed)
    {
        generator = new Perlin();
        generator.Seed = seed;
        generator.NoiseQuality = NoiseQuality.Standard;
        generator.OctaveCount = 5;
        generator.Frequency = .01;
    }
    public int GetData(double x, double y)
    {
        return (int)(generator.GetValue(x, y, 0) * 128 + 100);
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.