A procedurally generated city (2d)-Part 2 : The city generator

In the previous post we got our L-System nodes ready and we went through a quick 3 step iteration to generate a small city. This was just theory though, so let's create some code which actually generates this city.

For this, I have the CityGenerator class, which needs to have a method which will allow us to create a city with certain restrictions.

public class CityGenerator{

    CityGeneratorOptions opt = new CityGeneratorOptions();
    int mapWidth, mapHeight;

    public Array<CityNode> create(int iterations, int width, int height){
        Array<CityNode> nodes = new Array<CityNode>();
        this.mapWidth = width;
        this.mapHeight = height;
        Cityblock seed = new CityBlock(0, 0, width, height, opt);

        nodes.add(seed);
        Array<CityNode> temp = new Array<CityNode>();
        for (int i = 0; i < iterations; i++){
            step(nodes, temp);
            nodes.clear();
            nodes.addAll(temp);
            temp.clear();
        }
    }

    private static void step(Array<CityNode> input, Array<CityNode> output){
        for(CityNode node : input)
            node.grow(output);
    }
}

You will notice that just like in previous post, we are using the opt variable, which is a class which just contains a set of restrictions on how big the blocks and roads can be, if you are wondering how it looks, this is it:

public class CityGeneratorOptions{  
        public int minBldWidth;
        public int minBldHeight;
        public int minBlockWidth;
        public int minBlockHeight;
        public int minRoadWidth;
        public int maxRoadWidth;

        public CityGeneratorOptions(){
            this(3, 4, 7, 4, 2, 6);
        }

        public CityGeneratorOptions(int minBldWidth, int minBldHeight, int minBlockWidth, int minBlockHeight, int minRoadWidth, int maxRoadWidth){
            this.minBldWidth = minBldWidth;
            this.minBldHeight = minBldHeight;
            this.minBlockWidth = minBlockWidth;
            this.minBlockHeight = minBlockHeight;
            this.minRoadWidth = minRoadWidth;
            this.maxRoadWidth = maxRoadWidth;
        }
    }

That was pretty simple!
Our CityNodes should be laid all around the place now, let's see how they look. Here's an applicationListener to see the city layout with libgdx (not actual code, I just wrote this...might be some spelling error in there)

public class MyApp extends ApplicationAdapter(){

    ShapeRenderer renderer;
    Array<CityNode> nodes;
    OrthographicCamera camera;

    public void create(){
        renderer = new ShapeRenderer();
        nodes = new CityGenerator().create(3, 100, 60);
        camera = new OrthographicCamera();
        camera.setToOrtho2d(false, 100, 60); //so that our city fills completely the screen
    }

    public void render(){
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);

        for(CityNode node : nodes){
            shapeRenderer.setColor(node.color);
            shapeRenderer.rect(node.bounds.x, node.bounds.y, node.bounds.width, node.bounds.height);
        }

        renderer.end();
    }
}

Here's a screen of a 3 iterations process with a size of 100x60

And another with a 7 steps iteration:

Not too bad, not too bad.

comments powered by Disqus