Improved generation tool

This commit is contained in:
Anuken
2019-03-15 15:06:55 -04:00
parent 97067a6ee2
commit e7ffbd817c
13 changed files with 388 additions and 126 deletions

View File

@@ -212,6 +212,7 @@ editor.errorload = Error loading file:\n[accent]{0}
editor.errorsave = Error saving file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0}
editor.errorname = Map has no name defined. editor.errorname = Map has no name defined.
editor.update = Update editor.update = Update
editor.randomize = Randomize
editor.apply = Apply editor.apply = Apply
editor.generate = Generate editor.generate = Generate
editor.resize = Resize editor.resize = Resize

View File

@@ -13,7 +13,6 @@ import io.anuke.arc.graphics.glutils.FrameBuffer;
import io.anuke.arc.math.Mathf; import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.util.ScreenRecorder;
import io.anuke.arc.util.Time; import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp; import io.anuke.arc.util.Tmp;
import io.anuke.arc.util.pooling.Pools; import io.anuke.arc.util.pooling.Pools;
@@ -131,10 +130,6 @@ public class Renderer implements ApplicationListener{
draw(); draw();
} }
if(!ui.chatfrag.chatOpen()){
ScreenRecorder.record(); //this only does something if CoreGifRecorder is on the class path, which it usually isn't
}
} }
void updateShake(float scale){ void updateShake(float scale){

View File

@@ -52,7 +52,7 @@ public class MapEditor{
tiles = createTiles(map.width, map.height); tiles = createTiles(map.width, map.height);
tags.putAll(map.tags); tags.putAll(map.tags);
MapIO.readTiles(map, tiles); MapIO.readTiles(map, tiles);
checkTiles(); checkLinkedTiles();
renderer.resize(width(), height()); renderer.resize(width(), height());
loading = false; loading = false;
} }
@@ -61,12 +61,12 @@ public class MapEditor{
reset(); reset();
this.tiles = tiles; this.tiles = tiles;
checkTiles(); checkLinkedTiles();
renderer.resize(width(), height()); renderer.resize(width(), height());
} }
//adds missing blockparts //adds missing blockparts
void checkTiles(){ public void checkLinkedTiles(){
//clear block parts first //clear block parts first
for(int x = 0; x < width(); x ++){ for(int x = 0; x < width(); x ++){
for(int y = 0; y < height(); y++){ for(int y = 0; y < height(); y++){

View File

@@ -1,32 +1,49 @@
package io.anuke.mindustry.editor; package io.anuke.mindustry.editor;
import io.anuke.arc.Core;
import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Array;
import io.anuke.arc.function.Supplier;
import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.graphics.Pixmap;
import io.anuke.arc.graphics.Pixmap.Format; import io.anuke.arc.graphics.Pixmap.Format;
import io.anuke.arc.graphics.Texture; import io.anuke.arc.graphics.Texture;
import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.editor.generation.FilterOption; import io.anuke.arc.util.Scaling;
import io.anuke.mindustry.editor.generation.GenerateFilter; import io.anuke.arc.util.async.AsyncExecutor;
import io.anuke.arc.util.async.AsyncResult;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.editor.generation.*;
import io.anuke.mindustry.editor.generation.GenerateFilter.GenerateInput; import io.anuke.mindustry.editor.generation.GenerateFilter.GenerateInput;
import io.anuke.mindustry.editor.generation.NoiseFilter;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.ui.BorderImage; import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.DummyTile; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.Floor;
import static io.anuke.mindustry.Vars.mobile;
@SuppressWarnings("unchecked")
public class MapGenerateDialog extends FloatingDialog{ public class MapGenerateDialog extends FloatingDialog{
private final MapEditor editor; private final MapEditor editor;
private Pixmap pixmap; private Pixmap pixmap;
private Texture texture; private Texture texture;
private GenerateInput input = new GenerateInput(); private GenerateInput input = new GenerateInput();
private Array<GenerateFilter> filters = new Array<>(); private Array<GenerateFilter> filters = new Array<>();
private int scaling = mobile ? 3 : 1;
private Supplier<GenerateFilter>[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new};
private Table filterTable;
private AsyncExecutor executor = new AsyncExecutor(1);
private AsyncResult<Void> result;
private boolean generating;
private DummyTile returnTile = new DummyTile();
private DummyTile[][] buffer1, buffer2;
public MapGenerateDialog(MapEditor editor){ public MapGenerateDialog(MapEditor editor){
super("editor.generate"); super("$editor.generate");
this.editor = editor; this.editor = editor;
shown(this::setup); shown(this::setup);
@@ -35,9 +52,17 @@ public class MapGenerateDialog extends FloatingDialog{
apply(); apply();
hide(); hide();
}).size(180f, 64f); }).size(180f, 64f);
buttons.addButton("$editor.randomize", () -> {
for(GenerateFilter filter : filters){
filter.randomize();
}
update();
}).size(180f, 64f);
} }
void setup(){ void setup(){
filters.clear();
if(pixmap != null){ if(pixmap != null){
pixmap.dispose(); pixmap.dispose();
texture.dispose(); texture.dispose();
@@ -45,123 +70,246 @@ public class MapGenerateDialog extends FloatingDialog{
texture = null; texture = null;
} }
pixmap = new Pixmap(editor.width(), editor.height(), Format.RGBA8888); pixmap = new Pixmap(editor.width() / scaling, editor.height() / scaling, Format.RGBA8888);
texture = new Texture(pixmap); texture = new Texture(pixmap);
cont.clear(); cont.clear();
cont.table("flat", t -> { cont.table("flat", t -> {
t.margin(8f); t.margin(8f);
t.add(new BorderImage(texture)).size(500f).padRight(6); t.add(new BorderImage(texture)).grow().padRight(6).top().get().setScaling(Scaling.fit);
t.table(right -> { t.table(right -> {
Table[] fs = {null}; right.pane(p -> filterTable = p).grow().get().setScrollingDisabled(true, false);
Runnable rebuild = () -> {
Table p = fs[0];
p.clearChildren();
for(GenerateFilter filter : filters){
p.table("button", f -> {
f.left();
for(FilterOption option : filter.options){
option.build(f);
f.row();
}
for(Element e : f.getChildren()){
e.changed(this::update);
}
}).pad(3).width(280f);
p.row();
}
};
right.pane(p -> {
p.top();
fs[0] = p;
}).fill().width(300f).growY().get().setScrollingDisabled(true, false);
right.row(); right.row();
right.addButton("$add", () -> { right.addButton("$add", this::showAdd).fillX().height(50f);
filters.add(new NoiseFilter()); }).grow();
rebuild.run();
}).fillX().height(50f);
}).grow(); }).grow();
t.row();
t.addButton("$editor.update", () -> {
input.randomize();
update(); update();
}).size(300f, 66f).colspan(2).pad(6);
buffer1 = create();
buffer2 = create();
}
DummyTile[][] create(){
DummyTile[][] out = new DummyTile[editor.width() / scaling][editor.height() / scaling];
for(int x = 0; x < out.length; x++){
for(int y = 0; y < out[0].length; y++){
out[x][y] = new DummyTile();
}
}
return out;
}
void rebuildFilters(){
filterTable.clearChildren();
filterTable.top();
for(GenerateFilter filter : filters){
filterTable.table(t -> {
t.add(filter.name()).padTop(5).color(Pal.accent).growX().left();
t.row();
t.table(b -> {
b.left();
b.defaults().size(50f);
b.addImageButton("icon-refresh", 14*2, () -> {
filter.randomize();
update();
}); });
b.addImageButton("icon-arrow-up", 10*2, () -> {
int idx = filters.indexOf(filter);
filters.swap(idx, Math.max(0, idx - 1));
rebuildFilters();
update(); update();
});
b.addImageButton("icon-arrow-down", 10*2, () -> {
int idx = filters.indexOf(filter);
filters.swap(idx, Math.min(filters.size-1, idx + 1));
rebuildFilters();
update();
});
b.addImageButton("icon-trash", 14*2, () -> {
filters.remove(filter);
rebuildFilters();
update();
});
}).growX();
}).fillX();
filterTable.row();
filterTable.table("underline", f -> {
f.left();
for(FilterOption option : filter.options){
option.changed = this::update;
f.table(t -> {
t.left();
option.build(t);
}).growX().left();
f.row();
}
}).pad(3).padTop(0).width(280f);
filterTable.row();
}
}
void showAdd(){
FloatingDialog selection = new FloatingDialog("");
selection.setFillParent(false);
selection.cont.defaults().size(210f, 60f);
for(Supplier<GenerateFilter> gen : filterTypes){
GenerateFilter filter = gen.get();
selection.cont.addButton(filter.name(), () -> {
filters.add(filter);
rebuildFilters();
update();
selection.hide();
});
selection.cont.row();
}
selection.addCloseButton();
selection.show();
}
DummyTile dset(Tile tile){
returnTile.set(tile);
return returnTile;
} }
void apply(){ void apply(){
Tile[][] writeTiles = new Tile[editor.width()][editor.height()]; if(result != null){
result.get();
}
//writeback buffer
DummyTile[][] writeTiles = new DummyTile[editor.width()][editor.height()];
for(int x = 0; x < editor.width(); x++){ for(int x = 0; x < editor.width(); x++){
for(int y = 0; y < editor.height(); y++){ for(int y = 0; y < editor.height(); y++){
writeTiles[x][y] = new DummyTile(x, y); writeTiles[x][y] = new DummyTile();
} }
} }
for(GenerateFilter filter : filters){ for(GenerateFilter filter : filters){
input.setFilter(filter, (x, y) -> dset(editor.tile(x, y)));
//write to buffer
for(int x = 0; x < editor.width(); x++){ for(int x = 0; x < editor.width(); x++){
for(int y = 0; y < editor.height(); y++){ for(int y = 0; y < editor.height(); y++){
Tile tile = editor.tile(x, y); Tile tile = editor.tile(x, y);
Tile write = writeTiles[x][y];
input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore());
filter.apply(input); filter.apply(input);
write.setRotation(tile.getRotation()); writeTiles[x][y].set(input.floor, input.block, input.ore, tile.getTeam(), tile.getRotation());
write.setOre(input.ore);
write.setFloor((Floor)input.floor);
write.setBlock(input.block);
write.setTeam(tile.getTeam());
} }
} }
editor.load(() -> { editor.load(() -> {
//read from buffer back into tiles
for(int x = 0; x < editor.width(); x++){ for(int x = 0; x < editor.width(); x++){
for(int y = 0; y < editor.height(); y++){ for(int y = 0; y < editor.height(); y++){
Tile tile = editor.tile(x, y); Tile tile = editor.tile(x, y);
Tile write = writeTiles[x][y]; DummyTile write = writeTiles[x][y];
tile.setRotation(write.getRotation()); tile.setRotation((byte)write.rotation);
tile.setOre(write.ore()); tile.setFloor((Floor)write.floor);
tile.setFloor(write.floor()); tile.setBlock(write.block);
tile.setBlock(write.block()); tile.setTeam(write.team);
tile.setTeam(write.getTeam()); tile.setOre(write.ore);
} }
} }
}); });
} }
//reset undo stack as generation... messes things up
editor.load(editor::checkLinkedTiles);
editor.renderer().updateAll(); editor.renderer().updateAll();
editor.clearOp(); editor.clearOp();
} }
void update(){ void update(){
boolean modified = false; if(generating){
for(GenerateFilter filter : filters){ return;
modified = true; }
for(int x = 0; x < editor.width(); x++){
for(int y = 0; y < editor.height(); y++){ Array<GenerateFilter> copy = new Array<>(filters);
Tile tile = editor.tile(x, y);
input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); result = executor.submit(() -> {
generating = true;
if(!filters.isEmpty()){
//write to buffer1 for reading
for(int px = 0; px < pixmap.getWidth(); px++){
for(int py = 0; py < pixmap.getHeight(); py++){
buffer1[px][py].set(editor.tile(px * scaling, py * scaling));
}
}
}
for(GenerateFilter filter : copy){
input.setFilter(filter, (x, y) -> buffer1[x][y]);
//read from buffer1 and write to buffer2
for(int px = 0; px < pixmap.getWidth(); px++){
for(int py = 0; py < pixmap.getHeight(); py++){
int x = px*scaling, y = py*scaling;
DummyTile tile = buffer1[px][py];
input.begin(editor, x, y, tile.floor, tile.block, tile.ore);
filter.apply(input); filter.apply(input);
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(input.floor, input.block, input.ore, Team.none)); buffer2[px][py].set(input.floor, input.block, input.ore, tile.team, tile.rotation);
}
}
for(int px = 0; px < pixmap.getWidth(); px++){
for(int py = 0; py < pixmap.getHeight(); py++){
buffer1[px][py].set(buffer2[px][py]);
} }
} }
} }
if(!modified){ for(int px = 0; px < pixmap.getWidth(); px++){
for(int x = 0; x < editor.width(); x++){ for(int py = 0; py < pixmap.getHeight(); py++){
for(int y = 0; y < editor.height(); y++){ int color;
Tile tile = editor.tile(x, y); //get result from buffer1 if there's filters left, otherwise get from editor directly
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none)); if(filters.isEmpty()){
Tile tile = editor.tile(px * scaling, py * scaling);
color = MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none);
}else{
DummyTile tile = buffer1[px][py];
color = MapIO.colorFor(tile.floor, tile.block, tile.ore, Team.none);
} }
pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color);
} }
} }
Core.app.post(() -> {
texture.draw(pixmap, 0, 0); texture.draw(pixmap, 0, 0);
generating = false;
});
return null;
});
}
public static class DummyTile{
public Block block = Blocks.air, ore = Blocks.air, floor = Blocks.air;
public Team team = Team.none;
public int rotation;
void set(Block floor, Block wall, Block ore, Team team, int rotation){
this.floor = floor;
this.block = wall;
this.ore = ore;
this.team = team;
this.rotation = rotation;
}
void set(DummyTile other){
set(other.floor, other.block, other.ore, other.team, other.rotation);
}
void set(Tile other){
set(other.floor(), other.block(), other.ore(), other.getTeam(), other.getRotation());
}
} }
} }

