Question

I am currently making a program to procedurally generate 2d terrain maps, with different technics such as perlin noise, simplex, voronoi, fractal noise, etc. on a size-defined image to be able to use it in my games requiring a 2d terrain.

I've come across the "Modelling fake planets" section of http://paulbourke.net/fractals/noise and I need to make it on a 2d texture, and not on a 3d world like it is explained.

Now I'm trying to

  1. create a line from point 'X' to point 'Y'
  2. That line will define a zone with a boolean value for left or right of the line to be "darker".
  3. Doing that for a number of iteration to create a texture.
  4. Using the RGB value of the final image to change stuffs such as forests, lakes, etc.

this would work this way:

overrides with this method below,

http://img35.imageshack.us/img35/24/islf.png

I used my high school maths powers to create a code sample but it's not really working...

Questions:

  1. How should i change it so it works instead of just being failing?
  2. Is there a simpler way than using what i am using?

Java file: if i need an example on how i will proceed, here it is:

package Generator;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import VectorialStuffs.Vector2;

public class Linear
{
    public static BufferedImage generateImage(Dimension dim, int iterations)
    {
        BufferedImage image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);

        //point X and point Y
        Vector2 pointX;
        Vector2 pointY;

        //difference between those
        Vector2 diff;
        Vector2 side;
        double slope;

        //random
        Random rand = new Random();
        boolean direction;              //the orientation of the dark zone. (left/right)

        for (int i = 0; i < iterations; ++i)
        {
            pointX = new Vector2(0, 0);
            pointY = new Vector2(0, 0);
            direction = rand.nextBoolean();
            System.out.println(direction);

            side = new Vector2(0, 0);   //there are 4 sides of the image.
            while (side.x == side.y)
            {
                side.x = rand.nextInt(3);   //0 - 1 - 2 - 3
                side.y = rand.nextInt(3);
            }

            switch(side.x)  //not the x coord, the X point! ;D
            {
                //x = random and y = 0
                case 0:
                    pointX.x = rand.nextInt(dim.width);
                    pointX.y = 0;
                break;
                //x = max and y = random
                case 2:
                    pointX.x = dim.width;
                    pointX.y = rand.nextInt(dim.height);
                break;
                //x = random and y = max
                case 1:
                    pointX.x = rand.nextInt(dim.width);
                    pointX.y = dim.height;
                break;
                //x = 0 and y = random
                case 3:
                    pointX.x = 0;
                    pointX.y = rand.nextInt(dim.height);
                break;
            }

            switch(side.y)  //not the y coord, the Y point! ;D
            {
                //x = random and y = 0
                case 0:
                    pointY.x = rand.nextInt(dim.width);
                    pointY.y = 0;
                break;
                //x = max and y = random
                case 2:
                    pointY.x = dim.width;
                    pointY.y = rand.nextInt(dim.height);
                break;
                //x = random and y = max
                case 1:
                    pointY.x = rand.nextInt(dim.width);
                    pointY.y = dim.height;
                break;
                //x = 0 and y = random
                case 3:
                    pointY.x = 0;
                    pointY.y = rand.nextInt(dim.height);
                break;
            }

            diff = new Vector2((pointY.x - pointX.x), (pointY.y - pointX.y));
            slope = diff.y / diff.x;

            Graphics graph = image.getGraphics();

            if (direction)  //true = right | false = left
            {
                int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                int end = dim.width;

                graph.setColor(Color.red);
                graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                graph.setColor(Color.yellow);
                graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);

                for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                {
                    System.out.println(times);
                    start = (int)((times-diff.y)/slope + diff.y);   //this is where it goes wrong?
                    for (int value = start; value < end; ++value)
                    {
                        graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                        graph.fillRect(value, times, 1, 1);
                    }
                }
                graph.dispose();
            }
            else
            {
                int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                int end = dim.width;

                graph.setColor(Color.red);
                graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                graph.setColor(Color.yellow);
                graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);

                for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                {
                    System.out.println(times);
                    start = (int)((times-diff.y)/slope);
                    for (int value = end; value < start; --value)
                    {
                        graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                        graph.fillRect(value, times, 1, 1);
                    }
                }
                graph.dispose();
            }
        }

        return image;
    }
}

Note: In this case vector2 is just a class with X and Y, which can be accessed (this is probably going to be temporary).

Startup part to avoid you losing time:

terrainImage = Linear.generateImage(size, 1);   //size being a Dimension. -> "new Dimension(256, 256)"
if (terrainImage != null)
{
    Icon wIcon = new ImageIcon(terrainImage);
    JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.OK_OPTION, wIcon);
}

//edit here is the code that needs improvement:

