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