View File

@@ -1,24 +1,25 @@
package io.anuke.mindustry.editor.generation; package io.anuke.mindustry.editor.generation;
import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile;
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor;
public class DistortFilter extends GenerateFilter{ public class DistortFilter extends GenerateFilter{
float scl = 40, mag = 5; float scl = 40, mag = 5;
{ {
options( options(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 1000f), new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f),
new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 10f) new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f)
); );
} }
@Override @Override
public void apply(){ public void apply(){
Tile tile = in.tile(in.x + noise(in.x, in.y, scl, mag)-mag/2f, in.y + noise(in.x, in.y+o, scl, mag)-mag/2f); DummyTile tile = in.tile(in.x + noise(in.x, in.y, scl, mag)-mag/2f, in.y + noise(in.x, in.y+o, scl, mag)-mag/2f);
in.floor = tile.floor(); in.floor = tile.floor;
if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); if(!tile.block.synthetic() && !in.block.synthetic()) in.block = tile.block;
in.ore = tile.ore(); if(!((Floor)in.floor).isLiquid) in.ore = tile.ore;
} }
} }

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.editor.generation;
import io.anuke.arc.Core; import io.anuke.arc.Core;
import io.anuke.arc.function.*; import io.anuke.arc.function.*;
import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.scene.ui.Slider;
import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.ui.dialogs.FloatingDialog;
@@ -16,6 +17,7 @@ public abstract class FilterOption{
public static final Predicate<Block> wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full)); public static final Predicate<Block> wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full));
public abstract void build(Table table); public abstract void build(Table table);
public Runnable changed = () -> {};
static class SliderOption extends FilterOption{ static class SliderOption extends FilterOption{
final String name; final String name;
@@ -35,7 +37,9 @@ public abstract class FilterOption{
public void build(Table table){ public void build(Table table){
table.add(name); table.add(name);
table.row(); table.row();
table.addSlider(min, max, (max-min)/100f, setter).get().setValue(getter.get()); Slider slider = table.addSlider(min, max, (max-min)/200f, setter).growX().get();
slider.setValue(getter.get());
slider.changed(changed);
} }
} }
@@ -54,7 +58,6 @@ public abstract class FilterOption{
@Override @Override
public void build(Table table){ public void build(Table table){
table.add(name + ": ");
table.addButton(b -> { table.addButton(b -> {
b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()).setRegion(supplier.get().icon(Icon.small))).size(8*3); b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()).setRegion(supplier.get().icon(Icon.small))).size(8*3);
}, () -> { }, () -> {
@@ -67,12 +70,15 @@ public abstract class FilterOption{
dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> { dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> {
consumer.accept(block); consumer.accept(block);
dialog.hide(); dialog.hide();
changed.run();
}); });
if(++i % 10 == 0) dialog.cont.row(); if(++i % 10 == 0) dialog.cont.row();
} }
dialog.show(); dialog.show();
}); }).pad(4).margin(12f);
table.add(name);
} }
} }
} }

