Get Array of Points that Make a Circle And Displace Them

Started by
5 comments, last by aregee 9 years, 9 months ago

Hi, so I'm trying to figure out a world generation algorithm for my game in Unity but I am having a hard time deciding how to implement it.

So few days ago, I stumbled on an old thread in this site which they achieve exactly what I am trying to do. They generate some circles and then use Perlin noise to mess with radius (or at least that's what I understood so far), resulting in irregular continents.

I tried using "if (x-x0)^2 + (y-y0)^2 <= r^2 then" but the thing is, I don't get the same result

According to that thread, their way of drawing a circle is using function that has a theta, but I can't find a way of doing that.
So my question is: How Can I get an array of points that make up a circle (NOT CIRCUMFERENCE) so that I can get the same results as the image bellow?

The reason I don't ask in that thread its because its already too old and is locked.

Advertisement

Are you talking about the parametric equation of a circle? You have to decide how many points your circle will have and then you can calculate theta accordingly, e.g.:


Vector2[] circle = new Vector2[numVertices];
float delta = (2*PI) / numVertices;

for (int i=0; i < numVertices; i++)
{
   float t = delta * i;
   x = x0 + cos(t)*r;
   y = y0 + sin(t)*r;
   circle[i] = new Vector2(x,y);
}

Where x0,y0 are the coordinates of your center and r is the radius of the circle. As the for loop runs, t will be incremented until it covers the whole circle. The more points you calculate, the closer it will approximate a circle.

--Avengers UTD Chronicles - My game development blog

their way of drawing a circle is using function that has a theta, but I can't find a way of doing that.

Theta is an angle incremented from 0 to 2 Pi, commonly in a loop to generate (x,y) coordinate pairs.

Off the top of my head:


float delta = (some small value);
for(float theta = 0; theta < 2*Pi; theta += delta)
{
   float x = sin(theta);
   float y = cos(theta);
   // use (x,y) for something
}

ph34r.png by AvengerDr

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thanks for your post, my problem is that using a parametric function, I just have the points surrounding the center, not actually the filled circle.

If for each iteration in the loop you add a random displacement to the radius, you will get a circle with jagged segments - if you were to connect all the vertices to each other. In fact, this set of points could then be transformed into a polyline or spline and filled accordingly to your requirements.

--Avengers UTD Chronicles - My game development blog

You do know that there are other potentially easier ways to create continents, right? Such as height maps or incremental flood fill..

Looking at those images, I'm guessing they are using very close points, possibly with variations in the theta as well as the radius. If you are interested in this for mathematical reasons or whatever, then by all means, but if you just want nice continents, there are probably easier ways.

I tried to take the challenge to make my own implementation, knowing nothing about the subject at all. It looks nothing like the images you showed. Then I noticed that they are using Perlin noise, and I was just using a simple random generator... Basically using the method AvengerDr suggested, drawing a circle with various displacements, deformations. (Basically drawing a jagged oval rather than a jagged circle.)

Edit: Looking at the picture you posted, it looks like they are not only using Perlin noise, but using spherical coordinates too. (Mapping to a sphere.)

notamap.png

On the other hand, looking at the picture from the answer in the thread that you posted a link to, the initial shapes looks very much like what I get with my attempt.

Picture prom the post:

CK9dbvJ.png

Code (quick and dirty...)


- (void)drawRect:(NSRect)dirtyRect {

    [[NSColor blackColor] set];
    [NSBezierPath fillRect:dirtyRect];
    
    [[NSColor whiteColor] set];

    double centerX = [self bounds].size.width / 2.0f;
    double centerY = [self bounds].size.height / 2.0f;
    
    double x = 0.0f;
    double y = 0.0f;
    
    double radius = 100.0f;
    
    double delta = 0.05f;

    double randomValue = 0.0f;
    
    randomValue = (double)arc4random_uniform(10000) / 10000.0f;
    double scaleX = (randomValue + 0.1f);
    
    randomValue = (double)arc4random_uniform(10000) / 10000.0f;
    double scaleY = (randomValue + 0.1f);

    randomValue = (double)arc4random_uniform(10000) / 10000.0f;
    double clampToValue = randomValue * 200.0f;

    NSBezierPath *circle = [NSBezierPath bezierPath];
    BOOL isFirst = YES;
    double deviationRadius = 0.0f;

    for (double theta = 0.0f; theta < 2 * M_PI; theta += delta) {
        randomValue = ((double)arc4random_uniform(10000) / 10000.0f) - 0.5f;

        deviationRadius += randomValue * 100.0f;
        
        if ((clampToValue - (radius - deviationRadius)) < 0.0f) {
            deviationRadius += clampToValue;
        }
        
        x = sin(theta) * (radius + deviationRadius) * scaleX + centerX;
        y = cos(theta) * (radius + deviationRadius) * scaleY + centerY;

        if (isFirst) {
            [circle moveToPoint:NSMakePoint(x, y)];
            isFirst = NO;
        }
        else {
            [circle lineToPoint:NSMakePoint(x, y)];
        }
        
    }

    [circle closePath];
    [circle fill];
//    [circle stroke];
}

This topic is closed to new replies.

Advertisement