Added mirror tool for attack/PvP maps

This commit is contained in:
Anuken
2019-07-24 12:07:12 -04:00
parent c80be4940f
commit b99b13a6e4
8 changed files with 104 additions and 15 deletions

View File

@ -277,6 +277,7 @@ filter.option.threshold = Threshold
filter.option.circle-scale = Circle Scale
filter.option.octaves = Octaves
filter.option.falloff = Falloff
filter.option.angle = Angle
filter.option.block = Block
filter.option.floor = Floor
filter.option.flooronto = Target Floor

Binary file not shown.

Binary file not shown.

View File

@ -30,7 +30,8 @@ import static io.anuke.mindustry.Vars.*;
public class MapGenerateDialog extends FloatingDialog{
private final Supplier<GenerateFilter>[] filterTypes = new Supplier[]{
NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new,
RiverNoiseFilter::new, OreFilter::new, MedianFilter::new, BlendFilter::new
RiverNoiseFilter::new, OreFilter::new, MedianFilter::new, BlendFilter::new,
MirrorFilter::new
};
private final MapEditor editor;
@ -84,9 +85,19 @@ public class MapGenerateDialog extends FloatingDialog{
cont.clear();
cont.table(t -> {
t.margin(8f);
t.stack(new BorderImage(texture){{
t.stack(new BorderImage(texture){
{
setScaling(Scaling.fit);
}}, new Stack(){{
}
@Override
public void draw(){
super.draw();
for(GenerateFilter filter : filters){
filter.draw(this);
}
}
}, new Stack(){{
add(new Image("loadDim"));
add(new Image("icon-refresh"){{
setScaling(Scaling.none);

View File

@ -24,28 +24,32 @@ public abstract class FilterOption{
public abstract void build(Table table);
public Runnable changed = () -> {
};
public Runnable changed = () -> {};
static class SliderOption extends FilterOption{
final String name;
final FloatProvider getter;
final FloatConsumer setter;
final float min, max;
final float min, max, step;
SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max){
this(name, getter, setter, min, max, (max - min) / 200);
}
SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max, float step){
this.name = name;
this.getter = getter;
this.setter = setter;
this.min = min;
this.max = max;
this.step = step;
}
@Override
public void build(Table table){
table.add("$filter.option." + name);
table.row();
Slider slider = table.addSlider(min, max, (max - min) / 200f, setter).growX().get();
Slider slider = table.addSlider(min, max, step, setter).growX().get();
slider.setValue(getter.get());
if(updateEditorOnChange){
slider.changed(changed);

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.editor.generation;
import io.anuke.arc.Core;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.util.Pack;
import io.anuke.arc.util.noise.RidgedPerlin;
import io.anuke.arc.util.noise.Simplex;
@ -20,6 +21,9 @@ public abstract class GenerateFilter{
protected abstract void apply();
//draw any additional guides
public void draw(Image image){}
protected float noise(float x, float y, float scl, float mag){
return (float)in.noise.octaveNoise2D(1f, 0f, 1f / scl, x + o, y + o) * mag;
}

View File

@ -0,0 +1,69 @@
package io.anuke.mindustry.editor.generation;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.editor.MapGenerateDialog.*;
import io.anuke.mindustry.editor.generation.FilterOption.*;
import io.anuke.mindustry.graphics.*;
import static io.anuke.mindustry.Vars.content;
public class MirrorFilter extends GenerateFilter{
private final Vector2 v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2();
float angle = 45;
{
options(new SliderOption("angle", () -> angle, f -> angle = f, 0, 360, 45));
}
@Override
protected void apply(){
v1.trns(angle - 90, 1f);
v2.set(v1).scl(-1f);
v1.add(in.width/2f, in.height/2f);
v2.add(in.width/2f, in.height/2f);
v3.set(in.x / in.scaling, in.y / in.scaling);
if(!left(v1, v2, v3)){
mirror(v3, v1.x, v1.y, v2.x, v2.y);
GenTile tile = in.tile(v3.x, v3.y);
in.floor = content.block(tile.floor);
in.block = content.block(tile.block);
in.ore = content.block(tile.ore);
}
}
@Override
public void draw(Image image){
super.draw(image);
float size = Math.max(image.getWidth() *2, image.getHeight()*2);
Consumer<Vector2> clamper = v -> v.clamp(image.getX(), image.getX() + image.getWidth(), image.getY(), image.getY() + image.getHeight());
clamper.accept(Tmp.v1.trns(angle - 90, size).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()));
clamper.accept(Tmp.v2.set(Tmp.v1).sub(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()).rotate(180f).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()));
Lines.stroke(Unit.dp.scl(3f), Pal.accent);
Lines.line(Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y);
Draw.reset();
}
void mirror(Vector2 p, float x0, float y0, float x1, float y1){
float dx = x1 - x0;
float dy = y1 - y0;
float a = (dx * dx - dy * dy) / (dx * dx + dy*dy);
float b = 2 * dx * dy / (dx*dx + dy*dy);
p.set((a * (p.x - x0) + b*(p.y - y0) + x0), (b * (p.x - x0) - a*(p.y - y0) + y0));
}
boolean left(Vector2 a, Vector2 b, Vector2 c){
return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0;
}
}

View File

@ -1,14 +1,12 @@
package io.anuke.mindustry.type;
import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.IntMap;
import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.game.Content;
import io.anuke.arc.collection.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
import io.anuke.mindustry.world.blocks.storage.*;
import static io.anuke.mindustry.Vars.defaultTeam;
import static io.anuke.mindustry.Vars.world;
import static io.anuke.mindustry.Vars.*;
public class Loadout extends Content{
private final Array<Tile> outArray = new Array<>();
@ -70,6 +68,8 @@ public class Loadout extends Content{
int rx = Pos.x(entry.key);
int ry = Pos.y(entry.key);
Tile tile = world.tile(x + rx, y + ry);
if(tile == null) continue;
world.setBlock(tile, entry.value.block, defaultTeam);
tile.rotation((byte)entry.value.rotation);
if(entry.value.ore != null){