if (direction)  //true = right | false = left
                {
                    int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                    int end = dim.width;

                    graph.setColor(Color.red);
                    graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                    graph.setColor(Color.yellow);
                    graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);

                    for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                    {
                        System.out.println(times);
                        start = (int)((times-diff.y)/slope + diff.y);   //this is where it goes wrong?
                        for (int value = start; value < end; ++value)
                        {
                            graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                            graph.fillRect(value, times, 1, 1);
                        }
                    }
                    graph.dispose();
                }
                else
                {
                    int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                    int end = dim.width;

                    graph.setColor(Color.red);
                    graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                    graph.setColor(Color.yellow);
                    graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);

                    for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                    {
                        System.out.println(times);
                        start = (int)((times-diff.y)/slope);
                        for (int value = end; value < start; --value)
                        {
                            graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                            graph.fillRect(value, times, 1, 1);
                        }
                    }
                    graph.dispose();
                }

i can't get it to work like i showed in the picture above, all it does is either nothing, or offset from the 2 points. Also, sometimes it freezes for no reason, so idk what will happen if i make more iterations of this :/

Was it helpful?

Solution

The pattern generation element of your code should only take about 3 lines, including rotation, colour pattern modulation and all as a function of iterations of i.

I will try and be clear:

you don't need a bar/line to generate your maps, you need any pattern on one/2 axes that starts off half of the period of the map and that gets a smaller and smaller proportion of the map or a smaller and smaller period.

pattern:

A line is round(x); or round (x+y) or round(sin(x+y +translatebar)+barwidth)<--a real bar in middle not just on side // you can do curvy and zigzag lines later and 2D lines using additions and multiplications of X and Y functions. That function is essentially just a single line where you can change it X value so that rotates.

Rotation:

instead of a functional X every time which make a vertical line, you need to use sinus and co sinus function to generate X and Y values.

4 example 30; rotation is : round( X * 0.866+ Y* 0.5)

Get the sine and cosine of a random values and it will give you random rotations of your pattern the handy thing is that you just make a random value of your loop iteration and send it to a sign cosine.

OK i ll write this in pseudocode it will be simpler:


var pattern = 0; // black canvas

for(var i=1; i=100; i++)
{
   pattern += round((sin   (X*sin(pseudorand(i))  + Y*cos(pseudorand(i)) + translation) + roundshift )*strength;
}

The above loop will generate thousands of map patterns by adding bars of different rotations.

Round = quantizes your sin(XY) function so it is just black and white / red grey.

Sin(XY) = a variable function to use as a pattern, quantized by round to 0/1 values... multiply and clamp that value in the same line so it doesnt exceed 1 or 0

roundshift = value inside round(sin) pattern that shifts the sin down or up inside the round value resulting in smaller or larger amouts of black/white ration of each iteration. its a multiple of i so it's a function of i, gets smaller every loop.

xsin(rnd i) ycos(rnd i) = rotates your pattern both rnd's are same number necessarily.

translate value = when you +/- a number to a Sin(x+translate). it moves bar backwards/forwards

in the end your pattern value will equals maxiumum 100, so devide by 100 so it's 0-1 or mult by 2.56 for 256, and use a color randomiser to make RGB random multiples of your pattern value.

The above loop obviously needs to run once for every pixel x y.

i dont know how to do the canvas array/texture addin pixels in JS, it should be easy.

The above code will give you great patterns and visual feedback of your errors so you should be able to refine it very nicely, only think i missed is clamp to 0-1 values of sin (-1 1)+ roundshift result.

so a bar is round(sin(xy)+translate), and you can use many many functions of xy added muptiplied sins to add together everything else instead bars, graph circles, squares, wiggles, ovals, rectangles etc.

there is a website all about patterns of this type, except for ordered angles and say 5-6 iterations, using dots bars triangles etc, he is Canadian and on deviant art as well, if there weren't so many TD pattern generated I could find his website!

OTHER TIPS

Here is a website explaining the process of "pattern piling" it's overlaying many shapes in smaller and smaller iterations.

only difference is he uses ordered rotations to create symmetry, and you want random rotations to create chaos maps.

see all the pics of piled patterns in 2d, he has many examples on deviant art and his site, i learnt alot from this guy:

http://algorithmic-worlds.net/info/info.php?page=pilpat here is more work of superimposed smaller and smaller patterns in symmetry rotations: https://www.google.com/search?q=Samuel+Monnier&espv=210&es_sm=93&source=lnms&tbm=isch&sa=X&ei=It0AU9uTCOn20gXXv4G4Cw&ved=0CAkQ_AUoAQ&biw=1365&bih=911

same as this using random sin cos rotations.

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top