View File

@@ -1,14 +1,18 @@
package io.anuke.mindustry.editor.generation; package io.anuke.mindustry.editor.generation;
import io.anuke.arc.Core;
import io.anuke.arc.math.Mathf; import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Pack;
import io.anuke.arc.util.noise.RidgedPerlin;
import io.anuke.arc.util.noise.Simplex; import io.anuke.arc.util.noise.Simplex;
import io.anuke.mindustry.editor.MapEditor; import io.anuke.mindustry.editor.MapEditor;
import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.blocks.Floor;
public abstract class GenerateFilter{ public abstract class GenerateFilter{
protected float o = (float)(Math.random()*10000000.0); protected float o = (float)(Math.random()*10000000.0);
protected long seed;
protected GenerateInput in; protected GenerateInput in;
public FilterOption[] options; public FilterOption[] options;
@@ -23,10 +27,26 @@ public abstract class GenerateFilter{
return (float)in.noise.octaveNoise2D(octaves, persistence, 1f/scl, x + o, y + o)*mag; return (float)in.noise.octaveNoise2D(octaves, persistence, 1f/scl, x + o, y + o)*mag;
} }
protected float rnoise(float x, float y, float scl, float mag){
return in.pnoise.getValue((int)(x + o), (int)(y + o), 1f/scl)*mag;
}
public void randomize(){
seed = Mathf.random(99999999);
}
protected float chance(){
return Mathf.randomSeed(Pack.longInt(in.x, in.y + (int)o));
}
public void options(FilterOption... options){ public void options(FilterOption... options){
this.options = options; this.options = options;
} }
public String name(){
return Core.bundle.get("filter." + getClass().getSimpleName().toLowerCase().replace("filter", ""), getClass().getSimpleName().replace("Filter", ""));
}
public final void apply(GenerateInput in){ public final void apply(GenerateInput in){
this.in = in; this.in = in;
apply(); apply();
@@ -42,6 +62,8 @@ public abstract class GenerateFilter{
public Block floor, block, ore; public Block floor, block, ore;
Simplex noise = new Simplex(); Simplex noise = new Simplex();
RidgedPerlin pnoise = new RidgedPerlin(0, 1);
TileProvider buffer;
public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){ public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){
this.editor = editor; this.editor = editor;
@@ -52,12 +74,18 @@ public abstract class GenerateFilter{
this.y = y; this.y = y;
} }
public void randomize(){ public void setFilter(GenerateFilter filter, TileProvider buffer){
noise.setSeed(Mathf.random(99999999)); this.buffer = buffer;
noise.setSeed(filter.seed);
pnoise.setSeed((int)(filter.seed + 1));
} }
Tile tile(double x, double y){ DummyTile tile(float x, float y){
return editor.tile((int)Mathf.clamp(x, 0, editor.width() - 1), (int)Mathf.clamp(y, 0, editor.height() - 1)); return buffer.get(Mathf.clamp((int)x, 0, editor.width() - 1), Mathf.clamp((int)y, 0, editor.height() - 1));
}
public interface TileProvider{
DummyTile get(int x, int y);
} }
} }
} }

