Random Generation Issues

Started by
3 comments, last by Silamoth 8 years, 2 months ago

So I'm not an incredibly experienced programmer, but I know a thing or two, so I've been working on a little game that I don't really know what will happen with. It'll likely just end up being me messing around. One of the things I'm trying to implement is random terrain generation. I have it sort of implemented, but it's really...weird. Just so you know, it's written in C# with Monogame, and I'm using Visual Studio 2013 Express at the moment. Here's the code:


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;

namespace Fantasy_RPG
{
    class Tile
    {
        List<Texture2D> textureList;

        Texture2D tileTexture;

        const int TileWidth = 64;
        const int TileHeight = 64;

        private Vector2 position;

        public Tile(ContentManager content, Vector2 position)
        {
            this.position = position;

            textureList = new List<Texture2D>();
            LoadTextures(content);
            Generate();
        }

        void LoadTextures(ContentManager content)
        {
            textureList.Add(content.Load<Texture2D>("My Sprites/Terrain/Grass1"));
            textureList.Add(content.Load<Texture2D>("My Sprites/Terrain/Grass2"));
        }

        void Generate()
        {
            Random random = new Random();

            int x = random.Next(0, textureList.Count);
            Console.WriteLine(x);

            for (int i = 0; i < textureList.Count; i++)
            {
                if (x == i)
                {
                    tileTexture = textureList[i];
                    Console.WriteLine(i);
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(tileTexture, position, Color.White);
        }
    }
}


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;

namespace Fantasy_RPG
{
    class TileGenerator
    {
        private List<Tile> tiles;

        public TileGenerator(ContentManager content)
        {
            tiles = new List<Tile>();
            Populate(content);
        }

        void Populate(ContentManager content)
        {
            for (int x = 0; x <= 1440; x += 64)
            {
                for (int y = 0; y <= 900; y += 64)
                {
                    tiles.Add(new Tile(content, new Vector2(x, y)));
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Tile tile in tiles)
            {
                tile.Draw(spriteBatch);
            }
        }
    }
}

This is then drawn properly in my Main class, but I don't think you'll want more code to read through smile.png.

So this sort of works, but it's more like chunks. The way I have it right now, there are two textures: a light green and a dark green texture. The background is usually dominated mostly by one, with chunks of the other mixed in. Oddly enough, if I comment out the


Console.WriteLine(x);

and


Console.WriteLine(i);

lines in the Tile class, it randomly makes the entire background one of the colors. If I comment out either of these lines, it is either entirely dominated by one color or just about completely dominated by one color more so than it normally is. I know enough about programming to know that random generation is really pseudo-random and based on time, so I've deduced that that must be why those lines affect it. However, my question now is, how can I fix this to make it work to be fully random, regardless of time impacted by console output lines I was using for debugging?

Thanks in advance!

Advertisement

The Generate() function appears to be malformed.

Put a breakpoint at the start of it and walk through it with the debugger and look at what it does. If this behavior is intentional then you certainly don't need a loop. I'd also recommend making the randomizer a static member or else placing it elsewhere and passing it in to the function so that you aren't creating a new randomizer object every time the function is called.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

You need to create a single instance of Random(), and then call Next() on it multiple times, once for each tile. That's the appropriate way to use a PRNG: Seed it once, and pull numerous random numbers from it.

My quick recommendation would be to add an int parameter to the Tile constructor and to the Tile.Generate() method, pass that parameter from the constructor to Generate() and use it within Generate() in place of x, and then from within the TileGenerator.Populate() method, create a single new instance of Random(), passing a call to Next() as the additional parameter that you just added to the Tile constructor.

"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke

Maybe I am missing something but couldn't you simplify Generate()? Like so:


void Generate()
        {
            StaticRandom random = StaticRandom::Instance();

            int x = random.Next(0, textureList.Count);
            Console.WriteLine(x);
            tileTexture = textureList[x];
        }

I added the StaticRandom stuff because, like Andy said, you're going to end up with a good portion of Tiles with the exact same seeds; since you'd be calling Random() many times within mere moments of one another.

Well, after taking a long break from this project, reading what you guys said, and looking back at my code, I have absolutely no clue what in the world I was doing when I wrote that code. I mean, seriously, the code looked like it was written by a newbie. Thanks for the help. I guess I just needed someone to make me realize how stupid I was being. :)

This topic is closed to new replies.

Advertisement