Correctly seeded sectors
This commit is contained in:
@@ -5,7 +5,6 @@ import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.noise.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.world.*;
|
||||
@@ -18,9 +17,8 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
protected static final DistanceHeuristic manhattan = (x1, y1, x2, y2) -> Math.abs(x1 - x2) + Math.abs(y1 - y2);
|
||||
protected static final ShortArray ints1 = new ShortArray(), ints2 = new ShortArray();
|
||||
|
||||
protected Simplex sim = new Simplex();
|
||||
protected Simplex sim2 = new Simplex();
|
||||
|
||||
protected Rand rand = new Rand();
|
||||
|
||||
protected int width, height;
|
||||
protected Tiles tiles;
|
||||
|
||||
@@ -34,9 +32,6 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
this.tiles = tiles;
|
||||
this.width = tiles.width;
|
||||
this.height = tiles.height;
|
||||
int seed = Mathf.random(99999999);
|
||||
sim.setSeed(seed);
|
||||
sim2.setSeed(seed + 1);
|
||||
|
||||
generate();
|
||||
}
|
||||
@@ -49,7 +44,7 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
public void cliffs2(){
|
||||
for(Tile tile : tiles){
|
||||
tile.setBlock(Blocks.air);
|
||||
tile.cost = tile.floor().isLiquid ? 0 : (byte)(sim.octaveNoise2D(4, 0.5, 1.0 / 90.0, tile.x, tile.y) * 5);
|
||||
tile.cost = tile.floor().isLiquid ? 0 : (byte)(noise(tile.x, tile.y, 4, 0.5f, 90f, 1) * 5);
|
||||
}
|
||||
|
||||
for(Tile tile : tiles){
|
||||
@@ -137,8 +132,8 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
int offsetX = x - 4, offsetY = y + 23;
|
||||
for(int i = ores.size - 1; i >= 0; i--){
|
||||
Block entry = ores.get(i);
|
||||
if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (40 + i * 2), offsetX, offsetY + i*999)) > 0.26f &&
|
||||
Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (30 + i * 4), offsetX, offsetY - i*999)) > 0.37f){
|
||||
if(Math.abs(0.5f - noise(offsetX, offsetY + i*999, 2, 0.7, (40 + i * 2))) > 0.26f &&
|
||||
Math.abs(0.5f - noise(offsetX, offsetY - i*999, 1, 1, (30 + i * 4))) > 0.37f){
|
||||
ore = entry;
|
||||
break;
|
||||
}
|
||||
@@ -148,7 +143,7 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
|
||||
public void terrain(Block dst, float scl, float mag, float cmag){
|
||||
pass((x, y) -> {
|
||||
double rocks = sim.octaveNoise2D(5, 0.5, 1f / scl, x, y) * mag
|
||||
double rocks = noise(x, y, 5, 0.5, scl) * mag
|
||||
+ Mathf.dst((float)x / width, (float)y / height, 0.5f, 0.5f) * cmag;
|
||||
|
||||
double edgeDist = Math.min(x, Math.min(y, Math.min(Math.abs(x - (width - 1)), Math.abs(y - (height - 1)))));
|
||||
@@ -164,9 +159,8 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
}
|
||||
|
||||
public void noise(Block floor, Block block, int octaves, float falloff, float scl, float threshold){
|
||||
sim.setSeed(Mathf.random(99999));
|
||||
pass((x, y) -> {
|
||||
if(sim.octaveNoise2D(octaves, falloff, 1f / scl, x, y) > threshold){
|
||||
if(noise(octaves, falloff, scl, x, y) > threshold){
|
||||
Tile tile = tiles.getn(x, y);
|
||||
this.floor = floor;
|
||||
if(tile.block().solid){
|
||||
@@ -177,9 +171,8 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
}
|
||||
|
||||
public void overlay(Block floor, Block block, float chance, int octaves, float falloff, float scl, float threshold){
|
||||
sim.setSeed(Mathf.random(99999));
|
||||
pass((x, y) -> {
|
||||
if(sim.octaveNoise2D(octaves, falloff, 1f / scl, x, y) > threshold && Mathf.chance(chance) && tiles.getn(x, y).floor() == floor){
|
||||
if(noise(x, y, octaves, falloff, scl) > threshold && Mathf.chance(chance) && tiles.getn(x, y).floor() == floor){
|
||||
ore = block;
|
||||
}
|
||||
});
|
||||
@@ -189,11 +182,13 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
Block[] blocks = {Blocks.darkPanel3};
|
||||
int secSize = 20;
|
||||
pass((x, y) -> {
|
||||
if(floor.asFloor().isLiquid) return;
|
||||
|
||||
int mx = x % secSize, my = y % secSize;
|
||||
int sclx = x / secSize, scly = y / secSize;
|
||||
if(noise(sclx, scly, 10f, 1f) > 0.63f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
|
||||
if(noise(sclx, scly, 0.2f, 1f) > 0.63f && noise(sclx, scly + 999, 200f, 1f) > 0.6f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
|
||||
if(Mathf.chance(noise(x + 0x231523, y, 40f, 1f))){
|
||||
floor = Structs.random(blocks);
|
||||
floor = blocks[rand.random(0, blocks.length - 1)];
|
||||
if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 2){
|
||||
floor = Blocks.darkPanel4;
|
||||
}
|
||||
@@ -212,7 +207,7 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
|
||||
tiles.each((x, y) -> {
|
||||
int idx = y*tiles.width + x;
|
||||
float cx = x + noise(x, y, scl, mag) - mag / 2f, cy = y + noise(x + 155f, y + 155f, scl, mag) - mag / 2f;
|
||||
float cx = x + noise(x - 155f, y - 200f, scl, mag) - mag / 2f, cy = y + noise(x + 155f, y + 155f, scl, mag) - mag / 2f;
|
||||
Tile other = tiles.getn(Mathf.clamp((int)cx, 0, tiles.width-1), Mathf.clamp((int)cy, 0, tiles.height-1));
|
||||
blocks[idx] = other.block().id;
|
||||
floors[idx] = other.floor().id;
|
||||
@@ -244,8 +239,51 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
}
|
||||
}
|
||||
|
||||
protected float noise(float x, float y, float scl, float mag){
|
||||
return (float)sim2.octaveNoise2D(1f, 0f, 1f / scl, x + 0x361266f, y + 0x251259f) * mag;
|
||||
public void cells(int iterations){
|
||||
cells(iterations, 16, 16, 3);
|
||||
}
|
||||
|
||||
public void cells(int iterations, int birthLimit, int deathLimit, int cradius){
|
||||
GridBits write = new GridBits(tiles.width, tiles.height);
|
||||
GridBits read = new GridBits(tiles.width, tiles.height);
|
||||
|
||||
tiles.each((x, y) -> read.set(x, y, !tiles.get(x, y).block().isAir()));
|
||||
|
||||
for(int i = 0; i < iterations; i++){
|
||||
tiles.each((x, y) -> {
|
||||
int alive = 0;
|
||||
|
||||
for(int cx = -cradius; cx <= cradius; cx++){
|
||||
for(int cy = -cradius; cy <= cradius; cy++){
|
||||
if((cx == 0 && cy == 0) || !Mathf.within(cx, cy, cradius)) continue;
|
||||
if(!Structs.inBounds(x + cx, y + cy, tiles.width, tiles.height) || read.get(x + cx, y + cy)){
|
||||
alive++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(read.get(x, y)){
|
||||
write.set(x, y, alive >= deathLimit);
|
||||
}else{
|
||||
write.set(x, y, alive > birthLimit);
|
||||
}
|
||||
});
|
||||
|
||||
//flush results
|
||||
read.set(write);
|
||||
}
|
||||
|
||||
tiles.each((x, y) -> tiles.get(x, y).setBlock(!read.get(x, y) ? Blocks.air : tiles.get(x, y).floor().wall));
|
||||
}
|
||||
|
||||
protected float noise(float x, float y, double scl, double mag){
|
||||
return noise(x, y, 1, 1, scl, mag);
|
||||
}
|
||||
|
||||
protected abstract float noise(float x, float y, double octaves, double falloff, double scl, double mag);
|
||||
|
||||
protected float noise(float x, float y, double octaves, double falloff, double scl){
|
||||
return noise(x, y, octaves, falloff, scl, 1);
|
||||
}
|
||||
|
||||
public void pass(Intc2 r){
|
||||
|
||||
@@ -11,10 +11,10 @@ import mindustry.maps.generators.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.schematics;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
//TODO refactor into generic planet class
|
||||
public class TestPlanetGenerator implements PlanetGenerator{
|
||||
public class TestPlanetGenerator extends BasicGenerator implements PlanetGenerator{
|
||||
Simplex noise = new Simplex();
|
||||
RidgedPerlin rid = new RidgedPerlin(1, 2);
|
||||
float scl = 5f;
|
||||
@@ -38,6 +38,12 @@ public class TestPlanetGenerator implements PlanetGenerator{
|
||||
{Blocks.darksandWater, Blocks.darksand, Blocks.darksand, Blocks.ice, Blocks.iceSnow, Blocks.iceSnow, Blocks.snow, Blocks.snow, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice, Blocks.ice}
|
||||
};
|
||||
|
||||
Array<Block> ores = Array.with(Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreCopper);
|
||||
ObjectMap<Block, Block> dec = ObjectMap.of(
|
||||
Blocks.sporeMoss, Blocks.sporeCluster,
|
||||
Blocks.moss, Blocks.sporeCluster
|
||||
);
|
||||
|
||||
float water = 2f / arr[0].length;
|
||||
|
||||
float rawHeight(Vec3 position){
|
||||
@@ -79,8 +85,9 @@ public class TestPlanetGenerator implements PlanetGenerator{
|
||||
public void decorate(Tiles tiles, Sector sec){
|
||||
this.tiles = tiles;
|
||||
this.sector = sec;
|
||||
rand.setSeed(sec.id);
|
||||
|
||||
new Terrain().generate(tiles);
|
||||
generate(tiles);
|
||||
}
|
||||
|
||||
Block getBlock(Vec3 position){
|
||||
@@ -96,119 +103,99 @@ public class TestPlanetGenerator implements PlanetGenerator{
|
||||
return arr[Mathf.clamp((int)(temp * arr.length), 0, arr.length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)];
|
||||
}
|
||||
|
||||
class Terrain extends BasicGenerator{
|
||||
Array<Block> ores = Array.with(Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreCopper);
|
||||
|
||||
@Override
|
||||
protected void generate(){
|
||||
|
||||
class Room{
|
||||
int x, y, radius;
|
||||
ObjectSet<Room> connected = new ObjectSet<>();
|
||||
|
||||
Room(int x, int y, int radius){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.radius = radius;
|
||||
connected.add(this);
|
||||
}
|
||||
|
||||
void connect(Room to){
|
||||
if(connected.contains(to)) return;
|
||||
|
||||
connected.add(to);
|
||||
float nscl = Mathf.random(20f, 60f);
|
||||
int stroke = Mathf.random(4, 12);
|
||||
brush(pathfind(x, y, to.x, to.y, tile -> (tile.solid() ? 5f : 0f) + (float)sim.octaveNoise2D(1, 1, 1f / nscl, tile.x, tile.y) * 50, manhattan), stroke);
|
||||
}
|
||||
}
|
||||
|
||||
cells(4);
|
||||
distort(20f, 12f);
|
||||
|
||||
float constraint = 1.3f;
|
||||
float radius = width / 2f / Mathf.sqrt3;
|
||||
int rooms = Mathf.random(2, 5);
|
||||
Array<Room> array = new Array<>();
|
||||
|
||||
//TODO replace random calls with seed
|
||||
|
||||
for(int i = 0; i < rooms; i++){
|
||||
Tmp.v1.trns(Mathf.random(360f), Mathf.random(radius / constraint));
|
||||
float rx = (width/2f + Tmp.v1.x);
|
||||
float ry = (height/2f + Tmp.v1.y);
|
||||
float maxrad = radius - Tmp.v1.len();
|
||||
float rrad = Math.min(Mathf.random(9f, maxrad / 2f), 30f);
|
||||
array.add(new Room((int)rx, (int)ry, (int)rrad));
|
||||
}
|
||||
|
||||
for(Room room : array){
|
||||
erase(room.x, room.y, room.radius);
|
||||
}
|
||||
|
||||
int connections = Mathf.random(Math.max(rooms - 1, 1), rooms + 3);
|
||||
Room spawn = array.random();
|
||||
for(int i = 0; i < connections; i++){
|
||||
array.random().connect(array.random());
|
||||
}
|
||||
|
||||
for(Room room : array){
|
||||
spawn.connect(room);
|
||||
}
|
||||
|
||||
cells(1);
|
||||
distort(20f, 6f);
|
||||
|
||||
inverseFloodFill(tiles.getn(spawn.x, spawn.y));
|
||||
|
||||
ores(ores);
|
||||
|
||||
for(Room other : array){
|
||||
if(other != spawn){
|
||||
// tiles.getn(other.x, other.y).setOverlay(Blocks.spawn);
|
||||
}
|
||||
}
|
||||
|
||||
trimDark();
|
||||
|
||||
median(2);
|
||||
|
||||
schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y);
|
||||
}
|
||||
|
||||
void cells(int iterations){
|
||||
GridBits write = new GridBits(tiles.width, tiles.height);
|
||||
GridBits read = new GridBits(tiles.width, tiles.height);
|
||||
|
||||
tiles.each((x, y) -> read.set(x, y, !tiles.get(x, y).block().isAir()));
|
||||
|
||||
int birthLimit = 16, deathLimit = 16, cradius = 3;
|
||||
|
||||
for(int i = 0; i < iterations; i++){
|
||||
tiles.each((x, y) -> {
|
||||
int alive = 0;
|
||||
|
||||
for(int cx = -cradius; cx <= cradius; cx++){
|
||||
for(int cy = -cradius; cy <= cradius; cy++){
|
||||
if((cx == 0 && cy == 0) || !Mathf.within(cx, cy, cradius)) continue;
|
||||
if(!Structs.inBounds(x + cx, y + cy, tiles.width, tiles.height) || read.get(x + cx, y + cy)){
|
||||
alive++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(read.get(x, y)){
|
||||
write.set(x, y, alive >= deathLimit);
|
||||
}else{
|
||||
write.set(x, y, alive > birthLimit);
|
||||
}
|
||||
});
|
||||
|
||||
//flush results
|
||||
read.set(write);
|
||||
}
|
||||
|
||||
tiles.each((x, y) -> tiles.get(x, y).setBlock(!read.get(x, y) ? Blocks.air : tiles.get(x, y).floor().wall));
|
||||
}
|
||||
@Override
|
||||
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
|
||||
Vec3 v = sector.rect.project(x, y).scl(5f);
|
||||
return (float)noise.octaveNoise3D(octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generate(){
|
||||
|
||||
class Room{
|
||||
int x, y, radius;
|
||||
ObjectSet<Room> connected = new ObjectSet<>();
|
||||
|
||||
Room(int x, int y, int radius){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.radius = radius;
|
||||
connected.add(this);
|
||||
}
|
||||
|
||||
void connect(Room to){
|
||||
if(connected.contains(to)) return;
|
||||
|
||||
connected.add(to);
|
||||
float nscl = rand.random(20f, 60f);
|
||||
int stroke = rand.random(4, 12);
|
||||
brush(pathfind(x, y, to.x, to.y, tile -> (tile.solid() ? 5f : 0f) + noise(tile.x, tile.y, 1, 1, 1f / nscl) * 50, manhattan), stroke);
|
||||
}
|
||||
}
|
||||
|
||||
cells(4);
|
||||
distort(10f, 12f);
|
||||
|
||||
float constraint = 1.3f;
|
||||
float radius = width / 2f / Mathf.sqrt3;
|
||||
int rooms = rand.random(2, 5);
|
||||
Array<Room> array = new Array<>();
|
||||
|
||||
for(int i = 0; i < rooms; i++){
|
||||
Tmp.v1.trns(rand.random(360f), rand.random(radius / constraint));
|
||||
float rx = (width/2f + Tmp.v1.x);
|
||||
float ry = (height/2f + Tmp.v1.y);
|
||||
float maxrad = radius - Tmp.v1.len();
|
||||
float rrad = Math.min(rand.random(9f, maxrad / 2f), 30f);
|
||||
array.add(new Room((int)rx, (int)ry, (int)rrad));
|
||||
}
|
||||
|
||||
for(Room room : array){
|
||||
erase(room.x, room.y, room.radius);
|
||||
}
|
||||
|
||||
int connections = rand.random(Math.max(rooms - 1, 1), rooms + 3);
|
||||
Room spawn = array.random();
|
||||
for(int i = 0; i < connections; i++){
|
||||
array.random().connect(array.random());
|
||||
}
|
||||
|
||||
for(Room room : array){
|
||||
spawn.connect(room);
|
||||
}
|
||||
|
||||
cells(1);
|
||||
distort(10f, 6f);
|
||||
|
||||
inverseFloodFill(tiles.getn(spawn.x, spawn.y));
|
||||
|
||||
ores(ores);
|
||||
|
||||
for(Room other : array){
|
||||
if(other != spawn){
|
||||
// tiles.getn(other.x, other.y).setOverlay(Blocks.spawn);
|
||||
}
|
||||
}
|
||||
|
||||
trimDark();
|
||||
|
||||
median(2);
|
||||
|
||||
tech();
|
||||
|
||||
pass((x, y) -> {
|
||||
for(int i = 0; i < 4; i++){
|
||||
Tile near = world.tile(x + Geometry.d4[i].x, y + Geometry.d4[i].y);
|
||||
if(near != null && near.block() != Blocks.air){
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(Mathf.chance(0.01) && !floor.asFloor().isLiquid && block == Blocks.air){
|
||||
block = dec.get(floor, floor.asFloor().decoration);
|
||||
}
|
||||
});
|
||||
|
||||
schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ public class Floor extends Block{
|
||||
public float oreScale = 24f, oreThreshold = 0.828f;
|
||||
/** Wall variant of this block. May be Blocks.air if not found. */
|
||||
public Block wall = Blocks.air;
|
||||
/** Decoration block. Usually a rock. May be air. */
|
||||
public Block decoration = Blocks.air;
|
||||
|
||||
protected TextureRegion[][] edges;
|
||||
protected byte eq = 0;
|
||||
@@ -106,6 +108,10 @@ public class Floor extends Block{
|
||||
|
||||
//keep default value if not found...
|
||||
if(wall == null) wall = Blocks.air;
|
||||
|
||||
if(decoration == Blocks.air){
|
||||
decoration = content.blocks().min(b -> b instanceof Rock && b.breakable ? color.diff(b.color) : Float.POSITIVE_INFINITY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user