Birdoggydog's Builds

Scaling a built island to half its width with one number

A test version of the Wishbone island at a quarter of the area, made by multiplying the finished files instead of generating or painting anything again.

I made a second copy of the island at half the width and half the height, so a quarter of the area. It’s 5,120 meters across instead of 10,240, and the highest point is 530 meters instead of 1,061. It’s a test build. The real world is still the big one, and I wanted to walk around the small one before deciding anything.

59 seconds on the half island: standing at the top of the exit lift, a look around, a walk to the crater lake’s rim, then flying up to see the whole island.

Why not just run the generator smaller?

I wanted to keep the dungeon and the overall layout, and I didn’t want to redo the waterfalls and the painting. Running the generator or the painter at another size would have eroded new rivers and painted everything again. So the scale is a separate Python script, scale_island.py, that reads the finished island’s files and writes another folder with every length multiplied by one number. FACTOR = 0.5 is written once, so trying 0.6 or 0.7 later means changing that number. After the script runs, the normal island builder turns the new folder into regions and a scene, which takes about 30 seconds.

What gets multiplied?

Everything is scaled the same in x, y and z around the island’s center, so slopes keep their angles and rivers keep their falls.

For the ground, each region file keeps its 512 by 512 samples and every height is multiplied by the factor. The manifest’s spacing, which is Terrain3D’s vertex_spacing, goes from 1.0 to 0.5, so a region now covers half the meters with the same samples. The painting is stored per vertex, so it’s copied unchanged. The far ground and the map screen already read vertex_spacing from the manifest, so they didn’t need touching.

The manifest’s lengths all get multiplied: size, sea level, the lakes’ rectangles, levels and outline files, places, routes, stops, the Tower and its height. Areas use the factor squared.

The rivers are a flat array of floats, 27 per section. The script multiplies the five vertices of each section, the two edge widths and the column holding the seconds the water has run. That last one is halved with the distances on purpose. The water’s pattern slides along a section at distance over time, so halving both keeps the water moving at the same speed per meter. In rivers.json the section step, each chunk’s width and line, and each fall’s lip, foot, pool, drop and run are scaled too.

The markers file says where things are placed. For the half island, scale_markers() writes a new block from the full island’s. Positions and heights are scaled. Things keep their size: the dungeon, the lift head’s walls, the buildings and the width of the way down. Stretches of the world get scaled, like the way’s points and a named place’s ground. The lift head’s path is refitted so its yard’s far wall lands where the scaled way begins. With a path of 77.5 m and a yard of 8 m, the new path is 34.75 m.

Standing in the exit lift

I wanted to start at the top of the exit elevator in the test, so the explore tool got two command-line arguments. --island=<name> explores another built island, and --at-lift puts the party on the deck 4 m back from the doorway, facing it. stand_at_lift() finds the lift head among the world’s markers, places the party, lets the terrain stream in, and sets the position again because the ground can move. explore_half.bat runs it with its own user:// folder, so it can’t touch anyone’s saves.

Why did the dungeon stick out of the hill?

The dungeon keeps its size, but the volcano on top of it is half as tall. With the original 41.2 m top shaft, 391 ceiling corners ended up under 1.5 m of ground and 16.8 m of the site stood out of the hillside. I lengthened the top shaft to 60 m, which puts the first floor 75.9 m above the sea. The script has a small table, TOP_SHAFT, keyed by factor, so a different factor needs its own value. The test prints what 2 m of cover everywhere would want.

A red-pink plain with a town in the distance, and in front a brown volcano with a round blue crater lake. A square concrete lift head stands in the lake, joined to the rim by a straight walkway, and the way down curves off the flank in three bands.

The halved volcano from above, with the lift head standing in the crater lake and the way down curling off the flank.

What doesn’t shrink?

Anything the game measures in meters itself stays the same size, and that’s where the half island looks wrong.

Eight small houses with gray roofs crowded together on a flat red plain, a gray path leading away from them, blue sea behind and white mountains and a tall dark tower on the far shore.

The town from above: the eight buildings are full size on ground at half the spacing, so the roofs nearly touch.

The town’s eight buildings stand at half their spacing. The way down’s deck is still 4 m wide, so at the hairpins its legs run side by side, and the lift head’s 13 m walls fill more of a crater lake that’s half as wide. The scatter that places trees and rocks works on a lattice in meters, so there are the same number per hectare and a quarter as many in all. River sheets still build within 520 m and mist within 1.5 km, which is twice as far in the island’s terms. The sea still extends 4 km past the island. Walking at 5 m/s crosses the island in half the time. The map’s zoom is in pixels per meter, so the island shows half as wide. I haven’t walked the town yet, so the crowding is from above only.

Did it still run well?

water_check.py now reads spacing and scale, and it gives identical counts on both islands, so the falls and lakes are where the ground puts them. tests/world_half runs 21 checks and they all pass, including heights at three known places being half the original’s and the full island’s 1,307 files having the same hashes before and after. At the lift top the half island’s frames average 9.8 to 11.5 ms, against 9.3 to 10.8 ms on the full one. The worst frame is 15.9 to 18.3 ms against 12.6 ms.

Whether the real world shrinks, and by what factor, is still to decide after playing it.