View File

@@ -14,9 +14,9 @@ public class NoiseFilter extends GenerateFilter{
{ {
options( options(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 100f), new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 20f), new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f), new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("wall", () -> block, b -> block = b, wallsOnly) new BlockOption("wall", () -> block, b -> block = b, wallsOnly)

View File

@@ -0,0 +1,36 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.editor.generation.FilterOption.BlockOption;
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
import io.anuke.mindustry.world.Block;
import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly;
public class RiverNoiseFilter extends GenerateFilter{
float scl = 40, threshold = 0f, threshold2 = 0.1f;
Block floor = Blocks.water, floor2 = Blocks.deepwater;
{
options(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly)
);
}
@Override
public void apply(){
float noise = rnoise(in.x, in.y, scl, 1f);
if(noise >= threshold){
in.floor = floor;
if(noise >= threshold2){
in.floor = floor2;
}
}
}
}

View File

@@ -0,0 +1,30 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.editor.generation.FilterOption.BlockOption;
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
import io.anuke.mindustry.world.Block;
import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly;
import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly;
public class ScatterFilter extends GenerateFilter{
float chance = 0.1f;
Block floor = Blocks.ice, block = Blocks.icerocks;
{
options(
new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("block", () -> block, b -> block = b, wallsOnly)
);
}
@Override
public void apply(){
if(in.srcfloor == floor && in.srcblock == Blocks.air && chance() <= chance){
in.block = block;
}
}
}

View File

@@ -0,0 +1,41 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.arc.math.Mathf;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.editor.generation.FilterOption.BlockOption;
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
import io.anuke.mindustry.world.Block;
import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly;
import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly;
public class TerrainFilter extends GenerateFilter{
float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, circleScl = 2.1f;
Block floor = Blocks.stone, block = Blocks.rocks;
{
options(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("circle scale", () -> circleScl, f -> circleScl = f, 0f, 3f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("wall", () -> block, b -> block = b, wallsOnly)
);
}
@Override
public void apply(){
float noise = noise(in.x, in.y, scl, 1f, octaves, falloff) + Mathf.dst((float) in.x / in.editor.width(), (float) in.y / in.editor.height(), 0.5f, 0.5f) * circleScl;
in.floor = floor;
in.ore = Blocks.air;
if(noise >= threshold){
in.block = block;
}else{
in.block = Blocks.air;
}
}
}

View File

@@ -1,25 +0,0 @@
package io.anuke.mindustry.world;
import io.anuke.mindustry.game.Team;
public class DummyTile extends Tile{
public DummyTile(int x, int y){
super(x, y);
}
@Override
public Team getTeam(){
return Team.all[getTeamID()];
}
@Override
protected void changed(){
//nothing matters
}
@Override
protected void preChanged(){
//it really doesn't
}
}

View File

@@ -144,6 +144,7 @@ public class PowerGraph{
public void update(){ public void update(){
if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){ if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){
powerBalance.addValue(0f);
return; return;
} }