Added terrain exporting and importing
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 249 B |
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 234 B |
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 268 B |
@ -151,8 +151,8 @@ text.editor.generate=Generate
|
||||
text.editor.resize=Resize
|
||||
text.editor.loadmap=Load Map
|
||||
text.editor.savemap=Save Map
|
||||
text.editor.loadimage=Load Image
|
||||
text.editor.saveimage=Save Image
|
||||
text.editor.loadimage=Import Terrain
|
||||
text.editor.saveimage=Export Terrain
|
||||
text.editor.unsaved=[scarlet]You have unsaved changes![]\nAre you sure you want to exit?
|
||||
text.editor.brushsize=Brush size: {0}
|
||||
text.editor.noplayerspawn=This map has no player spawnpoint!
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 92 KiB |
@ -1,7 +1,7 @@
|
||||
#Autogenerated file. Do not modify.
|
||||
#Sat Mar 24 18:18:45 EDT 2018
|
||||
#Sun Mar 25 00:43:28 EDT 2018
|
||||
version=release
|
||||
androidBuildCode=635
|
||||
androidBuildCode=638
|
||||
name=Mindustry
|
||||
code=3.4
|
||||
build=custom build
|
||||
|
@ -87,7 +87,7 @@ public class Logic extends Module {
|
||||
world.pathfinder().update();
|
||||
|
||||
|
||||
if(world.getAllyCores().size == 0 && !state.gameOver && false){ //TODO gameover state
|
||||
if(world.getAllyCores().size == 0 && !state.gameOver){ //TODO gameover state
|
||||
state.gameOver = true;
|
||||
if(Net.server()) NetEvents.handleGameOver();
|
||||
Events.fire(GameOverEvent.class);
|
||||
|
@ -179,7 +179,7 @@ public class World extends Module{
|
||||
|
||||
Entities.resizeTree(0, 0, width * tilesize, height * tilesize);
|
||||
|
||||
WorldGenerator.generate(tiles, MapIO.readTileData(map));
|
||||
WorldGenerator.generate(tiles, MapIO.readTileData(map), allyCores);
|
||||
}
|
||||
|
||||
void set(int x, int y, Block type, int rot){
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.anuke.mindustry.editor;
|
||||
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapTileData;
|
||||
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
@ -16,6 +17,7 @@ public class MapEditor{
|
||||
|
||||
private int brushSize = 1;
|
||||
private Block drawBlock = Blocks.stone;
|
||||
private Team drawTeam = Team.none;
|
||||
|
||||
public MapEditor(){
|
||||
|
||||
@ -31,7 +33,15 @@ public class MapEditor{
|
||||
this.brushSize = 1;
|
||||
renderer.resize(map.width(), map.height());
|
||||
}
|
||||
|
||||
|
||||
public void setDrawTeam(Team team){
|
||||
this.drawTeam = team;
|
||||
}
|
||||
|
||||
public Team getDrawTeam() {
|
||||
return drawTeam;
|
||||
}
|
||||
|
||||
public Block getDrawBlock(){
|
||||
return drawBlock;
|
||||
}
|
||||
@ -60,6 +70,10 @@ public class MapEditor{
|
||||
writer.wall = (byte)drawBlock.id;
|
||||
}
|
||||
|
||||
if(drawBlock.hasEntity()){
|
||||
writer.team = (byte)drawTeam.ordinal();
|
||||
}
|
||||
|
||||
for(int rx = -brushSize + 1; rx <= brushSize - 1; rx ++){
|
||||
for(int ry = -brushSize + 1; ry <= brushSize - 1; ry ++){
|
||||
if(Mathf.dst(rx, ry) <= brushSize){
|
||||
|
@ -3,8 +3,10 @@ package io.anuke.mindustry.editor;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.io.MapTileData;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
@ -18,6 +20,7 @@ import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Pixmaps;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.builders.build;
|
||||
@ -42,7 +45,7 @@ public class MapEditorDialog extends Dialog{
|
||||
private MapResizeDialog resizeDialog;
|
||||
private ScrollPane pane;
|
||||
private FloatingDialog menu;
|
||||
private FileChooser openFile, saveFile;
|
||||
private FileChooser openFile, saveFile, openImage, saveImage;
|
||||
private ObjectMap<String, String> tags = new ObjectMap<>();
|
||||
private boolean saved = false;
|
||||
|
||||
@ -56,7 +59,7 @@ public class MapEditorDialog extends Dialog{
|
||||
dialog = new MapGenerateDialog(editor);
|
||||
view = new MapView(editor);
|
||||
|
||||
saveFile = new FileChooser("$saveimage", false, file -> {
|
||||
saveFile = new FileChooser("$text.saveimage", false, file -> {
|
||||
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
|
||||
FileHandle result = file;
|
||||
ui.loadfrag.show();
|
||||
@ -88,6 +91,38 @@ public class MapEditorDialog extends Dialog{
|
||||
});
|
||||
});
|
||||
|
||||
saveImage = new FileChooser("$text.saveimage", false, file -> {
|
||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||
FileHandle result = file;
|
||||
ui.loadfrag.show();
|
||||
Timers.run(3f, () -> {
|
||||
|
||||
try{
|
||||
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
});
|
||||
|
||||
openImage = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
|
||||
ui.loadfrag.show();
|
||||
Timers.run(3f, () -> {
|
||||
try{
|
||||
MapTileData data = MapIO.readPixmap(new Pixmap(file));
|
||||
|
||||
editor.beginEdit(data);
|
||||
view.clearStack();
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
});
|
||||
|
||||
menu = new FloatingDialog("$text.menu");
|
||||
menu.addCloseButton();
|
||||
|
||||
@ -118,6 +153,19 @@ public class MapEditorDialog extends Dialog{
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
menu.content().row();
|
||||
|
||||
menu.content().addImageTextButton("$text.editor.saveimage", "icon-save-map", isize, () -> {
|
||||
saveImage.show();
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
menu.content().row();
|
||||
|
||||
menu.content().addImageTextButton("$text.editor.loadimage", "icon-load-map", isize, () -> {
|
||||
openImage.show();
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
@ -284,7 +332,22 @@ public class MapEditorDialog extends Dialog{
|
||||
if (tool == EditorTool.pencil)
|
||||
button.setChecked(true);
|
||||
|
||||
tools.add(button).padBottom(-6f);
|
||||
tools.add(button).padBottom(-5.1f);
|
||||
if(i++ % 2 == 1) tools.row();
|
||||
}
|
||||
|
||||
ButtonGroup<ImageButton> teamgroup = new ButtonGroup<>();
|
||||
|
||||
for(Team team : Team.values()){
|
||||
ImageButton button = new ImageButton("white", "toggle");
|
||||
button.margin(4f, 4f, 10f, 4f);
|
||||
button.getImageCell().grow();
|
||||
button.getStyle().imageUpColor = team.color;
|
||||
button.clicked(() -> editor.setDrawTeam(team));
|
||||
button.update(() -> button.setChecked(editor.getDrawTeam() == team));
|
||||
teamgroup.add(button);
|
||||
tools.add(button).padBottom(-5.1f);
|
||||
|
||||
if(i++ % 2 == 1) tools.row();
|
||||
}
|
||||
|
||||
@ -351,44 +414,9 @@ public class MapEditorDialog extends Dialog{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifyMap(){
|
||||
//TODO make sure both teams have cores or something
|
||||
/*
|
||||
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){
|
||||
ui.showError("$text.editor.noplayerspawn");
|
||||
return false;
|
||||
}else if(playerSpawns > 1){
|
||||
ui.showError("$text.editor.manyplayerspawns");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(enemySpawns > MapEditor.maxSpawnpoints){
|
||||
ui.showError(Bundles.format("text.editor.manyenemyspawns", MapEditor.maxSpawnpoints));
|
||||
return false;
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addBlockSelection(Table table){
|
||||
Table content = new Table();
|
||||
pane = new ScrollPane(content, "volume");
|
||||
//pane.setScrollingDisabled(true, false);
|
||||
pane.setFadeScrollBars(false);
|
||||
pane.setOverscroll(true, false);
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
|
@ -0,0 +1,25 @@
|
||||
package io.anuke.mindustry.entities.units;
|
||||
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
|
||||
public class FlyingUnitType extends UnitType {
|
||||
|
||||
public FlyingUnitType(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(BaseUnit unit) {
|
||||
Draw.alpha(unit.hitTime / Unit.hitDuration);
|
||||
|
||||
Draw.rect(name, unit.x, unit.y, unit.rotation);
|
||||
|
||||
Draw.alpha(1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void behavior(BaseUnit unit) {
|
||||
|
||||
}
|
||||
}
|
@ -5,7 +5,8 @@ import com.badlogic.gdx.graphics.Color;
|
||||
public enum Team {
|
||||
none(Color.DARK_GRAY),
|
||||
blue(Color.ROYAL),
|
||||
red(Color.valueOf("e84737"));
|
||||
red(Color.valueOf("e84737")),
|
||||
green(Color.valueOf("1dc645"));
|
||||
|
||||
public final Color color;
|
||||
|
||||
|
@ -9,6 +9,8 @@ import com.badlogic.gdx.utils.ObjectMap.Entry;
|
||||
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.ColorMapper;
|
||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
@ -25,6 +27,7 @@ public class MapIO {
|
||||
|
||||
public static Pixmap generatePixmap(MapTileData data){
|
||||
Pixmap pixmap = new Pixmap(data.width(), data.height(), Format.RGBA8888);
|
||||
data.position(0, 0);
|
||||
|
||||
for(int x = 0; x < data.width(); x ++){
|
||||
for(int y = 0; y < data.height(); y ++){
|
||||
@ -39,6 +42,31 @@ public class MapIO {
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
public static MapTileData readPixmap(Pixmap pixmap){
|
||||
MapTileData data = new MapTileData(pixmap.getWidth(), pixmap.getHeight());
|
||||
|
||||
data.position(0, 0);
|
||||
TileDataMarker marker = data.getMarker();
|
||||
|
||||
for(int x = 0; x < data.width(); x ++){
|
||||
for(int y = 0; y < data.height(); y ++){
|
||||
BlockPair pair = ColorMapper.get(pixmap.getPixel(y, pixmap.getWidth() - 1 - x));
|
||||
|
||||
if(pair == null){
|
||||
marker.floor = (byte)Blocks.stone.id;
|
||||
marker.wall = (byte)Blocks.air.id;
|
||||
}else{
|
||||
marker.floor = (byte)pair.floor.id;
|
||||
marker.wall = (byte)pair.wall.id;
|
||||
}
|
||||
|
||||
data.write();
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static void writeMap(FileHandle file, ObjectMap<String, String> tags, MapTileData data) throws IOException{
|
||||
MapMeta meta = new MapMeta(version, tags, data.width(), data.height());
|
||||
|
||||
|
@ -39,6 +39,10 @@ public class MapTileData {
|
||||
return height;
|
||||
}
|
||||
|
||||
public TileDataMarker getMarker() {
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**Reads and returns the next tile data.*/
|
||||
public TileDataMarker read(){
|
||||
tile.read(buffer);
|
||||
@ -52,6 +56,11 @@ public class MapTileData {
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**Writes and returns the next tile data.*/
|
||||
public void write(){
|
||||
tile.write(buffer);
|
||||
}
|
||||
|
||||
/**Writes tile data at a specified position.*/
|
||||
public void write(int x, int y, TileDataMarker writer){
|
||||
position(x, y);
|
||||
|
@ -220,6 +220,10 @@ public class Block extends BaseBlock {
|
||||
region.setRegionHeight(8);
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean hasEntity(){
|
||||
return destructible || update;
|
||||
}
|
||||
|
||||
public TileEntity getEntity(){
|
||||
return new TileEntity();
|
||||
|
@ -305,7 +305,7 @@ public class Tile{
|
||||
|
||||
Block block = block();
|
||||
|
||||
if (block.destructible || block.update) {
|
||||
if (block.hasEntity()) {
|
||||
entity = block.getEntity().init(this, block.update);
|
||||
if(block.hasInventory) entity.inventory = new InventoryModule();
|
||||
if(block.hasLiquids) entity.liquid = new LiquidModule();
|
||||
|
@ -1,11 +1,13 @@
|
||||
package io.anuke.mindustry.world;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.io.MapTileData;
|
||||
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.mindustry.world.blocks.ProductionBlocks;
|
||||
import io.anuke.ucore.noise.Noise;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
@ -20,7 +22,7 @@ public class WorldGenerator {
|
||||
}};
|
||||
|
||||
/**Should fill spawns with the correct spawnpoints.*/
|
||||
public static void generate(Tile[][] tiles, MapTileData data){
|
||||
public static void generate(Tile[][] tiles, MapTileData data, Array<Tile> cores){
|
||||
Noise.setSeed(world.getSeed());
|
||||
|
||||
IntArray multiblocks = new IntArray();
|
||||
@ -34,6 +36,10 @@ public class WorldGenerator {
|
||||
multiblocks.add(tiles[x][y].packedPosition());
|
||||
}
|
||||
|
||||
if(tiles[x][y].block() == ProductionBlocks.core){
|
||||
cores.add(tiles[x][y]);
|
||||
}
|
||||
|
||||
//TODO ores, plants, extra decoration?
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,80 @@
|
||||
package io.anuke.mindustry.world.blocks.types.production;
|
||||
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.resource.ItemStack;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.types.modules.InventoryModule;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnitFactory extends Block {
|
||||
protected UnitType type;
|
||||
protected ItemStack[] requirements;
|
||||
protected float produceTime = 1000f;
|
||||
protected float powerUse = 0.1f;
|
||||
|
||||
public UnitFactory(String name) {
|
||||
super(name);
|
||||
solid = true;
|
||||
update = true;
|
||||
hasPower = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile) {
|
||||
UnitFactoryEntity entity = tile.entity();
|
||||
|
||||
float used = Math.min(powerUse * Timers.delta(), powerCapacity);
|
||||
|
||||
if(hasRequirements(entity.inventory, entity.buildTime/produceTime) &&
|
||||
entity.power.amount >= used){
|
||||
|
||||
entity.buildTime += Timers.delta();
|
||||
entity.power.amount -= used;
|
||||
|
||||
if(entity.buildTime >= produceTime){
|
||||
BaseUnit unit = new BaseUnit(type, tile.getTeam());
|
||||
unit.set(tile.drawx(), tile.drawy());
|
||||
entity.buildTime = 0f;
|
||||
|
||||
for(ItemStack stack : requirements){
|
||||
entity.inventory.removeItem(stack.item, stack.amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getEntity() {
|
||||
return new UnitFactoryEntity();
|
||||
}
|
||||
|
||||
protected boolean hasRequirements(InventoryModule inv, float fraction){
|
||||
for(ItemStack stack : requirements){
|
||||
if(!inv.hasItem(stack.item, (int)(fraction * stack.amount))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class UnitFactoryEntity extends TileEntity{
|
||||
public float buildTime;
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream stream) throws IOException {
|
||||
stream.writeFloat(buildTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream stream) throws IOException {
|
||||
buildTime = stream.readFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|