Finish map editor core functionality
@@ -16,7 +16,7 @@ allprojects {
|
|||||||
apply plugin: "eclipse"
|
apply plugin: "eclipse"
|
||||||
apply plugin: "idea"
|
apply plugin: "idea"
|
||||||
|
|
||||||
version = '1.0'
|
version = 'release'
|
||||||
ext {
|
ext {
|
||||||
appName = "Mindustry"
|
appName = "Mindustry"
|
||||||
gdxVersion = '1.9.6'
|
gdxVersion = '1.9.6'
|
||||||
|
|||||||
BIN
core/assets-raw/sprites/blocks/enemyspawn.png
Normal file
|
After Width: | Height: | Size: 240 B |
BIN
core/assets-raw/sprites/blocks/playerspawn.png
Normal file
|
After Width: | Height: | Size: 239 B |
|
Before Width: | Height: | Size: 98 B After Width: | Height: | Size: 185 B |
|
Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 202 B |
|
Before Width: | Height: | Size: 209 B After Width: | Height: | Size: 209 B |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 70 B |
|
Before Width: | Height: | Size: 131 B After Width: | Height: | Size: 131 B |
@@ -87,7 +87,7 @@
|
|||||||
{
|
{
|
||||||
"id": 12,
|
"id": 12,
|
||||||
"name": "tutorial",
|
"name": "tutorial",
|
||||||
"visible": true,
|
"visible": false,
|
||||||
"flipBase": false,
|
"flipBase": false,
|
||||||
"backgroundColor": "646464"
|
"backgroundColor": "646464"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@@ -49,6 +49,7 @@ io.anuke.ucore.scene.ui.ImageTextButton$ImageTextButtonStyle: {
|
|||||||
},
|
},
|
||||||
io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: {
|
io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: {
|
||||||
default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
|
default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
|
||||||
|
horizontal: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal},
|
||||||
volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
|
volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
|
||||||
clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical}
|
clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ public class Mindustry extends ModuleCore {
|
|||||||
DefenseBlocks.compositewall,
|
DefenseBlocks.compositewall,
|
||||||
DistributionBlocks.conduit,
|
DistributionBlocks.conduit,
|
||||||
ProductionBlocks.coaldrill,
|
ProductionBlocks.coaldrill,
|
||||||
WeaponBlocks.chainturret
|
WeaponBlocks.chainturret,
|
||||||
|
SpecialBlocks.enemySpawn
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void play(){
|
public void play(){
|
||||||
|
if(core == null) return;
|
||||||
|
|
||||||
renderer.clearTiles();
|
renderer.clearTiles();
|
||||||
|
|
||||||
player.x = core.worldx();
|
player.x = core.worldx();
|
||||||
@@ -435,7 +437,7 @@ public class Control extends Module{
|
|||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
|
|
||||||
if(debug){
|
if(debug && GameState.is(State.playing)){
|
||||||
//debug actions
|
//debug actions
|
||||||
if(Inputs.keyUp(Keys.P)){
|
if(Inputs.keyUp(Keys.P)){
|
||||||
Effects.effect(Fx.shellsmoke, player);
|
Effects.effect(Fx.shellsmoke, player);
|
||||||
|
|||||||
@@ -449,10 +449,18 @@ public class UI extends SceneModule{
|
|||||||
editorDialog.show();
|
editorDialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapEditorDialog getEditor(){
|
public MapEditorDialog getEditorDialog(){
|
||||||
return editorDialog;
|
return editorDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapEditor getEditor(){
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadLevels(){
|
||||||
|
((LevelDialog)levels).reload();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEditing(){
|
public boolean isEditing(){
|
||||||
return editorDialog.getScene() != null;
|
return editorDialog.getScene() != null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,8 @@ public class World extends Module{
|
|||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
Generator.generate(map.pixmap, tiles);
|
Generator.generate(map.pixmap, tiles);
|
||||||
|
|
||||||
|
if(control.getCore() == null) return;
|
||||||
|
|
||||||
//TODO multiblock core
|
//TODO multiblock core
|
||||||
control.getInput().placeBlock(control.getCore().x, control.getCore().y, ProductionBlocks.core, 0, false, false);
|
control.getInput().placeBlock(control.getCore().x, control.getCore().y, ProductionBlocks.core, 0, false, false);
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public enum EditorTool{
|
|||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
Block block = ColorMapper.get(editor.pixmap().getPixel(x, y)).dominant();
|
Block block = ColorMapper.get(editor.pixmap().getPixel(x, y)).dominant();
|
||||||
editor.setDrawBlock(block);
|
editor.setDrawBlock(block);
|
||||||
Vars.ui.getEditor().updateSelectedBlock();
|
Vars.ui.getEditorDialog().updateSelectedBlock();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
zoom;
|
zoom;
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ import io.anuke.mindustry.world.blocks.Blocks;
|
|||||||
import io.anuke.ucore.graphics.Pixmaps;
|
import io.anuke.ucore.graphics.Pixmaps;
|
||||||
|
|
||||||
public class MapEditor{
|
public class MapEditor{
|
||||||
public static final int[] validMapSizes = {64, 128, 256};
|
public static final int[] validMapSizes = {128, 256, 512};
|
||||||
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
|
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
|
||||||
|
public static final int maxSpawnpoints = 15;
|
||||||
|
|
||||||
private Pixmap[] brushPixmaps = new Pixmap[brushSizes.length];
|
private Pixmap[] brushPixmaps = new Pixmap[brushSizes.length];
|
||||||
|
|
||||||
@@ -36,6 +37,10 @@ public class MapEditor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map getMap(){
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateTexture(){
|
public void updateTexture(){
|
||||||
texture.draw(pixmap, 0, 0);
|
texture.draw(pixmap, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -156,10 +161,18 @@ public class MapEditor{
|
|||||||
return pixmap;
|
return pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resize(int mapSize){
|
public void resize(int width, int height){
|
||||||
Pixmap out = Pixmaps.resize(pixmap, mapSize, mapSize);
|
Pixmap out = Pixmaps.resize(pixmap, width, height);
|
||||||
pixmap.dispose();
|
pixmap.dispose();
|
||||||
pixmap = out;
|
pixmap = out;
|
||||||
texture.draw(pixmap, 0, 0);
|
texture.dispose();
|
||||||
|
texture = new Texture(out);
|
||||||
|
|
||||||
|
if(filterPixmap != null){
|
||||||
|
filterPixmap.dispose();
|
||||||
|
filterTexture.dispose();
|
||||||
|
filterPixmap = null;
|
||||||
|
filterTexture = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
package io.anuke.mindustry.mapeditor;
|
package io.anuke.mindustry.mapeditor;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.ColorMapper;
|
import io.anuke.mindustry.world.ColorMapper;
|
||||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||||
import io.anuke.mindustry.world.Map;
|
import io.anuke.mindustry.world.Map;
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.SpecialBlocks;
|
||||||
import io.anuke.ucore.core.Core;
|
import io.anuke.ucore.core.Core;
|
||||||
import io.anuke.ucore.core.Draw;
|
import io.anuke.ucore.core.Draw;
|
||||||
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.scene.builders.*;
|
import io.anuke.ucore.scene.builders.*;
|
||||||
import io.anuke.ucore.scene.ui.*;
|
import io.anuke.ucore.scene.ui.*;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
@@ -16,6 +21,10 @@ public class MapEditorDialog extends Dialog{
|
|||||||
private MapEditor editor;
|
private MapEditor editor;
|
||||||
private MapView view;
|
private MapView view;
|
||||||
private MapGenerateDialog dialog;
|
private MapGenerateDialog dialog;
|
||||||
|
private MapLoadDialog loadDialog;
|
||||||
|
private MapSaveDialog saveDialog;
|
||||||
|
private MapResizeDialog resizeDialog;
|
||||||
|
|
||||||
private ButtonGroup<ImageButton> blockgroup;
|
private ButtonGroup<ImageButton> blockgroup;
|
||||||
|
|
||||||
public MapEditorDialog(MapEditor editor){
|
public MapEditorDialog(MapEditor editor){
|
||||||
@@ -24,6 +33,34 @@ public class MapEditorDialog extends Dialog{
|
|||||||
dialog = new MapGenerateDialog(editor);
|
dialog = new MapGenerateDialog(editor);
|
||||||
view = new MapView(editor);
|
view = new MapView(editor);
|
||||||
|
|
||||||
|
loadDialog = new MapLoadDialog(map -> {
|
||||||
|
editor.beginEdit(map);
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
|
||||||
|
Pixmap pix = editor.pixmap();
|
||||||
|
if(!(pix.getWidth() == x && pix.getHeight() == y)){
|
||||||
|
Vars.ui.showLoading();
|
||||||
|
Timers.run(10f, ()->{
|
||||||
|
editor.resize(x, y);
|
||||||
|
Vars.ui.hideLoading();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
saveDialog = new MapSaveDialog(name -> {
|
||||||
|
Vars.ui.showLoading();
|
||||||
|
if(verifyMap()){
|
||||||
|
editor.getMap().name = name;
|
||||||
|
Timers.run(10f, () -> {
|
||||||
|
Vars.world.maps().saveAndReload(editor.getMap(), editor.pixmap());
|
||||||
|
Vars.ui.hideLoading();
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
Vars.ui.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setFillParent(true);
|
setFillParent(true);
|
||||||
|
|
||||||
clearChildren();
|
clearChildren();
|
||||||
@@ -48,7 +85,6 @@ public class MapEditorDialog extends Dialog{
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(){
|
public void build(){
|
||||||
@@ -68,13 +104,13 @@ public class MapEditorDialog extends Dialog{
|
|||||||
row();
|
row();
|
||||||
|
|
||||||
new imagebutton("icon-load", isize, () -> {
|
new imagebutton("icon-load", isize, () -> {
|
||||||
|
loadDialog.show();
|
||||||
}).text("load map");
|
}).text("load map");
|
||||||
|
|
||||||
row();
|
row();
|
||||||
|
|
||||||
new imagebutton("icon-save", isize, ()->{
|
new imagebutton("icon-save", isize, ()->{
|
||||||
|
saveDialog.show();
|
||||||
}).text("save map");
|
}).text("save map");
|
||||||
|
|
||||||
row();
|
row();
|
||||||
@@ -92,7 +128,7 @@ public class MapEditorDialog extends Dialog{
|
|||||||
row();
|
row();
|
||||||
|
|
||||||
new imagebutton("icon-cursor", 10f*3f, () -> {
|
new imagebutton("icon-cursor", 10f*3f, () -> {
|
||||||
|
resizeDialog.show();
|
||||||
}).text("resize").padTop(4f);
|
}).text("resize").padTop(4f);
|
||||||
|
|
||||||
row();
|
row();
|
||||||
@@ -150,6 +186,38 @@ public class MapEditorDialog extends Dialog{
|
|||||||
}}.grow().end();
|
}}.grow().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean verifyMap(){
|
||||||
|
int psc = ColorMapper.getColor(SpecialBlocks.playerSpawn);
|
||||||
|
int esc = ColorMapper.getColor(SpecialBlocks.enemySpawn);
|
||||||
|
|
||||||
|
int playerSpawns = 0;
|
||||||
|
int enemySpawns = 0;
|
||||||
|
Pixmap pix = editor.pixmap();
|
||||||
|
|
||||||
|
for(int x = 0; x < pix.getWidth(); x ++){
|
||||||
|
for(int y = 0; y < pix.getHeight(); y ++){
|
||||||
|
int i = pix.getPixel(x, y);
|
||||||
|
if(i == psc) playerSpawns ++;
|
||||||
|
if(i == esc) enemySpawns ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(playerSpawns == 0){
|
||||||
|
Vars.ui.showError("This map has no player spawnpoint!");
|
||||||
|
return false;
|
||||||
|
}else if(playerSpawns > 1){
|
||||||
|
Vars.ui.showError("Maps cannot have more than one\nplayer spawnpoint!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enemySpawns > MapEditor.maxSpawnpoints){
|
||||||
|
Vars.ui.showError("Cannot have more than\n" + MapEditor.maxSpawnpoints + " enemy spawnpoints!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void addBlockSelection(Table table){
|
private void addBlockSelection(Table table){
|
||||||
Table content = new Table();
|
Table content = new Table();
|
||||||
ScrollPane pane = new ScrollPane(content, "volume");
|
ScrollPane pane = new ScrollPane(content, "volume");
|
||||||
@@ -174,6 +242,8 @@ public class MapEditorDialog extends Dialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group.getButtons().get(3).setChecked(true);
|
||||||
|
|
||||||
Table extra = new Table("button");
|
Table extra = new Table("button");
|
||||||
extra.addWrap(() -> editor.getDrawBlock().name).width(120f).center();
|
extra.addWrap(() -> editor.getDrawBlock().name).width(120f).center();
|
||||||
table.add(extra).growX();
|
table.add(extra).growX();
|
||||||
|
|||||||
63
core/src/io/anuke/mindustry/mapeditor/MapLoadDialog.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package io.anuke.mindustry.mapeditor;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.ui.BorderImage;
|
||||||
|
import io.anuke.mindustry.ui.FloatingDialog;
|
||||||
|
import io.anuke.mindustry.world.Map;
|
||||||
|
import io.anuke.ucore.function.Consumer;
|
||||||
|
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||||
|
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||||
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
|
||||||
|
public class MapLoadDialog extends FloatingDialog{
|
||||||
|
Map selected = Vars.world.maps().getMap(0);
|
||||||
|
|
||||||
|
public MapLoadDialog(Consumer<Map> loader) {
|
||||||
|
super("load map");
|
||||||
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
|
|
||||||
|
int maxcol = 3;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
Table table = new Table();
|
||||||
|
table.defaults().size(200f, 90f).units(Unit.dp).pad(4f);
|
||||||
|
table.pad(Unit.dp.inPixels(10f));
|
||||||
|
|
||||||
|
ScrollPane pane = new ScrollPane(table, "horizontal");
|
||||||
|
pane.setFadeScrollBars(false);
|
||||||
|
|
||||||
|
for(Map map : Vars.world.maps().list()){
|
||||||
|
if(!map.visible) continue;
|
||||||
|
|
||||||
|
TextButton button = new TextButton(map.name, "toggle");
|
||||||
|
button.add(new BorderImage(map.texture, 2f)).size(Unit.dp.inPixels(16*4f));
|
||||||
|
button.getCells().reverse();
|
||||||
|
button.clicked(() -> selected = map);
|
||||||
|
button.getLabelCell().grow().left().padLeft(5f).units(Unit.dp);
|
||||||
|
group.add(button);
|
||||||
|
table.add(button);
|
||||||
|
if(++i % maxcol == 0) table.row();
|
||||||
|
}
|
||||||
|
|
||||||
|
content().add("Select a map to load:");
|
||||||
|
content().row();
|
||||||
|
content().add(pane);
|
||||||
|
|
||||||
|
TextButton button = new TextButton("Load");
|
||||||
|
button.setDisabled(() -> selected == null);
|
||||||
|
button.clicked(() -> {
|
||||||
|
if(selected != null){
|
||||||
|
loader.accept(selected);
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons().defaults().size(200f, 50f).units(Unit.dp);
|
||||||
|
buttons().addButton("Cancel", this::hide);
|
||||||
|
buttons().add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
67
core/src/io/anuke/mindustry/mapeditor/MapResizeDialog.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package io.anuke.mindustry.mapeditor;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
|
import com.badlogic.gdx.utils.Align;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.ui.FloatingDialog;
|
||||||
|
import io.anuke.ucore.function.BiConsumer;
|
||||||
|
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||||
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
|
||||||
|
public class MapResizeDialog extends FloatingDialog{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
|
||||||
|
super("resize map");
|
||||||
|
shown(() -> {
|
||||||
|
Pixmap pix = editor.pixmap();
|
||||||
|
width = pix.getWidth();
|
||||||
|
height = pix.getHeight();
|
||||||
|
|
||||||
|
Table table = new Table();
|
||||||
|
|
||||||
|
for(int d = 0; d < 2; d ++){
|
||||||
|
boolean w = d == 0;
|
||||||
|
int curr = d == 0 ? pix.getWidth() : pix.getHeight();
|
||||||
|
int idx = 0;
|
||||||
|
for(int i = 0; i < MapEditor.validMapSizes.length; i ++)
|
||||||
|
if(MapEditor.validMapSizes[i] == curr) idx = i;
|
||||||
|
|
||||||
|
table.add(d == 0 ? "Width: ": "Height: ");
|
||||||
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
|
for(int i = 0; i < MapEditor.validMapSizes.length; i ++){
|
||||||
|
int size = MapEditor.validMapSizes[i];
|
||||||
|
TextButton button = new TextButton(size + "", "toggle");
|
||||||
|
button.clicked(() -> {
|
||||||
|
if(w)
|
||||||
|
width = size;
|
||||||
|
else
|
||||||
|
height = size;
|
||||||
|
});
|
||||||
|
group.add(button);
|
||||||
|
if(i == idx) button.setChecked(true);
|
||||||
|
table.add(button).size(100f, 54f).pad(2f).units(Unit.dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.row();
|
||||||
|
}
|
||||||
|
|
||||||
|
content().add(() ->
|
||||||
|
width + height > 512 ? "[scarlet]Warning!\n[]Maps larger than 256 units may be laggy and unstable." : ""
|
||||||
|
).get().setAlignment(Align.center, Align.center);
|
||||||
|
content().row();
|
||||||
|
content().add(table);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons().defaults().size(200f, 50f).units(Unit.dp);
|
||||||
|
buttons().addButton("Cancel", this::hide);
|
||||||
|
buttons().addButton("Resize", () -> {
|
||||||
|
cons.accept(width, height);
|
||||||
|
hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
57
core/src/io/anuke/mindustry/mapeditor/MapSaveDialog.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package io.anuke.mindustry.mapeditor;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.ui.FloatingDialog;
|
||||||
|
import io.anuke.mindustry.world.Map;
|
||||||
|
import io.anuke.ucore.function.Consumer;
|
||||||
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
|
||||||
|
public class MapSaveDialog extends FloatingDialog{
|
||||||
|
private TextField field;
|
||||||
|
|
||||||
|
public MapSaveDialog(Consumer<String> cons){
|
||||||
|
super("Save Map");
|
||||||
|
field = new TextField();
|
||||||
|
|
||||||
|
shown(() -> {
|
||||||
|
content().clear();
|
||||||
|
content().add(() ->{
|
||||||
|
Map map = Vars.world.maps().getMap(field.getText());
|
||||||
|
if(map != null){
|
||||||
|
if(map.custom){
|
||||||
|
return "[accent]Warning!\nThis overwrites an existing map.";
|
||||||
|
}else{
|
||||||
|
return "[crimson]Cannot overwrite default map!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}).colspan(2);
|
||||||
|
content().row();
|
||||||
|
content().add("Map Name: ");
|
||||||
|
content().add(field).size(220f, 48f);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons().defaults().size(200f, 50f).pad(2f).units(Unit.dp);
|
||||||
|
buttons().addButton("Cancel", this::hide);
|
||||||
|
|
||||||
|
TextButton button = new TextButton("Save");
|
||||||
|
button.clicked(() -> {
|
||||||
|
if(!invalid()){
|
||||||
|
cons.accept(field.getText());
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
button.setDisabled(this::invalid);
|
||||||
|
buttons().add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean invalid(){
|
||||||
|
if(field.getText().isEmpty()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Map map = Vars.world.maps().getMap(field.getText());
|
||||||
|
return map != null && !map.custom;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,12 +120,12 @@ public class MapView extends Element implements GestureListener{
|
|||||||
float centery = y + height/2 + offsety * zoom;
|
float centery = y + height/2 + offsety * zoom;
|
||||||
|
|
||||||
batch.flush();
|
batch.flush();
|
||||||
ScissorStack.pushScissors(Tmp.r1.set(x + width/2 - size/2, y + height/2 - size/2, size, size));
|
boolean pop = 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.draw(editor.texture(), centerx - sclsize/2, centery - sclsize/2, sclsize, sclsize);
|
||||||
batch.flush();
|
batch.flush();
|
||||||
|
|
||||||
ScissorStack.popScissors();
|
if(pop) ScissorStack.popScissors();
|
||||||
|
|
||||||
Draw.color(Colors.get("accent"));
|
Draw.color(Colors.get("accent"));
|
||||||
Draw.thick(Unit.dp.inPixels(3f));
|
Draw.thick(Unit.dp.inPixels(3f));
|
||||||
@@ -134,7 +134,7 @@ public class MapView extends Element implements GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean active(){
|
private boolean active(){
|
||||||
return Core.scene.getKeyboardFocus().isDescendantOf(Vars.ui.getEditor()) && Vars.ui.isEditing() && tool == EditorTool.zoom;
|
return Core.scene.getKeyboardFocus() != null && Core.scene.getKeyboardFocus().isDescendantOf(Vars.ui.getEditorDialog()) && Vars.ui.isEditing() && tool == EditorTool.zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.ui;
|
package io.anuke.mindustry.ui;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Colors;
|
import com.badlogic.gdx.graphics.Colors;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
|
|
||||||
import io.anuke.ucore.core.Draw;
|
import io.anuke.ucore.core.Draw;
|
||||||
@@ -8,6 +9,18 @@ import io.anuke.ucore.scene.ui.Image;
|
|||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
|
|
||||||
public class BorderImage extends Image{
|
public class BorderImage extends Image{
|
||||||
|
private float thickness = 3f;
|
||||||
|
|
||||||
|
public BorderImage(){}
|
||||||
|
|
||||||
|
public BorderImage(Texture texture){
|
||||||
|
super(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BorderImage(Texture texture, float thick){
|
||||||
|
super(texture);
|
||||||
|
thickness = thick;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Batch batch, float alpha){
|
public void draw(Batch batch, float alpha){
|
||||||
@@ -17,7 +30,7 @@ public class BorderImage extends Image{
|
|||||||
float scaleY = getScaleY();
|
float scaleY = getScaleY();
|
||||||
|
|
||||||
Draw.color(Colors.get("accent"));
|
Draw.color(Colors.get("accent"));
|
||||||
Draw.thick(Unit.dp.inPixels(3f));
|
Draw.thick(Unit.dp.inPixels(thickness));
|
||||||
Draw.linerect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
|
Draw.linerect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,16 @@ public class LevelDialog extends FloatingDialog{
|
|||||||
super("Level Select");
|
super("Level Select");
|
||||||
getTitleTable().getCell(title()).growX().center();
|
getTitleTable().getCell(title()).growX().center();
|
||||||
getTitleTable().center();
|
getTitleTable().center();
|
||||||
|
addCloseButton();
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload(){
|
||||||
|
content().clear();
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
addCloseButton();
|
|
||||||
Table maps = new Table();
|
Table maps = new Table();
|
||||||
ScrollPane pane = new ScrollPane(maps);
|
ScrollPane pane = new ScrollPane(maps);
|
||||||
pane.setFadeScrollBars(false);
|
pane.setFadeScrollBars(false);
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ import com.badlogic.gdx.utils.IntMap.Entry;
|
|||||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||||
|
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.SpecialBlocks;
|
||||||
|
|
||||||
public class ColorMapper{
|
public class ColorMapper{
|
||||||
private static ObjectIntMap<Block> reverseColors = new ObjectIntMap<>();
|
private static ObjectIntMap<Block> reverseColors = new ObjectIntMap<>();
|
||||||
private static Array<BlockPair> pairs = new Array<>();
|
private static Array<BlockPair> pairs = new Array<>();
|
||||||
private static IntMap<BlockPair> colors = map(
|
private static IntMap<BlockPair> colors = map(
|
||||||
|
"ff0000", pair(Blocks.dirt, SpecialBlocks.enemySpawn),
|
||||||
|
"00ff00", pair(Blocks.stone, SpecialBlocks.playerSpawn),
|
||||||
"323232", pair(Blocks.stone),
|
"323232", pair(Blocks.stone),
|
||||||
"646464", pair(Blocks.stone, Blocks.stoneblock),
|
"646464", pair(Blocks.stone, Blocks.stoneblock),
|
||||||
"50965a", pair(Blocks.grass),
|
"50965a", pair(Blocks.grass),
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ import com.badlogic.gdx.utils.IntMap;
|
|||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.core.GameState;
|
||||||
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.entities.enemies.TargetEnemy;
|
import io.anuke.mindustry.entities.enemies.TargetEnemy;
|
||||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||||
import io.anuke.mindustry.world.blocks.Blocks;
|
import io.anuke.mindustry.world.blocks.Blocks;
|
||||||
|
import io.anuke.mindustry.world.blocks.SpecialBlocks;
|
||||||
import io.anuke.ucore.graphics.Hue;
|
import io.anuke.ucore.graphics.Hue;
|
||||||
import io.anuke.ucore.noise.Noise;
|
import io.anuke.ucore.noise.Noise;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class Generator{
|
public class Generator{
|
||||||
static final int spawn = Color.rgba8888(Color.RED);
|
|
||||||
static final int start = Color.rgba8888(Color.GREEN);
|
|
||||||
static final ObjectMap<Block, Block> rocks = new ObjectMap(){{
|
static final ObjectMap<Block, Block> rocks = new ObjectMap(){{
|
||||||
put(Blocks.stone, Blocks.rock);
|
put(Blocks.stone, Blocks.rock);
|
||||||
put(Blocks.snow, Blocks.icerock);
|
put(Blocks.snow, Blocks.icerock);
|
||||||
@@ -25,6 +26,7 @@ public class Generator{
|
|||||||
|
|
||||||
/**Returns world size.*/
|
/**Returns world size.*/
|
||||||
public static void generate(Pixmap pixmap, Tile[][] tiles){
|
public static void generate(Pixmap pixmap, Tile[][] tiles){
|
||||||
|
boolean hasenemies = true, hascore = false;;
|
||||||
|
|
||||||
Noise.setSeed(Vars.world.getSeed());
|
Noise.setSeed(Vars.world.getSeed());
|
||||||
|
|
||||||
@@ -39,11 +41,16 @@ public class Generator{
|
|||||||
if(pair != null){
|
if(pair != null){
|
||||||
block = pair.wall;
|
block = pair.wall;
|
||||||
floor = pair.floor;
|
floor = pair.floor;
|
||||||
}else if(color == start){
|
}
|
||||||
|
|
||||||
|
if(block == SpecialBlocks.playerSpawn){
|
||||||
|
block = Blocks.air;
|
||||||
Vars.control.setCore(Vars.world.tile(x, y));
|
Vars.control.setCore(Vars.world.tile(x, y));
|
||||||
}else if(color == spawn){
|
hascore = true;
|
||||||
|
}else if(block == SpecialBlocks.enemySpawn){
|
||||||
|
block = Blocks.air;
|
||||||
Vars.control.addSpawnPoint(Vars.world.tile(x, y));
|
Vars.control.addSpawnPoint(Vars.world.tile(x, y));
|
||||||
floor = Blocks.dirt;
|
hasenemies = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block == Blocks.air && Mathf.chance(0.025) && rocks.containsKey(floor)){
|
if(block == Blocks.air && Mathf.chance(0.025) && rocks.containsKey(floor)){
|
||||||
@@ -78,6 +85,16 @@ public class Generator{
|
|||||||
tiles[x][y].setFloor(floor);
|
tiles[x][y].setFloor(floor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!hascore){
|
||||||
|
GameState.set(State.menu);
|
||||||
|
Vars.ui.showError("[orange]Invalid map:[] this map has no core!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!hasenemies){
|
||||||
|
GameState.set(State.menu);
|
||||||
|
Vars.ui.showError("[orange]Invalid map:[] this map has no enemy spawnpoints!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntMap<Block> map(Object...objects){
|
private static IntMap<Block> map(Object...objects){
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.Pixmap;
|
|||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
|
||||||
public class Map{
|
public class Map{
|
||||||
public int id;
|
public int id = -1;
|
||||||
public String name;
|
public String name;
|
||||||
public boolean visible = true;
|
public boolean visible = true;
|
||||||
public boolean flipBase = false;
|
public boolean flipBase = false;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.badlogic.gdx.utils.Json.Serializer;
|
|||||||
import com.badlogic.gdx.utils.JsonWriter.OutputType;
|
import com.badlogic.gdx.utils.JsonWriter.OutputType;
|
||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.graphics.Pixmaps;
|
import io.anuke.ucore.graphics.Pixmaps;
|
||||||
|
|
||||||
public class Maps implements Disposable{
|
public class Maps implements Disposable{
|
||||||
@@ -50,16 +51,58 @@ public class Maps implements Disposable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveAndReload(Map map, Pixmap out){
|
||||||
|
if(map.pixmap != null && out != map.pixmap && map.texture != null){
|
||||||
|
map.texture.dispose();
|
||||||
|
map.texture = new Texture(out);
|
||||||
|
}else if (out == map.pixmap){
|
||||||
|
map.texture.draw(out, 0, 0);
|
||||||
|
}
|
||||||
|
map.pixmap = out;
|
||||||
|
if(map.texture == null) map.texture = new Texture(map.pixmap);
|
||||||
|
|
||||||
|
if(map.id == -1){
|
||||||
|
if(mapNames.containsKey(map.name)){
|
||||||
|
map.id = mapNames.get(map.name).id;
|
||||||
|
}else{
|
||||||
|
map.id = ++lastID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Settings.has("hiscore" + map.name)){
|
||||||
|
Settings.defaults("hiscore" + map.name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveCustomMap(map);
|
||||||
|
Vars.ui.reloadLevels();
|
||||||
|
//TODO reload map dialog
|
||||||
|
}
|
||||||
|
|
||||||
public void saveMaps(Array<Map> array, FileHandle file){
|
public void saveMaps(Array<Map> array, FileHandle file){
|
||||||
json.toJson(new ArrayContainer(array), file);
|
json.toJson(new ArrayContainer(array), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveCustomMap(Map toSave){
|
public void saveCustomMap(Map toSave){
|
||||||
|
toSave.custom = true;
|
||||||
Array<Map> out = new Array<>();
|
Array<Map> out = new Array<>();
|
||||||
|
boolean added = false;
|
||||||
for(Map map : maps.values()){
|
for(Map map : maps.values()){
|
||||||
if(map.custom)
|
if(map.custom){
|
||||||
|
if(map.name.equals(toSave.name)){
|
||||||
|
out.add(toSave);
|
||||||
|
added = true;
|
||||||
|
}else{
|
||||||
out.add(map);
|
out.add(map);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!added){
|
||||||
|
out.add(toSave);
|
||||||
|
}
|
||||||
|
maps.remove(toSave.id);
|
||||||
|
mapNames.remove(toSave.name);
|
||||||
|
maps.put(toSave.id, toSave);
|
||||||
|
mapNames.put(toSave.name, toSave);
|
||||||
Pixmaps.write(toSave.pixmap, Vars.customMapDirectory.child(toSave.name + ".png"));
|
Pixmaps.write(toSave.pixmap, Vars.customMapDirectory.child(toSave.name + ".png"));
|
||||||
saveMaps(out, Vars.customMapDirectory.child("maps.json"));
|
saveMaps(out, Vars.customMapDirectory.child("maps.json"));
|
||||||
}
|
}
|
||||||
@@ -73,6 +116,7 @@ public class Maps implements Disposable{
|
|||||||
map.texture = new Texture(map.pixmap);
|
map.texture = new Texture(map.pixmap);
|
||||||
maps.put(map.id, map);
|
maps.put(map.id, map);
|
||||||
mapNames.put(map.name, map);
|
mapNames.put(map.name, map);
|
||||||
|
lastID = Math.max(lastID, map.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package io.anuke.mindustry.world.blocks;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
|
||||||
|
public class SpecialBlocks{
|
||||||
|
public static final Block
|
||||||
|
playerSpawn = new Block("playerspawn"),
|
||||||
|
enemySpawn = new Block("enemyspawn");
|
||||||
|
}
|
||||||
@@ -19,10 +19,9 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
|||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
//TODO
|
|
||||||
public class Teleporter extends Block implements Configurable{
|
public class Teleporter extends Block implements Configurable{
|
||||||
public static final int colors = 4;
|
|
||||||
public static final Color[] colorArray = {Color.ROYAL, Color.ORANGE, Color.SCARLET, Color.FOREST, Color.PURPLE, Color.GOLD, Color.PINK};
|
public static final Color[] colorArray = {Color.ROYAL, Color.ORANGE, Color.SCARLET, Color.FOREST, Color.PURPLE, Color.GOLD, Color.PINK};
|
||||||
|
public static final int colors = colorArray.length;
|
||||||
|
|
||||||
private static Array<Tile> removal = new Array<>();
|
private static Array<Tile> removal = new Array<>();
|
||||||
private static Array<Tile> returns = new Array<>();
|
private static Array<Tile> returns = new Array<>();
|
||||||
@@ -71,16 +70,13 @@ public class Teleporter extends Block implements Configurable{
|
|||||||
TeleporterEntity entity = tile.entity();
|
TeleporterEntity entity = tile.entity();
|
||||||
|
|
||||||
table.addIButton("icon-arrow-left", Unit.dp.inPixels(10*3), ()->{
|
table.addIButton("icon-arrow-left", Unit.dp.inPixels(10*3), ()->{
|
||||||
entity.color --;
|
entity.color = (byte)Mathf.mod(entity.color - 1, colors);
|
||||||
if(entity.color < 0)
|
|
||||||
entity.color += 4;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
table.add().size(40f).units(Unit.dp);
|
table.add().size(40f).units(Unit.dp);
|
||||||
|
|
||||||
table.addIButton("icon-arrow-right", Unit.dp.inPixels(10*3), ()->{
|
table.addIButton("icon-arrow-right", Unit.dp.inPixels(10*3), ()->{
|
||||||
entity.color ++;
|
entity.color = (byte)Mathf.mod(entity.color + 1, colors);
|
||||||
entity.color %= 4;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
desktop/mindustry-maps/custom.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
@@ -1 +1 @@
|
|||||||
{}
|
{"maps":[{"id":13,"name":"custom","custom":true},{"id":14,"name":"wowmap","custom":true},{"id":15,"name":"moremap","custom":true},{"id":16,"name":"trash","custom":true},{"id":17,"name":"wonderifthisworks","custom":true}]}
|
||||||
BIN
desktop/mindustry-maps/moremap.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
desktop/mindustry-maps/trash.png
Normal file
|
After Width: | Height: | Size: 856 B |
BIN
desktop/mindustry-maps/wonderifthisworks.png
Normal file
|
After Width: | Height: | Size: 873 B |
BIN
desktop/mindustry-maps/wowmap.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |