Scale waves based on difficulty; improve map editor
@ -79,7 +79,7 @@ project(":core") {
|
||||
apply plugin: "java"
|
||||
|
||||
dependencies {
|
||||
compile 'com.github.anuken:ucore:283ecacfef'
|
||||
compile 'com.github.anuken:ucore:9c523c4'
|
||||
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||
compile "com.badlogicgames.gdx:gdx-ai:1.8.1"
|
||||
}
|
||||
|
BIN
core/assets-raw/sprites/ui/icon-fill.png
Executable file
After Width: | Height: | Size: 255 B |
BIN
core/assets-raw/sprites/ui/icon-loading.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
core/assets-raw/sprites/ui/icon-pencil.png
Executable file
After Width: | Height: | Size: 247 B |
BIN
core/assets-raw/sprites/ui/icon-pick.png
Executable file
After Width: | Height: | Size: 236 B |
BIN
core/assets-raw/sprites/ui/icon-redo.png
Executable file
After Width: | Height: | Size: 245 B |
BIN
core/assets-raw/sprites/ui/icon-undo.png
Executable file
After Width: | Height: | Size: 238 B |
BIN
core/assets-raw/sprites/ui/icon-zoom.png
Executable file
After Width: | Height: | Size: 244 B |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 79 KiB |
@ -16,8 +16,8 @@ import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.*;
|
||||
import io.anuke.mindustry.entities.effect.Fx;
|
||||
import io.anuke.mindustry.entities.effect.Shield;
|
||||
import io.anuke.mindustry.entities.enemies.BlastEnemy;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.entities.enemies.FortressEnemy;
|
||||
import io.anuke.mindustry.entities.enemies.HealerEnemy;
|
||||
import io.anuke.mindustry.input.AndroidInput;
|
||||
import io.anuke.mindustry.input.DesktopInput;
|
||||
@ -471,7 +471,7 @@ public class Control extends Module{
|
||||
new HealerEnemy().set(player.x, player.y).add();
|
||||
}else{
|
||||
float px = player.x, py = player.y;
|
||||
Timers.run(30f, ()-> new BlastEnemy().set(px, py).add());
|
||||
Timers.run(30f, ()-> new FortressEnemy().set(px, py).add());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -546,7 +546,7 @@ public class Renderer extends RendererModule{
|
||||
Draw.dashCircle(spawn.start.worldx(), spawn.start.worldy(), enemyspawnspace);
|
||||
}
|
||||
|
||||
}else if(player.breakMode.delete && control.input.drawPlace()){
|
||||
}else if(player.breakMode.delete && control.input.drawPlace() && player.recipe == null){ //TODO test!
|
||||
player.breakMode.draw(control.input.getBlockX(), control.input.getBlockY(),
|
||||
control.input.getBlockEndX(), control.input.getBlockEndY());
|
||||
}
|
||||
|
@ -448,6 +448,14 @@ public class UI extends SceneModule{
|
||||
public void showEditor(){
|
||||
editorDialog.show();
|
||||
}
|
||||
|
||||
public MapEditorDialog getEditor(){
|
||||
return editorDialog;
|
||||
}
|
||||
|
||||
public boolean isEditing(){
|
||||
return editorDialog.getScene() != null;
|
||||
}
|
||||
|
||||
public void updateItems(){
|
||||
((HudFragment)hudfrag).updateItems();
|
||||
|
@ -1,15 +0,0 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.ucore.modules.ModuleCore;
|
||||
|
||||
public class Editor extends ModuleCore{
|
||||
public static EditorControl control;
|
||||
public static EditorUI ui;
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
module(control = new EditorControl());
|
||||
module(ui = new EditorUI());
|
||||
}
|
||||
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.*;
|
||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Generator;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.mindustry.world.blocks.types.Floor;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.graphics.Pixmaps;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.noise.RidgedPerlin;
|
||||
import io.anuke.ucore.noise.Simplex;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class EditorControl extends Module{
|
||||
private ObjectIntMap<Block> colors = new ObjectIntMap<>();
|
||||
Pixmap pixmap;
|
||||
Texture texture;
|
||||
Simplex sim = new Simplex();
|
||||
RidgedPerlin rid = new RidgedPerlin(1, 10, 20f);
|
||||
RidgedPerlin rid2 = new RidgedPerlin(1, 6, 1f);
|
||||
RidgedPerlin rid3 = new RidgedPerlin(1, 6, 1f);
|
||||
String map = "fortress";
|
||||
ObjectMap<String, Boolean> prefs = new OrderedMap<String, Boolean>(){
|
||||
{
|
||||
put("replace", true);
|
||||
put("terrain", false);
|
||||
put("circle", false);
|
||||
put("distort", false);
|
||||
put("sand", false);
|
||||
put("grass", false);
|
||||
put("stone", false);
|
||||
put("allgrass", false);
|
||||
put("allsnow", false);
|
||||
put("allsand", false);
|
||||
put("lavarock", false);
|
||||
put("water", false);
|
||||
put("oil", false);
|
||||
put("lavariver", false);
|
||||
put("slavariver", false);
|
||||
put("river", false);
|
||||
put("iceriver", false);
|
||||
put("oilriver", false);
|
||||
}
|
||||
};
|
||||
|
||||
public EditorControl() {
|
||||
IntMap.Keys keys = Generator.colors.keys();
|
||||
|
||||
for(int key = keys.next(); keys.hasNext; key = keys.next()){
|
||||
colors.put(Generator.colors.get(key), key);
|
||||
}
|
||||
loadMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
clearScreen();
|
||||
|
||||
if(Inputs.keyUp(Keys.ESCAPE)){
|
||||
Gdx.app.exit();
|
||||
}
|
||||
|
||||
if(Core.scene.getKeyboardFocus() == null){
|
||||
if(Inputs.keyUp(Keys.R)){
|
||||
randomize();
|
||||
loadMap(map);
|
||||
}
|
||||
|
||||
if(Inputs.keyUp(Keys.E)){
|
||||
try{
|
||||
ClassReflection.getMethod(ClassReflection.forName("com.badlogic.gdx.graphics.PixmapIO"), "writePNG", FileHandle.class, Pixmap.class)
|
||||
.invoke(Gdx.files.absolute("/home/anuke/Pictures/maps/out-" + TimeUtils.millis() + ".png"), pixmap);
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void randomize(){
|
||||
sim.setSeed(Mathf.random(999999));
|
||||
rid.setSeed(Mathf.random(999999));
|
||||
rid2.setSeed(Mathf.random(999999));
|
||||
rid3.setSeed(Mathf.random(999999));
|
||||
}
|
||||
|
||||
public void reload(){
|
||||
loadMap(map);
|
||||
}
|
||||
|
||||
public void loadMap(String name){
|
||||
if(pixmap != null)
|
||||
pixmap.dispose();
|
||||
pixmap = new Pixmap(Gdx.files.internal("maps/" + name + ".png"));
|
||||
process();
|
||||
}
|
||||
|
||||
public void process(){
|
||||
if(prefs.get("terrain")){
|
||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||
float dist = Vector2.dst((float) x / pixmap.getWidth(), (float) y / pixmap.getHeight(), 0.5f, 0.5f) * 2f;
|
||||
double noise = sim.octaveNoise2D(6, 0.6, 1 / 180.0, x, y + 9999) / (prefs.get("circle") ? 1.7 : 1f) + dist / 10f;
|
||||
|
||||
if(dist > 0.8){
|
||||
noise += 2 * (dist - 0.8);
|
||||
}
|
||||
|
||||
Block block = noise > 0.6 ? Blocks.stoneblock : Blocks.stone;
|
||||
|
||||
pixmap.drawPixel(x, y, colors.get(block, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pixmap src = Pixmaps.copy(pixmap);
|
||||
|
||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
if(prefs.get("distort")){
|
||||
double intensity = 12;
|
||||
double scale = 80;
|
||||
double octaves = 4;
|
||||
double falloff = 0.6;
|
||||
double nx = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y) - 0.5f) * intensity;
|
||||
double ny = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y + 99999) - 0.5f) * intensity;
|
||||
dx = (int) nx;
|
||||
dy = (int) ny;
|
||||
}
|
||||
|
||||
int pix = src.getPixel(x + dx, y + dy);
|
||||
|
||||
Block block = Generator.colors.get(pix);
|
||||
|
||||
if(block == null)
|
||||
continue;
|
||||
|
||||
boolean floor = block instanceof Floor;
|
||||
|
||||
double noise = sim.octaveNoise2D(4, 0.6, 1 / 170.0, x, y) + sim.octaveNoise2D(1, 1.0, 1 / 5.0, x, y) / 18.0;
|
||||
double nwater = sim.octaveNoise2D(1, 1.0, 1 / 130.0, x, y);
|
||||
noise += nwater / 5.0;
|
||||
|
||||
double noil = sim.octaveNoise2D(1, 1.0, 1 / 150.0, x + 9999, y) + sim.octaveNoise2D(1, 1.0, 1 / 2.0, x, y) / 290.0;
|
||||
|
||||
if(!floor || prefs.get("replace")){
|
||||
|
||||
if(prefs.get("allgrass")){
|
||||
block = floor ? Blocks.grass : Blocks.grassblock;
|
||||
}else if(prefs.get("allsnow")){
|
||||
block = floor ? Blocks.snow : Blocks.snowblock;
|
||||
}else if(prefs.get("allsand")){
|
||||
block = floor ? Blocks.sand : Blocks.sandblock;
|
||||
}else if(prefs.get("replace")){
|
||||
block = floor ? Blocks.stone : Blocks.stoneblock;
|
||||
}
|
||||
|
||||
if(noise > 0.7 && prefs.get("grass")){
|
||||
block = floor ? Blocks.grass : Blocks.grassblock;
|
||||
}
|
||||
if(noise > 0.7 && prefs.get("lavarock")){
|
||||
block = floor ? Blocks.blackstone : Blocks.blackstoneblock;
|
||||
}
|
||||
if(noise > 0.7 && prefs.get("sand")){
|
||||
block = floor ? Blocks.sand : Blocks.sandblock;
|
||||
}
|
||||
if(noise > 0.8 && prefs.get("stone")){
|
||||
block = floor ? Blocks.stone : Blocks.stoneblock;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor){
|
||||
if(nwater > 0.93 && prefs.get("water")){
|
||||
block = Blocks.water;
|
||||
if(nwater > 0.943){
|
||||
block = Blocks.deepwater;
|
||||
}
|
||||
}
|
||||
|
||||
if(noil > 0.95 && prefs.get("oil")){
|
||||
block = Blocks.dirt;
|
||||
if(noil > 0.955){
|
||||
block = Blocks.oil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("lavariver")){
|
||||
double lava = rid.getValue(x, y, 1 / 100f);
|
||||
double t = 0.6;
|
||||
if(lava > t){
|
||||
block = Blocks.lava;
|
||||
}else if(lava > t - 0.2){
|
||||
block = Blocks.blackstone;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("slavariver")){
|
||||
double lava = rid.getValue(x, y, 1 / 40f);
|
||||
double t = 0.7;
|
||||
if(lava > t){
|
||||
block = Blocks.lava;
|
||||
}else if(lava > t - 0.3){
|
||||
block = Blocks.blackstone;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("oilriver")){
|
||||
double lava = rid3.getValue(x, y, 1 / 100f);
|
||||
double t = 0.9;
|
||||
if(lava > t){
|
||||
block = Blocks.oil;
|
||||
}else if(lava > t - 0.2){
|
||||
block = Blocks.dirt;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("river")){
|
||||
double riv = rid2.getValue(x, y, 1 / 140f);
|
||||
double t = 0.4;
|
||||
|
||||
if(riv > t + 0.1){
|
||||
block = Blocks.deepwater;
|
||||
}else if(riv > t){
|
||||
block = Blocks.water;
|
||||
}else if(riv > t - 0.2){
|
||||
block = Blocks.grass;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("iceriver")){
|
||||
double riv = rid2.getValue(x, y, 1 / 140f);
|
||||
double t = 0.4;
|
||||
|
||||
if(riv > t + 0.1){
|
||||
block = Blocks.ice;
|
||||
}else if(riv > t){
|
||||
block = Blocks.ice;
|
||||
}else if(riv > t - 0.2){
|
||||
block = Blocks.snow;
|
||||
}
|
||||
}
|
||||
|
||||
pixmap.drawPixel(x, y, colors.get(block, 0));
|
||||
}
|
||||
}
|
||||
|
||||
src.dispose();
|
||||
|
||||
if(texture != null){
|
||||
texture.dispose();
|
||||
}
|
||||
texture = new Texture(pixmap);
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Buttons;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Scaling;
|
||||
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.graphics.Atlas;
|
||||
import io.anuke.ucore.modules.SceneModule;
|
||||
import io.anuke.ucore.scene.Skin;
|
||||
import io.anuke.ucore.scene.builders.*;
|
||||
import io.anuke.ucore.scene.style.TextureRegionDrawable;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.TextField;
|
||||
|
||||
public class EditorUI extends SceneModule{
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
|
||||
build.begin();
|
||||
new table(){{
|
||||
Image image = new Image();
|
||||
image.update(()-> image.setDrawable(new TextureRegionDrawable(new TextureRegion(Editor.control.texture))));
|
||||
image.setScaling(Scaling.fit);
|
||||
add(image).size(256 * 3);
|
||||
|
||||
new table("button"){{
|
||||
new field(Editor.control.map, text->{
|
||||
if(Gdx.files.internal("maps/" + text + ".png").exists()){
|
||||
Editor.control.map = text;
|
||||
Editor.control.reload();
|
||||
}
|
||||
});
|
||||
row();
|
||||
for(String key : Editor.control.prefs.keys()){
|
||||
new checkbox(key, Editor.control.prefs.get(key), b->{
|
||||
Editor.control.prefs.put(key, b);
|
||||
Editor.control.reload();
|
||||
}).left();
|
||||
row();
|
||||
}
|
||||
margin(16);
|
||||
}}.end();
|
||||
}}.end();
|
||||
build.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
super.update();
|
||||
if(Inputs.buttonUp(Buttons.LEFT)){
|
||||
if(!hasMouse() || !(scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) instanceof TextField)){
|
||||
scene.setKeyboardFocus(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadSkin(){
|
||||
skin = new Skin(Gdx.files.internal("ui/uiskin.json"), new Atlas(Gdx.files.internal("sprites/sprites.atlas")));
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
package io.anuke.mindustry.entities;
|
||||
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class EnemySpawn{
|
||||
private static float[] scalings = {2f, 1.5f, 1f};
|
||||
|
||||
/**The enemy type spawned*/
|
||||
public final Class<? extends Enemy> type;
|
||||
/**When this spawns should end*/
|
||||
@ -33,6 +36,8 @@ public class EnemySpawn{
|
||||
if(wave < after || wave > before || (wave - after) % spacing != 0){
|
||||
return 0;
|
||||
}
|
||||
float scaling = this.scaling * scalings[(Settings.getInt("difficulty"))];
|
||||
|
||||
return Math.min(amount-1 + 1 * Math.max((int)((wave / spacing) / scaling), 1) - (tier(wave, lane)-1) * tierscaleback, max);
|
||||
}
|
||||
|
||||
|
@ -331,6 +331,15 @@ public class Fx{
|
||||
Draw.reset();
|
||||
}),
|
||||
|
||||
shieldhit = new Effect(9, e -> {
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Color.WHITE, Color.SKY, e.ifract());
|
||||
Draw.spikes(e.x, e.y, e.ifract() * 5f, 2, 6);
|
||||
Draw.thickness(4f*e.fract());
|
||||
Draw.circle(e.x, e.y, e.ifract()*14f);
|
||||
Draw.reset();
|
||||
}),
|
||||
|
||||
shoot = new Effect(8, e -> {
|
||||
Draw.thickness(1f);
|
||||
Draw.color(Color.WHITE, Color.GOLD, e.ifract());
|
||||
|
@ -78,7 +78,7 @@ public class AndroidInput extends InputHandler{
|
||||
|
||||
if(!GameState.is(State.menu)){
|
||||
Tile cursor = world.tile(Mathf.scl2(Graphics.mouseWorld().x, tilesize), Mathf.scl2(Graphics.mouseWorld().y, tilesize));
|
||||
if(cursor != null && !ui.hasMouse()){
|
||||
if(cursor != null && !ui.hasMouse(screenX, screenY)){
|
||||
Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor;
|
||||
if(linked != null && linked.block() instanceof Configurable){
|
||||
ui.showConfig(linked);
|
||||
@ -155,7 +155,7 @@ public class AndroidInput extends InputHandler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tryPlaceBlock(int x, int y, boolean sound){
|
||||
public boolean tryPlaceBlock(int x, int y, boolean sound){
|
||||
if(player.recipe != null &&
|
||||
validPlace(x, y, player.recipe.result) && cursorNear() &&
|
||||
Vars.control.hasItems(player.recipe.requirements)){
|
||||
@ -169,6 +169,8 @@ public class AndroidInput extends InputHandler{
|
||||
if(!Vars.control.hasItems(player.recipe.requirements)){
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public class DesktopInput extends InputHandler{
|
||||
|
||||
Tile cursor = world.tile(tilex(), tiley());
|
||||
|
||||
if(Inputs.buttonUp(Buttons.LEFT) && cursor != null){
|
||||
if(Inputs.buttonUp(Buttons.LEFT) && cursor != null && !ui.hasMouse()){
|
||||
Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor;
|
||||
if(linked != null && linked.block() instanceof Configurable){
|
||||
ui.showConfig(linked);
|
||||
|
@ -49,7 +49,7 @@ public abstract class InputHandler extends InputAdapter{
|
||||
return Vector2.dst(player.x, player.y, getBlockX() * tilesize, getBlockY() * tilesize) <= placerange;
|
||||
}
|
||||
|
||||
public void tryPlaceBlock(int x, int y, boolean sound){
|
||||
public boolean tryPlaceBlock(int x, int y, boolean sound){
|
||||
if(player.recipe != null &&
|
||||
validPlace(x, y, player.recipe.result) && !ui.hasMouse() && cursorNear() &&
|
||||
Vars.control.hasItems(player.recipe.requirements)){
|
||||
@ -63,7 +63,9 @@ public abstract class InputHandler extends InputAdapter{
|
||||
if(!Vars.control.hasItems(player.recipe.requirements)){
|
||||
Cursors.restoreCursor();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean tryDeleteBlock(int x, int y, boolean sound){
|
||||
|
@ -306,10 +306,12 @@ public enum PlaceMode{
|
||||
boolean first = true;
|
||||
for(int x = 0; x <= Math.abs(this.endx - this.tilex); x ++){
|
||||
for(int y = 0; y <= Math.abs(this.endy - this.tiley); y ++){
|
||||
control.getInput().tryPlaceBlock(
|
||||
if(control.getInput().tryPlaceBlock(
|
||||
tilex + x * Mathf.sign(endx - tilex),
|
||||
tiley + y * Mathf.sign(endy - tiley), first);
|
||||
first = false;
|
||||
tiley + y * Mathf.sign(endy - tiley), first)){
|
||||
first = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
core/src/io/anuke/mindustry/mapeditor/EditorTool.java
Normal file
@ -0,0 +1,70 @@
|
||||
package io.anuke.mindustry.mapeditor;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.ColorMapper;
|
||||
|
||||
public enum EditorTool{
|
||||
pencil{
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
editor.draw(x, y);
|
||||
}
|
||||
},
|
||||
fill{
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
Pixmap pix = editor.pixmap();
|
||||
|
||||
int dest = pix.getPixel(x, y);
|
||||
|
||||
int width = pix.getWidth();
|
||||
|
||||
IntSet set = new IntSet();
|
||||
Stack<GridPoint2> points = new Stack<GridPoint2>();
|
||||
points.add(new GridPoint2(x, y));
|
||||
|
||||
while( !points.isEmpty()){
|
||||
GridPoint2 pos = points.pop();
|
||||
set.add(asInt(pos.x, pos.y, width));
|
||||
|
||||
int pcolor = pix.getPixel(pos.x, pos.y);
|
||||
if(colorEquals(pcolor, dest)){
|
||||
|
||||
pix.drawPixel(pos.x, pos.y);
|
||||
|
||||
if(pos.x > 0 && !set.contains(asInt(pos.x - 1, pos.y, width))) points.add(new GridPoint2(pos).cpy().add( -1, 0));
|
||||
if(pos.y > 0 && !set.contains(asInt(pos.x, pos.y - 1, width))) points.add(new GridPoint2(pos).cpy().add(0, -1));
|
||||
if(pos.x < pix.getWidth() - 1 && !set.contains(asInt(pos.x + 1, pos.y, width))) points.add(new GridPoint2(pos).cpy().add(1, 0));
|
||||
if(pos.y < pix.getHeight() - 1 && !set.contains(asInt(pos.x, pos.y + 1, width))) points.add(new GridPoint2(pos).cpy().add(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
editor.updateTexture();
|
||||
}
|
||||
|
||||
int asInt(int x, int y, int width){
|
||||
return x+y*width;
|
||||
}
|
||||
|
||||
boolean colorEquals(int a, int b){
|
||||
return a == b;
|
||||
}
|
||||
},
|
||||
pick{
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
Block block = ColorMapper.get(editor.pixmap().getPixel(x, y)).dominant();
|
||||
editor.setDrawBlock(block);
|
||||
Vars.ui.getEditor().updateSelectedBlock();
|
||||
}
|
||||
},
|
||||
zoom;
|
||||
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
|
||||
}
|
||||
}
|
@ -19,6 +19,11 @@ public class MapEditor{
|
||||
private Pixmap[] brushPixmaps = new Pixmap[brushSizes.length];
|
||||
|
||||
private Map map;
|
||||
|
||||
private MapFilter filter = new MapFilter();
|
||||
private Pixmap filterPixmap;
|
||||
private Texture filterTexture;
|
||||
|
||||
private Pixmap pixmap;
|
||||
private Texture texture;
|
||||
private int brushSize = 1;
|
||||
@ -31,6 +36,44 @@ public class MapEditor{
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTexture(){
|
||||
texture.draw(pixmap, 0, 0);
|
||||
}
|
||||
|
||||
public MapFilter getFilter(){
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void applyFilterPreview(){
|
||||
if(filterPixmap != null && (filterPixmap.getWidth() != pixmap.getWidth()
|
||||
|| filterPixmap.getHeight() != pixmap.getHeight())){
|
||||
filterPixmap.dispose();
|
||||
filterTexture.dispose();
|
||||
filterPixmap = null;
|
||||
filterTexture = null;
|
||||
}
|
||||
|
||||
if(filterPixmap == null){
|
||||
filterPixmap = Pixmaps.copy(pixmap);
|
||||
filter.process(filterPixmap);
|
||||
filterTexture = new Texture(filterPixmap);
|
||||
}else{
|
||||
filterPixmap.drawPixmap(pixmap, 0, 0);
|
||||
filter.process(filterPixmap);
|
||||
filterTexture.draw(filterPixmap, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Texture getFilterTexture(){
|
||||
return filterTexture;
|
||||
}
|
||||
|
||||
public void applyFilter(){
|
||||
filter.process(pixmap);
|
||||
texture.draw(pixmap, 0, 0);
|
||||
}
|
||||
|
||||
public void beginEdit(Map map){
|
||||
this.map = map;
|
||||
this.brushSize = 1;
|
||||
@ -87,7 +130,7 @@ public class MapEditor{
|
||||
y = 0;
|
||||
}
|
||||
|
||||
pixmap.fillCircle(dx, dy, brushSize);
|
||||
pixmap.fillCircle(dx, dy, brushSize-1);
|
||||
|
||||
Pixmap dst = brush(brushSize);
|
||||
dst.drawPixmap(pixmap, x, y, dstWidth, dstHeight, 0, 0, dstWidth, dstHeight);
|
||||
@ -109,6 +152,10 @@ public class MapEditor{
|
||||
return texture;
|
||||
}
|
||||
|
||||
public Pixmap pixmap(){
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
public void resize(int mapSize){
|
||||
Pixmap out = Pixmaps.resize(pixmap, mapSize, mapSize);
|
||||
pixmap.dispose();
|
||||
|
@ -5,6 +5,7 @@ import io.anuke.mindustry.world.ColorMapper;
|
||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||
import io.anuke.mindustry.world.Map;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.scene.builders.*;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
@ -14,10 +15,13 @@ import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
public class MapEditorDialog extends Dialog{
|
||||
private MapEditor editor;
|
||||
private MapView view;
|
||||
private MapGenerateDialog dialog;
|
||||
private ButtonGroup<ImageButton> blockgroup;
|
||||
|
||||
public MapEditorDialog(MapEditor editor){
|
||||
super("Map Editor", "dialog");
|
||||
this.editor = editor;
|
||||
dialog = new MapGenerateDialog(editor);
|
||||
view = new MapView(editor);
|
||||
|
||||
setFillParent(true);
|
||||
@ -30,9 +34,23 @@ public class MapEditorDialog extends Dialog{
|
||||
|
||||
shown(() -> {
|
||||
editor.beginEdit(new Map());
|
||||
Core.scene.setScrollFocus(view);
|
||||
});
|
||||
}
|
||||
|
||||
public void updateSelectedBlock(){
|
||||
Block block = editor.getDrawBlock();
|
||||
int i = 0;
|
||||
for(BlockPair pair : ColorMapper.getPairs()){
|
||||
if(pair.wall == block || (pair.wall == Blocks.air && pair.floor == block)){
|
||||
blockgroup.getButtons().get(i).setChecked(true);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void build(){
|
||||
|
||||
new table(){{
|
||||
@ -40,8 +58,15 @@ public class MapEditorDialog extends Dialog{
|
||||
aleft();
|
||||
|
||||
new table(){{
|
||||
|
||||
defaults().growY().width(130f).units(Unit.dp).padBottom(-6);
|
||||
|
||||
new imagebutton("icon-terrain", isize, () -> {
|
||||
dialog.show();
|
||||
}).text("generate").units(Unit.dp);
|
||||
|
||||
row();
|
||||
|
||||
new imagebutton("icon-load", isize, () -> {
|
||||
|
||||
}).text("load map");
|
||||
@ -73,7 +98,7 @@ public class MapEditorDialog extends Dialog{
|
||||
row();
|
||||
|
||||
new imagebutton("icon-arrow-left", isize, () -> {
|
||||
|
||||
hide();
|
||||
}).padBottom(0).text("back");
|
||||
|
||||
}}.left().growY().end();
|
||||
@ -83,9 +108,24 @@ public class MapEditorDialog extends Dialog{
|
||||
}}.grow().end();
|
||||
|
||||
new table(){{
|
||||
new imagebutton("icon-terrain", isize, () -> {
|
||||
Table tools = new Table("button");
|
||||
tools.top();
|
||||
tools.padTop(0).padBottom(6);
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
int i = 0;
|
||||
|
||||
for(EditorTool tool : EditorTool.values()){
|
||||
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
|
||||
button.clicked(() -> view.setTool(tool));
|
||||
button.resizeImage(Unit.dp.inPixels(16*2f));
|
||||
group.add(button);
|
||||
|
||||
}).margin(12f).text("generate...").width(148f).units(Unit.dp);
|
||||
tools.add(button).size(80f, 85f).padBottom(-6f).units(Unit.dp);
|
||||
if(i++ % 2 == 1) tools.row();
|
||||
}
|
||||
|
||||
add(tools).units(Unit.dp).width(160f).padBottom(-6);
|
||||
|
||||
row();
|
||||
|
||||
@ -116,6 +156,7 @@ public class MapEditorDialog extends Dialog{
|
||||
pane.setFadeScrollBars(false);
|
||||
pane.setOverscroll(true, false);
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
blockgroup = group;
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
@ -16,33 +16,37 @@ import io.anuke.ucore.noise.Simplex;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class MapFilter{
|
||||
private ObjectMap<String, Boolean> prefs = new OrderedMap<String, Boolean>(){
|
||||
{
|
||||
put("replace", true);
|
||||
put("terrain", false);
|
||||
put("circle", false);
|
||||
put("distort", false);
|
||||
put("sand", false);
|
||||
put("grass", false);
|
||||
put("stone", false);
|
||||
put("allgrass", false);
|
||||
put("allsnow", false);
|
||||
put("allsand", false);
|
||||
put("lavarock", false);
|
||||
put("water", false);
|
||||
put("oil", false);
|
||||
put("lavariver", false);
|
||||
put("slavariver", false);
|
||||
put("river", false);
|
||||
put("iceriver", false);
|
||||
put("oilriver", false);
|
||||
}
|
||||
};
|
||||
private ObjectMap<String, GenPref> prefs = map(
|
||||
pref("replace", "whether to replace blocks"),
|
||||
pref("terrain", "generate new terrain"),
|
||||
pref("circle", "generate terrain in a circle"),
|
||||
pref("distort", "distort the map image"),
|
||||
pref("sand", "add patches of sand"),
|
||||
pref("grass", "add patches of grass"),
|
||||
pref("stone", "add patches of stone"),
|
||||
pref("blackstone", "add patches of black stone"),
|
||||
pref("allgrass", "fill map with grass"),
|
||||
pref("allsnow", "fill map with snow"),
|
||||
pref("allsand", "fill map with sand"),
|
||||
pref("water", "add lakes"),
|
||||
pref("oil", "add oil lakes"),
|
||||
pref("lavariver", "add lava rivers"),
|
||||
pref("slavariver", "ad small lava rivers"),
|
||||
pref("river", "add rivers"),
|
||||
pref("iceriver", "add frozen rivers"),
|
||||
pref("oilriver", "add oil rivers")
|
||||
);
|
||||
|
||||
private Simplex sim = new Simplex();
|
||||
private RidgedPerlin rid = new RidgedPerlin(1, 10, 20f);
|
||||
private RidgedPerlin rid2 = new RidgedPerlin(1, 6, 1f);
|
||||
private RidgedPerlin rid3 = new RidgedPerlin(1, 6, 1f);
|
||||
|
||||
public MapFilter(){
|
||||
prefs.get("replace").enabled = true;
|
||||
prefs.get("terrain").enabled = true;
|
||||
}
|
||||
|
||||
public void randomize(){
|
||||
sim.setSeed(Mathf.random(999999));
|
||||
rid.setSeed(Mathf.random(999999));
|
||||
@ -50,16 +54,16 @@ public class MapFilter{
|
||||
rid3.setSeed(Mathf.random(999999));
|
||||
}
|
||||
|
||||
public ObjectMap<String, Boolean> getPrefs(){
|
||||
public ObjectMap<String, GenPref> getPrefs(){
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public Pixmap process(Pixmap pixmap){
|
||||
if(prefs.get("terrain")){
|
||||
if(prefs.get("terrain").enabled){
|
||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||
float dist = Vector2.dst((float) x / pixmap.getWidth(), (float) y / pixmap.getHeight(), 0.5f, 0.5f) * 2f;
|
||||
double noise = sim.octaveNoise2D(6, 0.6, 1 / 180.0, x, y + 9999) / (prefs.get("circle") ? 1.7 : 1f) + dist / 10f;
|
||||
double noise = sim.octaveNoise2D(6, 0.6, 1 / 180.0, x, y + 9999) / (prefs.get("circle").enabled ? 1.7 : 1f) + dist / 10f;
|
||||
|
||||
if(dist > 0.8){
|
||||
noise += 2 * (dist - 0.8);
|
||||
@ -78,7 +82,7 @@ public class MapFilter{
|
||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
if(prefs.get("distort")){
|
||||
if(prefs.get("distort").enabled){
|
||||
double intensity = 12;
|
||||
double scale = 80;
|
||||
double octaves = 4;
|
||||
@ -105,41 +109,41 @@ public class MapFilter{
|
||||
|
||||
double noil = sim.octaveNoise2D(1, 1.0, 1 / 150.0, x + 9999, y) + sim.octaveNoise2D(1, 1.0, 1 / 2.0, x, y) / 290.0;
|
||||
|
||||
if(!floor || prefs.get("replace")){
|
||||
if(!floor || prefs.get("replace").enabled){
|
||||
|
||||
if(prefs.get("allgrass")){
|
||||
if(prefs.get("allgrass").enabled){
|
||||
block = floor ? Blocks.grass : Blocks.grassblock;
|
||||
}else if(prefs.get("allsnow")){
|
||||
}else if(prefs.get("allsnow").enabled){
|
||||
block = floor ? Blocks.snow : Blocks.snowblock;
|
||||
}else if(prefs.get("allsand")){
|
||||
}else if(prefs.get("allsand").enabled){
|
||||
block = floor ? Blocks.sand : Blocks.sandblock;
|
||||
}else if(prefs.get("replace")){
|
||||
}else if(prefs.get("replace").enabled){
|
||||
block = floor ? Blocks.stone : Blocks.stoneblock;
|
||||
}
|
||||
|
||||
if(noise > 0.7 && prefs.get("grass")){
|
||||
if(noise > 0.7 && prefs.get("grass").enabled){
|
||||
block = floor ? Blocks.grass : Blocks.grassblock;
|
||||
}
|
||||
if(noise > 0.7 && prefs.get("lavarock")){
|
||||
if(noise > 0.7 && prefs.get("blackstone").enabled){
|
||||
block = floor ? Blocks.blackstone : Blocks.blackstoneblock;
|
||||
}
|
||||
if(noise > 0.7 && prefs.get("sand")){
|
||||
if(noise > 0.7 && prefs.get("sand").enabled){
|
||||
block = floor ? Blocks.sand : Blocks.sandblock;
|
||||
}
|
||||
if(noise > 0.8 && prefs.get("stone")){
|
||||
if(noise > 0.8 && prefs.get("stone").enabled){
|
||||
block = floor ? Blocks.stone : Blocks.stoneblock;
|
||||
}
|
||||
}
|
||||
|
||||
if(floor){
|
||||
if(nwater > 0.93 && prefs.get("water")){
|
||||
if(nwater > 0.93 && prefs.get("water").enabled){
|
||||
block = Blocks.water;
|
||||
if(nwater > 0.943){
|
||||
block = Blocks.deepwater;
|
||||
}
|
||||
}
|
||||
|
||||
if(noil > 0.95 && prefs.get("oil")){
|
||||
if(noil > 0.95 && prefs.get("oil").enabled){
|
||||
block = Blocks.dirt;
|
||||
if(noil > 0.955){
|
||||
block = Blocks.oil;
|
||||
@ -147,7 +151,7 @@ public class MapFilter{
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("lavariver")){
|
||||
if(floor && prefs.get("lavariver").enabled){
|
||||
double lava = rid.getValue(x, y, 1 / 100f);
|
||||
double t = 0.6;
|
||||
if(lava > t){
|
||||
@ -157,7 +161,7 @@ public class MapFilter{
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("slavariver")){
|
||||
if(floor && prefs.get("slavariver").enabled){
|
||||
double lava = rid.getValue(x, y, 1 / 40f);
|
||||
double t = 0.7;
|
||||
if(lava > t){
|
||||
@ -167,7 +171,7 @@ public class MapFilter{
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("oilriver")){
|
||||
if(floor && prefs.get("oilriver").enabled){
|
||||
double lava = rid3.getValue(x, y, 1 / 100f);
|
||||
double t = 0.9;
|
||||
if(lava > t){
|
||||
@ -177,7 +181,7 @@ public class MapFilter{
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("river")){
|
||||
if(floor && prefs.get("river").enabled){
|
||||
double riv = rid2.getValue(x, y, 1 / 140f);
|
||||
double t = 0.4;
|
||||
|
||||
@ -190,7 +194,7 @@ public class MapFilter{
|
||||
}
|
||||
}
|
||||
|
||||
if(floor && prefs.get("iceriver")){
|
||||
if(floor && prefs.get("iceriver").enabled){
|
||||
double riv = rid2.getValue(x, y, 1 / 140f);
|
||||
double t = 0.4;
|
||||
|
||||
@ -211,4 +215,29 @@ public class MapFilter{
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
private static OrderedMap<String, GenPref> map(GenPref...objects){
|
||||
OrderedMap<String, GenPref> prefs = new OrderedMap<>();
|
||||
|
||||
for(int i = 0; i < objects.length; i ++){
|
||||
GenPref pref = (GenPref)objects[i];
|
||||
prefs.put(pref.name, pref);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
private GenPref pref(String name, String desc){
|
||||
return new GenPref(name, desc);
|
||||
}
|
||||
|
||||
class GenPref{
|
||||
public final String name;
|
||||
public final String description;
|
||||
public boolean enabled;
|
||||
|
||||
GenPref(String name, String description){
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,97 @@
|
||||
package io.anuke.mindustry.mapeditor;
|
||||
|
||||
public class MapGenerateDialog{
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Scaling;
|
||||
|
||||
import io.anuke.mindustry.mapeditor.MapFilter.GenPref;
|
||||
import io.anuke.mindustry.ui.BorderImage;
|
||||
import io.anuke.mindustry.ui.FloatingDialog;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.scene.style.TextureRegionDrawable;
|
||||
import io.anuke.ucore.scene.ui.CheckBox;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
|
||||
public class MapGenerateDialog extends FloatingDialog{
|
||||
private MapEditor editor;
|
||||
private Image image;
|
||||
private boolean loading;
|
||||
|
||||
public MapGenerateDialog(MapEditor editor) {
|
||||
super("generate");
|
||||
this.editor = editor;
|
||||
|
||||
Stack stack = new Stack();
|
||||
stack.add(image = new BorderImage());
|
||||
|
||||
Image loadImage = new Image("icon-loading");
|
||||
loadImage.setScaling(Scaling.none);
|
||||
loadImage.setScale(3f);
|
||||
loadImage.update(() -> loadImage.setOrigin(Align.center));
|
||||
loadImage.setVisible(() -> loading);
|
||||
Image next = new Image("white");
|
||||
next.setScaling(Scaling.fit);
|
||||
next.setColor(0, 0, 0, 0.6f);
|
||||
next.setVisible(() -> loading);
|
||||
|
||||
stack.add(next);
|
||||
stack.add(loadImage);
|
||||
|
||||
content().add(stack).grow();
|
||||
image.setScaling(Scaling.fit);
|
||||
Table preft = new Table();
|
||||
preft.left();
|
||||
preft.pad(Unit.dp.inPixels(4f)).padRight(Unit.dp.inPixels(25f));
|
||||
|
||||
for(GenPref pref : editor.getFilter().getPrefs().values()){
|
||||
CheckBox box = new CheckBox(pref.name);
|
||||
box.setChecked(pref.enabled);
|
||||
box.changed(() -> pref.enabled = box.isChecked());
|
||||
preft.add(box).pad(4f).units(Unit.dp).left();
|
||||
preft.row();
|
||||
}
|
||||
|
||||
ScrollPane pane = new ScrollPane(preft, "volume");
|
||||
pane.setFadeScrollBars(false);
|
||||
pane.setScrollingDisabled(true, false);
|
||||
|
||||
content().add(pane).fillY();
|
||||
|
||||
buttons().defaults().size(170f, 50f).units(Unit.dp).pad(4f);
|
||||
buttons().addButton("Back", () -> hide());
|
||||
buttons().addButton("Randomize", () ->{
|
||||
editor.getFilter().randomize();
|
||||
apply();
|
||||
});
|
||||
buttons().addButton("Update", () ->{
|
||||
apply();
|
||||
});
|
||||
buttons().addButton("Apply", () ->{
|
||||
editor.applyFilter();
|
||||
hide();
|
||||
});
|
||||
|
||||
shown(() ->{
|
||||
loading = true;
|
||||
Timers.run(30f, () -> {
|
||||
editor.applyFilterPreview();
|
||||
image.setDrawable(new TextureRegionDrawable(new TextureRegion(editor.getFilterTexture())));
|
||||
loading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void apply(){
|
||||
loading = true;
|
||||
Timers.run(3f, ()->{
|
||||
editor.applyFilterPreview();
|
||||
loading = false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,21 +1,42 @@
|
||||
package io.anuke.mindustry.mapeditor;
|
||||
|
||||
import com.badlogic.gdx.graphics.Colors;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.input.GestureDetector;
|
||||
import com.badlogic.gdx.input.GestureDetector.GestureListener;
|
||||
import com.badlogic.gdx.math.Bresenham2;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.event.InputEvent;
|
||||
import io.anuke.ucore.scene.event.InputListener;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Tmp;
|
||||
|
||||
public class MapView extends Element{
|
||||
public class MapView extends Element implements GestureListener{
|
||||
private MapEditor editor;
|
||||
private EditorTool tool = EditorTool.pencil;
|
||||
private Bresenham2 br = new Bresenham2();
|
||||
private float offsetx, offsety;
|
||||
private float zoom = 1f;
|
||||
|
||||
public void setTool(EditorTool tool){
|
||||
this.tool = tool;
|
||||
}
|
||||
|
||||
public MapView(MapEditor editor){
|
||||
this.editor = editor;
|
||||
|
||||
Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));
|
||||
|
||||
addListener(new InputListener(){
|
||||
int lastx, lasty;
|
||||
boolean drawing;
|
||||
@ -25,7 +46,9 @@ public class MapView extends Element{
|
||||
GridPoint2 p = project(x, y);
|
||||
lastx = p.x;
|
||||
lasty = p.y;
|
||||
editor.draw(p.x, p.y);
|
||||
tool.touched(editor, p.x, p.y);
|
||||
|
||||
drawing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -38,29 +61,131 @@ public class MapView extends Element{
|
||||
public void touchDragged (InputEvent event, float x, float y, int pointer) {
|
||||
GridPoint2 p = project(x, y);
|
||||
|
||||
if(drawing){
|
||||
if(drawing && tool == EditorTool.pencil){
|
||||
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
|
||||
for(GridPoint2 point : points){
|
||||
editor.draw(point.x, point.y);
|
||||
}
|
||||
}
|
||||
drawing = true;
|
||||
lastx = p.x;
|
||||
lasty = p.y;
|
||||
}
|
||||
});
|
||||
|
||||
addListener(new InputListener(){
|
||||
@Override
|
||||
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
|
||||
return tool == EditorTool.zoom;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void touchDragged (InputEvent event, float x, float y, int pointer) {
|
||||
//offsetx += Gdx.input.getDeltaX(pointer) / zoom;
|
||||
//offsety -= Gdx.input.getDeltaY(pointer) / zoom;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(float delta){
|
||||
super.act(delta);
|
||||
|
||||
float size = Math.min(width, height);
|
||||
offsetx = Mathf.clamp(offsetx, -size, size);
|
||||
offsety = Mathf.clamp(offsety, -size, size);
|
||||
|
||||
if(tool != EditorTool.zoom) return;
|
||||
|
||||
zoom += Inputs.scroll()/10f * zoom;
|
||||
clampZoom();
|
||||
}
|
||||
|
||||
private void clampZoom(){
|
||||
zoom = Mathf.clamp(zoom, 0.4f, 6f);
|
||||
}
|
||||
|
||||
private GridPoint2 project(float x, float y){
|
||||
float size = Math.min(width, height);
|
||||
x = (x - getWidth()/2 + size/2) / size * editor.texture().getWidth();
|
||||
y = (y - getHeight()/2 + size/2) / size * editor.texture().getHeight();
|
||||
float size = Math.min(width, height)*zoom;
|
||||
x = (x - getWidth()/2 + size/2 - offsetx*zoom) / size * editor.texture().getWidth();
|
||||
y = (y - getHeight()/2 + size/2 - offsety*zoom) / size * editor.texture().getHeight();
|
||||
return Tmp.g1.set((int)x, editor.texture().getHeight() - 1 - (int)y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float alpha){
|
||||
float size = Math.min(width, height);
|
||||
batch.draw(editor.texture(), x + width/2 - size/2, y + height/2 - size/2, size, size);
|
||||
float sclsize = size * zoom;
|
||||
float centerx = x + width/2 + offsetx * zoom;
|
||||
float centery = y + height/2 + offsety * zoom;
|
||||
|
||||
batch.flush();
|
||||
ScissorStack.pushScissors(Tmp.r1.set(x + width/2 - size/2, y + height/2 - size/2, size, size));
|
||||
|
||||
batch.draw(editor.texture(), centerx - sclsize/2, centery - sclsize/2, sclsize, sclsize);
|
||||
batch.flush();
|
||||
|
||||
ScissorStack.popScissors();
|
||||
|
||||
Draw.color(Colors.get("accent"));
|
||||
Draw.thick(Unit.dp.inPixels(3f));
|
||||
Draw.linerect(x + width/2 - size/2, y + height/2 - size/2, size, size);
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
private boolean active(){
|
||||
return Core.scene.getKeyboardFocus().isDescendantOf(Vars.ui.getEditor()) && Vars.ui.isEditing() && tool == EditorTool.zoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDown(float x, float y, int pointer, int button){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tap(float x, float y, int count, int button){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean longPress(float x, float y){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fling(float velocityX, float velocityY, int button){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pan(float x, float y, float deltaX, float deltaY){
|
||||
if(!active()) return false;
|
||||
offsetx += deltaX / zoom;
|
||||
offsety -= deltaY / zoom;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean panStop(float x, float y, int pointer, int button){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean zoom(float initialDistance, float distance){
|
||||
if(!active()) return false;
|
||||
float nzoom = distance - initialDistance;
|
||||
zoom += nzoom / 2000f / Unit.dp.inPixels(1f) * zoom;
|
||||
clampZoom();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pinchStop(){
|
||||
|
||||
}
|
||||
}
|
||||
|
24
core/src/io/anuke/mindustry/ui/BorderImage.java
Normal file
@ -0,0 +1,24 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.graphics.Colors;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
|
||||
public class BorderImage extends Image{
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch, float alpha){
|
||||
super.draw(batch, alpha);
|
||||
|
||||
float scaleX = getScaleX();
|
||||
float scaleY = getScaleY();
|
||||
|
||||
Draw.color(Colors.get("accent"));
|
||||
Draw.thick(Unit.dp.inPixels(3f));
|
||||
Draw.linerect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
@ -69,6 +69,10 @@ public class ColorMapper{
|
||||
public static class BlockPair{
|
||||
public final Block floor, wall;
|
||||
|
||||
public Block dominant(){
|
||||
return wall == Blocks.air ? floor : wall;
|
||||
}
|
||||
|
||||
private BlockPair(Block floor, Block wall){
|
||||
this.floor = floor;
|
||||
this.wall = wall;
|
||||
|
@ -55,7 +55,7 @@ public class ProductionBlocks{
|
||||
requirements = new Item[]{Item.coal, Item.iron};
|
||||
result = Item.steel;
|
||||
description = "Converts coal + iron to steel.";
|
||||
fullDescription = "The essential crafting block. When inputted 1x iron and 1x iron, outputs one steel.";
|
||||
fullDescription = "The essential crafting block. When inputted 1x iron and 1x coal, outputs one steel.";
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class ShieldBlock extends PowerBlock{
|
||||
}
|
||||
|
||||
bullet.remove();
|
||||
Effects.effect(Fx.laserhit, bullet);
|
||||
Effects.effect(bullet.damage > 5 ? Fx.shieldhit : Fx.laserhit, bullet);
|
||||
Vars.renderer.addShieldHit(bullet.x, bullet.y);
|
||||
|
||||
entity.power -= bullet.getDamage() * powerPerDamage;
|
||||
|
@ -31,7 +31,6 @@ public class TunnelConveyor extends Block{
|
||||
if(to == null || to.entity == null) return;
|
||||
to.block().handleItem(item, to, tunnel);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,18 +0,0 @@
|
||||
package io.anuke.mindustry.desktop;
|
||||
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
|
||||
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
||||
|
||||
import io.anuke.mindustry.editor.Editor;
|
||||
|
||||
public class EditorLauncher{
|
||||
public static void main (String[] arg) {
|
||||
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
|
||||
config.setTitle("Mindustry Editor");
|
||||
config.setMaximized(true);
|
||||
config.setWindowedMode(800, 600);
|
||||
config.setWindowIcon("sprites/icon.png");
|
||||
|
||||
new Lwjgl3Application(new Editor(), config);
|
||||
}
|
||||
}
|