tModLoader Generating a oval-like shape in World Gen

Ahndrek Li'Cyri

Skeletron Prime
Hello!
So I'm trying to generate a filled oval like shape, where it is longer then it is tall.
Let's say the Y radius is 150 tiles long, and the X radius is 100 tiles long, like so:
OvalExample.png


How would i go about generating this in code?
Any help is appreciated, thank you!
 

Kazzymodus

Moderator
Staff member
Moderator
You seem to have your x and y switched around (y is 150 and x is 100, which would make it taller than it was wide), so I went with replicating the shape in the image. Please note that none of this is tested, but it should create a general ellipsoid shape.
C#:
Vector2 offset; // This tile will be the highest point of the ellipsoid.

int xRadius = 100;
int yRadius = 150;

for (int y = 0; y < yRadius * 2; y++) // we work downwards
{
    float ratio = y / (float)(yRadius * 2); // This will give us a ratio from 0 to 1, depending on how far down we are
    int width = (int)(Math.Sin(ratio * Math.PI ) * xRadius * 2); // This will give us the width of the ellipsoid at height y
   
    for (int x = -width / 2; x < width / 2; x++)
    {
        Vector2 tilePosition = offset + new Vector2(x, y);
        CreateTileOrSomething(tilePosition);
    }
}
 

Ahndrek Li'Cyri

Skeletron Prime
You seem to have your x and y switched around (y is 150 and x is 100, which would make it taller than it was wide), so I went with replicating the shape in the image. Please note that none of this is tested, but it should create a general ellipsoid shape.
C#:
Vector2 offset; // This tile will be the highest point of the ellipsoid.

int xRadius = 100;
int yRadius = 150;

for (int y = 0; y < yRadius * 2; y++) // we work downwards
{
    float ratio = y / (float)(yRadius * 2); // This will give us a ratio from 0 to 1, depending on how far down we are
    int width = (int)(Math.Sin(ratio * Math.PI ) * xRadius * 2); // This will give us the width of the ellipsoid at height y
 
    for (int x = -width / 2; x < width / 2; x++)
    {
        Vector2 tilePosition = offset + new Vector2(x, y);
        CreateTileOrSomething(tilePosition);
    }
}
Thanks, but i actually figured out a more mathmatical (and honestly probably way over complicated) route to doing it:
C#:
double PI = 3.14159265;
for (double angle = 0; angle <= 2 * PI; angle += 0.001)
{
    Vector2 PosTile = new Vector2(CenterX + (int)(RadiusX * Math.Cos(angle)), CenterY + (int)(RadiusY * Math.Sin(angle)));
    Vector2 NegTile = new Vector2(CenterX - (int)(RadiusX * Math.Cos(angle)), CenterY - (int)(RadiusY * Math.Sin(angle)));
    for (int i = (int)NegTile.X; i < (int)PosTile.X; i++)
    {
        for (int j = (int)NegTile.Y; j < (int)PosTile.Y; j++)
        {
            if (Main.tile[i, j].active())
            {
                Main.tile[i, j].type = 0;
            }
            else
            {
                WorldGen.PlaceTile(i, j, 0);
            }
        }
    }
}
 

Kazzymodus

Moderator
Staff member
Moderator
Thanks, but i actually figured out a more mathmatical (and honestly probably way over complicated) route to doing it:
C#:
double PI = 3.14159265;
for (double angle = 0; angle <= 2 * PI; angle += 0.001)
{
    Vector2 PosTile = new Vector2(CenterX + (int)(RadiusX * Math.Cos(angle)), CenterY + (int)(RadiusY * Math.Sin(angle)));
    Vector2 NegTile = new Vector2(CenterX - (int)(RadiusX * Math.Cos(angle)), CenterY - (int)(RadiusY * Math.Sin(angle)));
    for (int i = (int)NegTile.X; i < (int)PosTile.X; i++)
    {
        for (int j = (int)NegTile.Y; j < (int)PosTile.Y; j++)
        {
            if (Main.tile[i, j].active())
            {
                Main.tile[i, j].type = 0;
            }
            else
            {
                WorldGen.PlaceTile(i, j, 0);
            }
        }
    }
}
This is unbelievably inefficient. You are calculating the outer antipodal tiles of a circle 6283 times (many of those calculations will be duplicate, due to how tiles work) and just filling in a rectangle between those points, and apart from the massive overlap inherent in that method, you're doing a full circle (which defies the point of using antipodes), essentially unnecessarily doubling all calculations (which are then wasted because the for loops can't use them).

It may be "more mathematical" (if that term even has meaning), but it's several orders of magnitude slower than it could be, with absolutely no tangible gain.
 

Ahndrek Li'Cyri

Skeletron Prime
This is unbelievably inefficient. You are calculating the outer antipodal tiles of a circle 6283 times (many of those calculations will be duplicate, due to how tiles work) and just filling in a rectangle between those points, and apart from the massive overlap inherent in that method, you're doing a full circle (which defies the point of using antipodes), essentially unnecessarily doubling all calculations (which are then wasted because the for loops can't use them).

It may be "more mathematical" (if that term even has meaning), but it's several orders of magnitude slower than it could be, with absolutely no tangible gain.
I actually didn't notice any slow down or change in generation speed when using either way to generate the shape, nor any change in use of memory, but i see the point you are making here.
 
Top Bottom