I am doing a school project and i am trying to make a Perlin Noise generated game map that is created each game at startup. I am doing the project in XNA 4.0 and have had no trouble programming in C# until now.

They teach pasal/Delphi at my school but I have started using c# after my teacher told me it was a better choice.

Here are some screenshots and the code i am using to make the perlin noise array.

I am using a 16x16 array of floating point variables to calculate the types of land on the map. For my testing i am using only grass, water and sand.

Screenshots: All of the results typically look like this.

Here is the code i am using: (I know its messy. I tried to keep it clean but after an hour or so of tinkering with the maths it has become a nightmare)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace RandomMapLib.MapGeneration { public static class PerlinNoise { #region fields static float[,] map; // 2d array with multiple octaves - i.e maps[octave][dimension1, dimension2] static int seed; static int seedCap = 10000; #endregion #region properties public static int Seed { get { return seed; } set { seed = (int)MathHelper.Clamp(value, 0, seedCap); } } public static int SeedCap { get { return seedCap; } set { seedCap = value; } } #endregion #region methods /// <summary> /// Generate a new random seed for the perlin noise generator /// </summary> public static void newSeed() { Random newSeed = new Random(); seed = newSeed.Next(0, seedCap); } /// <summary> /// Generates a random value between 0.0 and 1.0 to 4d.p for the point specified using the seed /// for this static class; /// </summary> /// <param name="x">the point on the x axis</param> /// <param name="y">the point on the y axis</param> /// <returns>the value generated with the seed</returns> public static float noise(float x, float y) { float n; Random random = new Random(); n = (float)random.Next(0,99)/100; return n; } /// <summary> /// Uses this classes noise function and applies simple smoothing to it /// </summary> /// <param name="x">the point on the x axis</param> /// <param name="y">the point on the y axis</param> /// <returns>the smooth noise for the point given in the [x, y] param</returns> public static float smoothNoise(float x, float y) { float corners; float sides; float centre; corners = (noise(x - 1, y - 1) + noise(x - 1, y + 2) + noise(x + 1, y - 1) + noise(x + 1, y + 1)) / 16; sides = (noise(x - 1, y) + noise(x, y - 1) + noise(x + 1, y) + noise(x, y + 1)) / 8; centre = noise(x, y) / 4; return corners + sides + centre; } /// <summary> /// Returns an interpolated smooth noise value /// </summary> /// <param name="x">x coord</param> /// <param name="y">y coord</param> /// <returns>smooth noise value</returns> public static float interpolatedNoise(float x, float y) { int intX = (int)x; float fracX = (float)x - intX; int intY = (int)y; float fracY = (float)y - intY; float v1, v2, v3, v4, i1, i2; v1 = smoothNoise(intX, intY); v2 = smoothNoise(intX + 1, intY); v3 = smoothNoise(intX, intY + 1); v4 = smoothNoise(intX + 1, intY + 1); i1 = MathHelper.SmoothStep(v1, v2, fracX); i2 = MathHelper.SmoothStep(v3, v4, fracY); return MathHelper.SmoothStep(i1, i2, fracY); } /// <summary> /// Gets a blended perlin point for the specified x,y coordinate for the number of octaves shown; /// </summary> /// <param name="x">the x coordinate</param> /// <param name="y">the y coordinate</param> /// <param name="persistance"> ||0 to 1|| --- the amplitude multiplier for each frequency</param> /// <param name="octaves">the number of frequencies being blended</param> /// <returns>a single point that is blended across all octaves</returns> public static float perlinNoise(float x, float y, float persistance, int octaves) { float total = 0; float p = persistance; float frequency; float amplitude; int n = octaves - 1; for (int i = 0; i < n; i++) { frequency = (float)Math.Pow(2, i); amplitude = (float)Math.Pow(p, i); total += noise(x * frequency, y * frequency) * amplitude; } return total; } #endregion } }

and my world object which uses the perlinNoise static class... --- It should be noted that the world object was working perfectly when i was using random noise to populate the map. so thats not really going to be broken, even though the code looks shocking. The TileManager class is pretty solid and i have had no problems with it.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Input; using RandomMapLib; using RandomMapLib.Tiles; using RandomMapLib.MapGeneration; namespace RandomMapTest { public class World : TileManager { float[,] map; public World(Game game, GraphicsDeviceManager gdm) : base(game, gdm) { map = new float[64, 64]; } protected override void LoadContent() { base.LoadContent(); int ArraySize = map.GetLength(0); Random rnd = new Random(); int type; for (int x = 0; x < ArraySize; x++) { for (int y = 0; y < ArraySize; y++) { map[x, y] = PerlinNoise.perlinNoise((float)x, (float)y, 0.5f, 3); } } spriteBatch = new SpriteBatch(GraphicsDevice); ContentManager Content = Game.Content; Texture2D tex = Content.Load<Texture2D>(@"map\mapTiles"); TileArray = new Tile[ArraySize, ArraySize]; for (int y = 0; y < ArraySize; y++) { for (int x = 0; x < ArraySize; x++) { map[x, y] = PerlinNoise.perlinNoise((float)x, (float)y, 0.5f, 3); if (map[x, y] < 0.5f) type = (int)TileType.Water; //else if (map[x, y] < 0.5) // type = (int)TileType.Sand; else type = (int)TileType.Grass; TileArray[x, y] = new Tile(tex, (TileType)type); TileArray[x, y].Position = new Point((x) * Tile.TileRes, (y) * Tile.TileRes); } } } public void generateMap() { int ArraySize = map.GetLength(0); Random rnd = new Random(); int type; for (int x = 0; x < ArraySize; x++) { for (int y = 0; y < ArraySize; y++) { map[x, y] = PerlinNoise.noise((float)x, (float)y); } } spriteBatch = new SpriteBatch(GraphicsDevice); ContentManager Content = Game.Content; Texture2D tex = Content.Load<Texture2D>(@"map\mapTiles"); TileArray = new Tile[ArraySize, ArraySize]; for (int y = 0; y < ArraySize; y++) { for (int x = 0; x < ArraySize; x++) { if (map[x, y] < 0.3f) type = (int)TileType.Water; else if (map[x, y] < 0.5) type = (int)TileType.Sand; else type = (int)TileType.Grass; TileArray[x, y] = new Tile(tex, (TileType)type); TileArray[x, y].Position = new Point((x) * Tile.TileRes, (y) * Tile.TileRes); } } } public override void Update(GameTime gameTime) { base.Update(gameTime); KeyboardState kb = Keyboard.GetState(); if (kb.IsKeyDown(Keys.Enter)) { PerlinNoise.newSeed(); generateMap(); } } public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { base.Draw(gameTime); } } }

If none of the above makes much sense its because i am really rushing through this to get to bed for much needed sleep .

Thanks for any feedback or even reading this shambles of a post,

Bryce

p.s i tried to upload the project but it exceeds 50mb so i thought there would be no point