Add basic map editor, change map system

This commit is contained in:
Anuken
2017-12-17 23:51:55 -05:00
parent 1b3d964b83
commit 1a8fdda421
34 changed files with 1237 additions and 465 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/desktop/packr-out/ /desktop/packr-out/
/desktop/packr-export/ /desktop/packr-export/
/desktop/mindustry-saves/ /desktop/mindustry-saves/
/destkop/mindustry-maps/
/core/lib/ /core/lib/
*.gif *.gif

View File

@ -16,6 +16,8 @@ _Keep in mind that this is just a basic outline of planned features, and will be
- [DONE] Add link to Mindustry discord everywhere - [DONE] Add link to Mindustry discord everywhere
- Balancing to slow down progression - Balancing to slow down progression
- Map editor - Map editor
- Delete saves
- Display playtime
### Major Bugs ### Major Bugs
- Black screen when tabbing out on Android - Black screen when tabbing out on Android

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.anuke.mindustry" package="io.anuke.mindustry"
android:versionCode="37" android:versionCode="38"
android:versionName="3.1.1" > android:versionName="3.1.2" >
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="25" /> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="25" />
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="com.android.vending.BILLING" />

View File

@ -52,7 +52,7 @@ public class AndroidLauncher extends AndroidApplication{
Mindustry.donationsCallable = new Callable(){ @Override public void run(){ showDonations(); } }; Mindustry.donationsCallable = new Callable(){ @Override public void run(){ showDonations(); } };
if(doubleScaleTablets && isTablet(this.getContext())){ if(doubleScaleTablets && isTablet(this.getContext())){
Unit.dp.addition = 1f; Unit.dp.addition = 0.5f;
} }
config.hideStatusBar = true; config.hideStatusBar = true;

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

View File

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -0,0 +1,95 @@
{
"maps": [
{
"id": 0,
"name": "maze",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 1,
"name": "fortress",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 2,
"name": "sinkhole",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 3,
"name": "caves",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 4,
"name": "volcano",
"visible": true,
"flipBase": true,
"backgroundColor": "646464"
},
{
"id": 5,
"name": "caldera",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 6,
"name": "scorch",
"visible": true,
"flipBase": false,
"backgroundColor": "e5d8bb"
},
{
"id": 7,
"name": "desert",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 8,
"name": "island",
"visible": true,
"flipBase": false,
"backgroundColor": "e5d8bb"
},
{
"id": 9,
"name": "grassland",
"visible": true,
"flipBase": false,
"backgroundColor": "5ab464"
},
{
"id": 10,
"name": "tundra",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
},
{
"id": 11,
"name": "spiral",
"visible": true,
"flipBase": false,
"backgroundColor": "f7feff"
},
{
"id": 12,
"name": "tutorial",
"visible": true,
"flipBase": false,
"backgroundColor": "646464"
}
]
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -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},
volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical} clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical}
}, },
io.anuke.ucore.scene.ui.Window$WindowStyle: { io.anuke.ucore.scene.ui.Window$WindowStyle: {

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry;
import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.I18NBundle; import com.badlogic.gdx.utils.I18NBundle;
import io.anuke.mindustry.core.*; import io.anuke.mindustry.core.*;
@ -20,14 +21,18 @@ public class Vars{
public static final float respawnduration = 60*4; public static final float respawnduration = 60*4;
//time between waves in frames (on normal mode) //time between waves in frames (on normal mode)
public static final float wavespace = 60*60*(android ? 1 : 1); public static final float wavespace = 60*60*(android ? 1 : 1);
//waves can last no longer than 2 minutes, otherwise the next one spawns //waves can last no longer than 3 minutes, otherwise the next one spawns
public static final float maxwavespace = 60*60*2; public static final float maxwavespace = 60*60*4f;
//advance time the pathfinding starts at //advance time the pathfinding starts at
public static final float aheadPathfinding = 60*20; public static final float aheadPathfinding = 60*20;
//how far away from spawn points the player can't place blocks //how far away from spawn points the player can't place blocks
public static final float enemyspawnspace = 65; public static final float enemyspawnspace = 65;
//discord group URL //discord group URL
public static final String discordURL = "https://discord.gg/r8BkXNd"; public static final String discordURL = "https://discord.gg/r8BkXNd";
//directory for user-created map data
public static final FileHandle customMapDirectory = Gdx.files.local("mindustry-maps/");
//save file directory
public static final FileHandle saveDirectory = Gdx.files.local("mindustry-saves/");
//scale of the font //scale of the font
public static float fontscale = Unit.dp.inPixels(1f)/2f; public static float fontscale = Unit.dp.inPixels(1f)/2f;
//camera zoom displayed on startup //camera zoom displayed on startup

View File

@ -42,11 +42,10 @@ public class Pathfind{
if(Vars.world.raycastWorld(enemy.x, enemy.y, target.worldx(), target.worldy()) != null){ if(Vars.world.raycastWorld(enemy.x, enemy.y, target.worldx(), target.worldy()) != null){
if(enemy.node > 1) if(enemy.node > 1)
enemy.node = enemy.node - 1; enemy.node = enemy.node - 1;
enemy.idletime = 0;
}else{ }else{
//must be blocked by a playermade block //must be blocked by a playermade block, do nothing
} }
enemy.idletime = 0;
} }
//-1 is only possible here if both pathfindings failed, which should NOT happen //-1 is only possible here if both pathfindings failed, which should NOT happen

View File

@ -118,8 +118,8 @@ public class Control extends Module{
Settings.loadAll("io.anuke.moment"); Settings.loadAll("io.anuke.moment");
for(Map map : Map.values()){ for(Map map : Vars.world.maps().list()){
Settings.defaults("hiscore" + map.name(), 0); Settings.defaults("hiscore" + map.name, 0);
} }
player = new Player(); player = new Player();
@ -278,10 +278,10 @@ public class Control extends Module{
wave ++; wave ++;
int last = Settings.getInt("hiscore" + world.getMap().name()); int last = Settings.getInt("hiscore" + world.getMap().name);
if(wave > last && mode != GameMode.sandbox){ if(wave > last && mode != GameMode.sandbox){
Settings.putInt("hiscore" + world.getMap().name(), wave); Settings.putInt("hiscore" + world.getMap().name, wave);
Settings.save(); Settings.save();
hiscore = true; hiscore = true;
} }
@ -518,7 +518,6 @@ public class Control extends Module{
} }
if(!tutorial.active() && mode != GameMode.sandbox){ if(!tutorial.active() && mode != GameMode.sandbox){
extrawavetime -= delta();
if(enemies <= 0){ if(enemies <= 0){
wavetime -= delta(); wavetime -= delta();
@ -531,10 +530,12 @@ public class Control extends Module{
world.pathfinder().updatePath(); world.pathfinder().updatePath();
lastUpdated = wave + 1; lastUpdated = wave + 1;
} }
}else{
extrawavetime -= delta();
} }
} }
if(wavetime <= 0){ if(wavetime <= 0 || extrawavetime <= 0){
runWave(); runWave();
} }

View File

@ -9,7 +9,6 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.blocks.*;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@ -33,7 +32,7 @@ public class Tutorial{
} }
public boolean active(){ public boolean active(){
return world.getMap() == Map.tutorial && !GameState.is(State.menu); return world.getMap().name.equals("tutorial") && !GameState.is(State.menu);
} }
public void buildUI(table table){ public void buildUI(table table){

View File

@ -15,6 +15,8 @@ import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Mindustry;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.mapeditor.MapEditor;
import io.anuke.mindustry.mapeditor.MapEditorDialog;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.ui.fragments.*; import io.anuke.mindustry.ui.fragments.*;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
@ -38,11 +40,13 @@ public class UI extends SceneModule{
Table loadingtable, desctable, configtable; Table loadingtable, desctable, configtable;
MindustrySettingsDialog prefs; MindustrySettingsDialog prefs;
MindustryKeybindDialog keys; MindustryKeybindDialog keys;
MapEditorDialog editorDialog;
Dialog about, restart, levels, upgrades, load, settingserror, gameerror, discord; Dialog about, restart, levels, upgrades, load, settingserror, gameerror, discord;
MenuDialog menu; MenuDialog menu;
Tooltip tooltip; Tooltip tooltip;
Tile configTile; Tile configTile;
Array<String> statlist = new Array<>(); Array<String> statlist = new Array<>();
MapEditor editor = new MapEditor();
boolean wasPaused = false; boolean wasPaused = false;
private Fragment blockfrag = new BlocksFragment(), private Fragment blockfrag = new BlocksFragment(),
@ -118,7 +122,7 @@ public class UI extends SceneModule{
Draw.color(); Draw.color();
TextureRegion back = Draw.region("background"); TextureRegion back = Draw.region("background");
float backscl = 5f; float backscl = Unit.dp.inPixels(5f);
Draw.alpha(0.7f); Draw.alpha(0.7f);
Core.batch.draw(back, w/2 - back.getRegionWidth()*backscl/2 +240f, h/2 - back.getRegionHeight()*backscl/2 + 250f, Core.batch.draw(back, w/2 - back.getRegionWidth()*backscl/2 +240f, h/2 - back.getRegionHeight()*backscl/2 + 250f,
@ -158,6 +162,8 @@ public class UI extends SceneModule{
configtable = new Table(); configtable = new Table();
scene.add(configtable); scene.add(configtable);
editorDialog = new MapEditorDialog(editor);
settingserror = new Dialog("Warning", "dialog"); settingserror = new Dialog("Warning", "dialog");
settingserror.content().add("[crimson]Failed to access local storage.\nSettings will not be saved."); settingserror.content().add("[crimson]Failed to access local storage.\nSettings will not be saved.");
settingserror.content().pad(10f); settingserror.content().pad(10f);
@ -438,6 +444,10 @@ public class UI extends SceneModule{
public void showDiscord(){ public void showDiscord(){
discord.show(); discord.show();
} }
public void showEditor(){
editorDialog.show();
}
public void updateItems(){ public void updateItems(){
((HudFragment)hudfrag).updateItems(); ((HudFragment)hudfrag).updateItems();

View File

@ -2,9 +2,6 @@ package io.anuke.mindustry.core;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
@ -25,15 +22,15 @@ import io.anuke.ucore.util.Tmp;
public class World extends Module{ public class World extends Module{
private int seed; private int seed;
private Pixmap[] mapPixmaps;
private Texture[] mapTextures;
private Map currentMap; private Map currentMap;
private Tile[][] tiles; private Tile[][] tiles;
private Tile[] temptiles = new Tile[4]; private Tile[] temptiles = new Tile[4];
private Pathfind pathfind = new Pathfind(); private Pathfind pathfind = new Pathfind();
private Maps maps = new Maps();
public World(){ public World(){
loadMaps(); maps.loadMaps();
currentMap = maps.getMap(0);
} }
@Override @Override
@ -43,13 +40,11 @@ public class World extends Module{
@Override @Override
public void dispose(){ public void dispose(){
for(Texture texture : mapTextures){ maps.dispose();
texture.dispose(); }
}
public Maps maps(){
for(Pixmap pix : mapPixmaps){ return maps;
pix.dispose();
}
} }
public Pathfind pathfinder(){ public Pathfind pathfinder(){
@ -82,11 +77,11 @@ public class World extends Module{
} }
public int width(){ public int width(){
return currentMap.width; return currentMap.getWidth();
} }
public int height(){ public int height(){
return currentMap.height; return currentMap.getHeight();
} }
public Tile tile(int x, int y){ public Tile tile(int x, int y){
@ -115,25 +110,6 @@ public class World extends Module{
return temptiles; return temptiles;
} }
public Texture getTexture(Map map){
return mapTextures[map.ordinal()];
}
public void loadMaps(){
Map[] maps = Map.values();
mapPixmaps = new Pixmap[maps.length];
mapTextures = new Texture[maps.length];
for(int i = 0; i < maps.length; i ++){
Pixmap pix = new Pixmap(Gdx.files.internal("maps/"+maps[i]+".png"));
mapPixmaps[i] = pix;
mapTextures[i] = new Texture(pix);
maps[i].width = pix.getWidth();
maps[i].height = pix.getHeight();
}
}
private void createTiles(){ private void createTiles(){
for(int x = 0; x < tiles.length; x ++){ for(int x = 0; x < tiles.length; x ++){
for(int y = 0; y < tiles[0].length; y ++){ for(int y = 0; y < tiles[0].length; y ++){
@ -164,28 +140,28 @@ public class World extends Module{
if(tiles != null){ if(tiles != null){
clearTileEntities(); clearTileEntities();
if(tiles.length != map.width || tiles[0].length != map.height){ if(tiles.length != map.getWidth() || tiles[0].length != map.getHeight()){
tiles = new Tile[map.width][map.height]; tiles = new Tile[map.getWidth()][map.getHeight()];
} }
createTiles(); createTiles();
}else{ }else{
tiles = new Tile[map.width][map.height]; tiles = new Tile[map.getWidth()][map.getHeight()];
createTiles(); createTiles();
} }
Vars.control.getSpawnPoints().clear(); Vars.control.getSpawnPoints().clear();
Entities.resizeTree(0, 0, map.width * tilesize, map.height * tilesize); Entities.resizeTree(0, 0, map.getWidth() * tilesize, map.getHeight() * tilesize);
this.seed = seed; this.seed = seed;
Generator.generate(mapPixmaps[map.ordinal()], tiles); Generator.generate(map.pixmap, tiles);
//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);
if(map != Map.tutorial){ if(!map.name.equals("tutorial")){
setDefaultBlocks(); setDefaultBlocks();
}else{ }else{
Vars.control.getTutorial().setDefaultBlocks(control.getCore().x, control.getCore().y); Vars.control.getTutorial().setDefaultBlocks(control.getCore().x, control.getCore().y);

View File

@ -17,7 +17,7 @@ public class Enemy extends DestructibleEntity{
public final static Color[] tierColors = { Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"), Color.valueOf("ff2d86") }; public final static Color[] tierColors = { Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"), Color.valueOf("ff2d86") };
public final static int maxtier = 4; public final static int maxtier = 4;
public final static float maxIdle = 60*1.5f; public final static float maxIdle = 60*1.5f;
public final static float maxIdleLife = 60f*15f; //15 seconds idle = death public final static float maxIdleLife = 60f*13f; //13 seconds idle = death
protected int timeid; protected int timeid;
protected Timer timer = new Timer(5); protected Timer timer = new Timer(5);
@ -238,7 +238,7 @@ public class Enemy extends DestructibleEntity{
xvelocity = (x - lastx) / Timers.delta(); xvelocity = (x - lastx) / Timers.delta();
yvelocity = (y - lasty) / Timers.delta(); yvelocity = (y - lasty) / Timers.delta();
float minv = 0.08f; float minv = 0.09f;
if(xvelocity < minv && yvelocity < minv && node > 0 && target == null){ if(xvelocity < minv && yvelocity < minv && node > 0 && target == null){
idletime += Timers.delta(); idletime += Timers.delta();

View File

@ -8,7 +8,6 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
@ -163,14 +162,14 @@ public class SaveIO{
stream.readInt(); //read version stream.readInt(); //read version
stream.readLong(); //read last saved time stream.readLong(); //read last saved time
stream.readByte(); //read the gamemode stream.readByte(); //read the gamemode
return Map.values()[stream.readByte()]; //read the map return Vars.world.maps().getMap(stream.readByte()); //read the map
}catch (IOException e){ }catch (IOException e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public static FileHandle fileFor(int slot){ public static FileHandle fileFor(int slot){
return Gdx.files.local("mindustry-saves/" + slot + ".mins"); return Vars.saveDirectory.child(slot + ".mins");
} }
public static void write(FileHandle file){ public static void write(FileHandle file){
@ -183,7 +182,7 @@ public class SaveIO{
//--GENERAL STATE-- //--GENERAL STATE--
stream.writeByte(Vars.control.getMode().ordinal()); //gamemode stream.writeByte(Vars.control.getMode().ordinal()); //gamemode
stream.writeByte(Vars.world.getMap().ordinal()); //map ID stream.writeByte(Vars.world.getMap().id); //map ID
stream.writeInt(Vars.control.getWave()); //wave stream.writeInt(Vars.control.getWave()); //wave
stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown
@ -399,7 +398,7 @@ public class SaveIO{
int seed = stream.readInt(); int seed = stream.readInt();
int tiles = stream.readInt(); int tiles = stream.readInt();
Vars.world.loadMap(Map.values()[mapid], seed); Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed);
Vars.renderer.clearTiles(); Vars.renderer.clearTiles();
for(Enemy enemy : enemiesToUpdate){ for(Enemy enemy : enemiesToUpdate){

View File

@ -0,0 +1,123 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.graphics.Pixmaps;
public class MapEditor{
public static final int[] validMapSizes = {64, 128, 256};
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
private Pixmap[] brushPixmaps = new Pixmap[brushSizes.length];
private Map map;
private Pixmap pixmap;
private Texture texture;
private int brushSize = 1;
private Block drawBlock = Blocks.stone;
public MapEditor(){
for(int i = 0; i < brushSizes.length; i ++){
int s = brushSizes[i];
brushPixmaps[i] = new Pixmap(s*2-1, s*2-1, Format.RGB888);
}
}
public void beginEdit(Map map){
this.map = map;
this.brushSize = 1;
if(map.pixmap == null){
pixmap = new Pixmap(256, 256, Format.RGB888);
pixmap.setColor(ColorMapper.getColor(Blocks.stone));
pixmap.fill();
texture = new Texture(pixmap);
}else{
pixmap = map.pixmap;
pixmap.setColor(ColorMapper.getColor(Blocks.stone));
texture = map.texture;
}
}
public Block getDrawBlock(){
return drawBlock;
}
public void setDrawBlock(Block block){
this.drawBlock = block;
pixmap.setColor(ColorMapper.getColor(block));
}
public void setBrushSize(int size){
this.brushSize = size;
}
public void draw(int dx, int dy){
if(dx < 0 || dy < 0 || dx >= pixmap.getWidth() || dy >= pixmap.getHeight()){
return;
}
Gdx.gl.glBindTexture(GL20.GL_TEXTURE_2D, texture.getTextureObjectHandle());
int dstWidth = brushSize*2-1;
int dstHeight = brushSize*2-1;
int width = pixmap.getWidth(), height = pixmap.getHeight();
int x = dx - dstWidth/2;
int y = dy - dstHeight/2;
if (x + dstWidth > width){
//x = width - dstWidth;
dstWidth = width - x;
}else if (x < 0){
dstWidth += x;
x = 0;
}
//System.out.println(x + " " + y + " " + dstWidth + " " + dstHeight);
if (y + dstHeight > height){
//y = height - dstHeight;
dstHeight = height - y;
}else if (y < 0){
dstHeight += y;
y = 0;
}
pixmap.fillCircle(dx, dy, brushSize);
Pixmap dst = brush(brushSize);
dst.drawPixmap(pixmap, x, y, dstWidth, dstHeight, 0, 0, dstWidth, dstHeight);
Gdx.gl.glTexSubImage2D(GL20.GL_TEXTURE_2D, 0, x, y, dstWidth, dstHeight,
dst.getGLFormat(), dst.getGLType(), dst.getPixels());
}
private Pixmap brush(int size){
for(int i = 0; i < brushSizes.length; i ++){
if(brushSizes[i] == size){
return brushPixmaps[i];
}
}
return null;
}
public Texture texture(){
return texture;
}
public void resize(int mapSize){
Pixmap out = Pixmaps.resize(pixmap, mapSize, mapSize);
pixmap.dispose();
pixmap = out;
texture.draw(pixmap, 0, 0);
}
}

View File

@ -0,0 +1,142 @@
package io.anuke.mindustry.mapeditor;
import io.anuke.mindustry.world.Block;
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.Draw;
import io.anuke.ucore.scene.builders.*;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.ui.layout.Unit;
public class MapEditorDialog extends Dialog{
private MapEditor editor;
private MapView view;
public MapEditorDialog(MapEditor editor){
super("Map Editor", "dialog");
this.editor = editor;
view = new MapView(editor);
setFillParent(true);
clearChildren();
pad(0);
build.begin(this);
build();
build.end();
shown(() -> {
editor.beginEdit(new Map());
});
}
public void build(){
new table(){{
float isize = Unit.dp.inPixels(14*3f);
aleft();
new table(){{
defaults().growY().width(130f).units(Unit.dp).padBottom(-6);
new imagebutton("icon-load", isize, () -> {
}).text("load map");
row();
new imagebutton("icon-save", isize, ()->{
}).text("save map");
row();
new imagebutton("icon-load", isize, () -> {
}).text("load image");
row();
new imagebutton("icon-save", isize, () -> {
}).text("save image");
row();
new imagebutton("icon-cursor", 10f*3f, () -> {
}).text("resize").padTop(4f);
row();
new imagebutton("icon-arrow-left", isize, () -> {
}).padBottom(0).text("back");
}}.left().growY().end();
new table("button"){{
add(view).grow();
}}.grow().end();
new table(){{
new imagebutton("icon-terrain", isize, () -> {
}).margin(12f).text("generate...").width(148f).units(Unit.dp);
row();
new table("button"){{
margin(10f);
Slider slider = new Slider(0, MapEditor.brushSizes.length-1, 1, false);
slider.moved(f -> {
editor.setBrushSize(MapEditor.brushSizes[(int)(float)f]);
});
new label(() -> "Brush size: " + MapEditor.brushSizes[(int)slider.getValue()]).left();
row();
add(slider).growX().padTop(4f).units(Unit.dp);
}}.growX().end();
row();
addBlockSelection(get());
row();
}}.right().growY().end();
}}.grow().end();
}
private void addBlockSelection(Table table){
Table content = new Table();
ScrollPane pane = new ScrollPane(content, "volume");
pane.setFadeScrollBars(false);
pane.setOverscroll(true, false);
ButtonGroup<ImageButton> group = new ButtonGroup<>();
int i = 0;
for(BlockPair pair : ColorMapper.getPairs()){
Block block = pair.wall == Blocks.air ? pair.floor : pair.wall;
ImageButton button = new ImageButton(Draw.hasRegion(block.name) ? Draw.region(block.name) : Draw.region(block.name + "1"), "toggle");
button.clicked(() -> editor.setDrawBlock(block));
button.resizeImage(Unit.dp.inPixels(8*4f));
group.add(button);
content.add(button).pad(4f).size(53f, 58f).units(Unit.dp);
if(i++ % 2 == 1){
content.row();
}
}
Table extra = new Table("button");
extra.addWrap(() -> editor.getDrawBlock().name).width(120f).center();
table.add(extra).growX();
table.row();
table.add(pane).growY().fillX();
}
}

View File

@ -0,0 +1,214 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.OrderedMap;
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 io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.noise.RidgedPerlin;
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 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 void randomize(){
sim.setSeed(Mathf.random(999999));
rid.setSeed(Mathf.random(999999));
rid2.setSeed(Mathf.random(999999));
rid3.setSeed(Mathf.random(999999));
}
public ObjectMap<String, Boolean> getPrefs(){
return prefs;
}
public Pixmap process(Pixmap pixmap){
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, ColorMapper.getColor(block));
}
}
}
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);
BlockPair pair = ColorMapper.get(pix);
Block block = pair == null ? null : pair.wall == Blocks.air ? pair.floor : pair.wall;
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, ColorMapper.getColor(block));
}
}
src.dispose();
return pixmap;
}
}

View File

@ -0,0 +1,66 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Bresenham2;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.utils.Array;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.util.Tmp;
public class MapView extends Element{
private MapEditor editor;
private Bresenham2 br = new Bresenham2();
public MapView(MapEditor editor){
this.editor = editor;
addListener(new InputListener(){
int lastx, lasty;
boolean drawing;
@Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
GridPoint2 p = project(x, y);
lastx = p.x;
lasty = p.y;
editor.draw(p.x, p.y);
return true;
}
@Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
drawing = false;
}
@Override
public void touchDragged (InputEvent event, float x, float y, int pointer) {
GridPoint2 p = project(x, y);
if(drawing){
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;
}
});
}
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();
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);
}
}

View File

@ -16,7 +16,7 @@ import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.scene.utils.Elements; import io.anuke.ucore.scene.utils.Elements;
public class LevelDialog extends FloatingDialog{ public class LevelDialog extends FloatingDialog{
private Map selectedMap = Map.maze; private Map selectedMap = Vars.world.maps().getMap(0);
private TextureRegion region = new TextureRegion(); private TextureRegion region = new TextureRegion();
public LevelDialog(){ public LevelDialog(){
@ -49,8 +49,8 @@ public class LevelDialog extends FloatingDialog{
content().add(selmode); content().add(selmode);
content().row(); content().row();
for(int i = 0; i < Map.values().length; i ++){ int i = 0;
Map map = Map.values()[i]; for(Map map : Vars.world.maps().list()){
if(!map.visible && !Vars.debug) continue; if(!map.visible && !Vars.debug) continue;
@ -59,9 +59,9 @@ public class LevelDialog extends FloatingDialog{
} }
Table inset = new Table("pane-button"); Table inset = new Table("pane-button");
inset.add("[accent]"+map.name()).pad(3f).units(Unit.dp); inset.add("[accent]"+map.name).pad(3f).units(Unit.dp);
inset.row(); inset.row();
inset.add((StringSupplier)(()->"High Score: [accent]" + Settings.getInt("hiscore" + map.name()))) inset.add((StringSupplier)(()->"High Score: [accent]" + Settings.getInt("hiscore" + map.name)))
.pad(3f).units(Unit.dp); .pad(3f).units(Unit.dp);
inset.pack(); inset.pack();
@ -72,7 +72,7 @@ public class LevelDialog extends FloatingDialog{
Image back = new Image("white"); Image back = new Image("white");
back.setColor(map.backgroundColor); back.setColor(map.backgroundColor);
ImageButton image = new ImageButton(new TextureRegion(Vars.world.getTexture(map)), "togglemap"); ImageButton image = new ImageButton(new TextureRegion(map.texture), "togglemap");
image.row(); image.row();
image.add(inset).width(images+6).units(Unit.dp); image.add(inset).width(images+6).units(Unit.dp);
image.clicked(()->{ image.clicked(()->{
@ -88,6 +88,8 @@ public class LevelDialog extends FloatingDialog{
maps.add(stack).width(170).pad(4f).units(Unit.dp); maps.add(stack).width(170).pad(4f).units(Unit.dp);
maps.padRight(Unit.dp.inPixels(26)); maps.padRight(Unit.dp.inPixels(26));
i ++;
} }
content().add(pane).uniformX(); content().add(pane).uniformX();

View File

@ -55,7 +55,9 @@ public class LoadDialog extends FloatingDialog{
button.row(); button.row();
Label info = new Label("[gray]" + (!SaveIO.isSaveValid(i) ? "<empty>" : SaveIO.getMode(slot) + ", " + SaveIO.getMap(slot) + ", Wave " + SaveIO.getWave(slot) + "\nLast Saved: " + SaveIO.getTimeString(i))); Label info = new Label("[gray]" + (!SaveIO.isSaveValid(i) ? "<empty>" : SaveIO.getMode(slot) + ", "
+ SaveIO.getMap(slot).name + ", Wave " + SaveIO.getWave(slot)
+ "\nLast Saved: " + SaveIO.getTimeString(i)));
info.setAlignment(Align.center, Align.center); info.setAlignment(Align.center, Align.center);
button.add(info).padBottom(3).padTop(7); button.add(info).padBottom(3).padTop(7);

View File

@ -1,5 +0,0 @@
package io.anuke.mindustry.ui;
public class MapEditor{
}

View File

@ -1,5 +1,7 @@
package io.anuke.mindustry.ui.fragments; package io.anuke.mindustry.ui.fragments;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import io.anuke.mindustry.Mindustry; import io.anuke.mindustry.Mindustry;
@ -7,16 +9,10 @@ import io.anuke.mindustry.core.GameState;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.ui.MenuButton; import io.anuke.mindustry.ui.MenuButton;
import io.anuke.mindustry.ui.PressGroup; import io.anuke.mindustry.ui.PressGroup;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.scene.builders.imagebutton; import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.table; import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.scene.ui.layout.Unit;
import static io.anuke.mindustry.Vars.android;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.gwt;
import static io.anuke.mindustry.Vars.ui;
public class MenuFragment implements Fragment{ public class MenuFragment implements Fragment{
public void build(){ public void build(){
@ -30,22 +26,25 @@ public class MenuFragment implements Fragment{
float scale = 4f; float scale = 4f;
defaults().size(100*scale, 21*scale).pad(-10f).units(Unit.dp); defaults().size(100*scale, 21*scale).pad(-10f).units(Unit.dp);
add(new MenuButton("text-play", group, ()-> ui.showLevels())); add(new MenuButton("text-play", group, ui::showLevels));
row(); row();
add(new MenuButton("text-tutorial", group, ()-> control.playMap(Map.tutorial))); add(new MenuButton("text-tutorial", group, ()-> control.playMap(world.maps().getMap("tutorial"))));
row(); row();
if(!gwt){ if(!gwt){
add(new MenuButton("text-load", group, ()-> ui.showLoadGame())); add(new MenuButton("text-load", group, ui::showLoadGame));
row();
add(new MenuButton("text-editor", group, ui::showEditor));
row(); row();
} }
add(new MenuButton("text-settings", group, ()-> ui.showPrefs())); add(new MenuButton("text-settings", group, ui::showPrefs));
row(); row();
if(!gwt){ if(!gwt){
add(new MenuButton("text-exit", group, ()-> Gdx.app.exit())); add(new MenuButton("text-exit", group, Gdx.app::exit));
} }
get().pad(Unit.dp.inPixels(16)); get().pad(Unit.dp.inPixels(16));
}}.end(); }}.end();
@ -60,9 +59,13 @@ public class MenuFragment implements Fragment{
new imagebutton("icon-play-2", isize, () -> ui.showLevels()).text("Play").padTop(4f); new imagebutton("icon-play-2", isize, () -> ui.showLevels()).text("Play").padTop(4f);
new imagebutton("icon-tutorial", isize, ()-> control.playMap(Map.tutorial)).text("Tutorial").padTop(4f); new imagebutton("icon-tutorial", isize, () -> control.playMap(world.maps().getMap("tutorial"))).text("Tutorial").padTop(4f);
new imagebutton("icon-load", isize, () -> ui.showLoadGame()).text("Load").padTop(4f); new imagebutton("icon-load", isize, () -> ui.showLoadGame()).text("Load").padTop(4f);
row();
new imagebutton("icon-terrain", isize, () -> ui.showEditor()).text("Editor").padTop(4f);
new imagebutton("icon-tools", isize, () -> ui.showPrefs()).text("Settings").padTop(4f); new imagebutton("icon-tools", isize, () -> ui.showPrefs()).text("Settings").padTop(4f);

View File

@ -0,0 +1,77 @@
package io.anuke.mindustry.world;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntMap.Entry;
import com.badlogic.gdx.utils.ObjectIntMap;
import io.anuke.mindustry.world.blocks.Blocks;
public class ColorMapper{
private static ObjectIntMap<Block> reverseColors = new ObjectIntMap<>();
private static Array<BlockPair> pairs = new Array<>();
private static IntMap<BlockPair> colors = map(
"323232", pair(Blocks.stone),
"646464", pair(Blocks.stone, Blocks.stoneblock),
"50965a", pair(Blocks.grass),
"5ab464", pair(Blocks.grass, Blocks.grassblock),
"506eb4", pair(Blocks.water),
"465a96", pair(Blocks.deepwater),
"252525", pair(Blocks.blackstone),
"575757", pair(Blocks.blackstone, Blocks.blackstoneblock),
"988a67", pair(Blocks.sand),
"e5d8bb", pair(Blocks.sand, Blocks.sandblock),
"c2d1d2", pair(Blocks.snow),
"c4e3e7", pair(Blocks.ice),
"f7feff", pair(Blocks.snow, Blocks.snowblock),
"6e501e", pair(Blocks.dirt),
"ed5334", pair(Blocks.lava),
"292929", pair(Blocks.oil)
);
public static BlockPair get(int color){
return colors.get(color);
}
public static IntMap<BlockPair> getColors(){
return colors;
}
public static Array<BlockPair> getPairs(){
return pairs;
}
public static int getColor(Block block){
return reverseColors.get(block, 0);
}
private static BlockPair pair(Block floor, Block wall){
return new BlockPair(floor, wall);
}
private static BlockPair pair(Block floor){
return new BlockPair(floor, Blocks.air);
}
private static IntMap<BlockPair> map(Object...objects){
IntMap<BlockPair> colors = new IntMap<>();
for(int i = 0; i < objects.length/2; i ++){
colors.put(Color.rgba8888(Color.valueOf((String)objects[i*2])), (BlockPair)objects[i*2+1]);
pairs.add((BlockPair)objects[i*2+1]);
}
for(Entry<BlockPair> e : colors.entries()){
reverseColors.put(e.value.wall == Blocks.air ? e.value.floor : e.value.wall, e.key);
}
return colors;
}
public static class BlockPair{
public final Block floor, wall;
private BlockPair(Block floor, Block wall){
this.floor = floor;
this.wall = wall;
}
}
}

View File

@ -2,42 +2,26 @@ package io.anuke.mindustry.world;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.enemies.TargetEnemy; import io.anuke.mindustry.entities.enemies.TargetEnemy;
import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.mindustry.world.blocks.Blocks;
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{
public static boolean debugBlockspam = false;
static final int spawn = Color.rgba8888(Color.RED); static final int spawn = Color.rgba8888(Color.RED);
static final int start = Color.rgba8888(Color.GREEN); static final int start = Color.rgba8888(Color.GREEN);
static final ObjectMap<Block, Block> rocks = new ObjectMap(){{
public static IntMap<Block> colors = map( put(Blocks.stone, Blocks.rock);
Hue.rgb(80, 150, 90), Blocks.grass, put(Blocks.snow, Blocks.icerock);
Hue.rgb(90, 180, 100), Blocks.grassblock, put(Blocks.grass, Blocks.shrub);
Hue.rgb(80, 110, 180), Blocks.water, put(Blocks.blackstone, Blocks.blackrock);
Hue.rgb(70, 90, 150), Blocks.deepwater, }};
Hue.rgb(110, 80, 30), Blocks.dirt,
Hue.rgb(160, 120, 70), Blocks.dirtblock,
Hue.rgb(100, 100, 100), Blocks.stoneblock,
Color.valueOf("323232"), Blocks.stone,
Color.valueOf("575757"), Blocks.blackstoneblock,
Color.valueOf("252525"), Blocks.blackstone,
Color.valueOf("ed5334"), Blocks.lava,
Color.valueOf("292929"), Blocks.oil,
Color.valueOf("e5d8bb"), Blocks.sandblock,
Color.valueOf("988a67"), Blocks.sand,
Color.valueOf("f7feff"), Blocks.snowblock,
Color.valueOf("c2d1d2"), Blocks.snow,
Color.valueOf("c4e3e7"), Blocks.ice
);
/**Returns world size.*/ /**Returns world size.*/
public static void generate(Pixmap pixmap, Tile[][] tiles){ public static void generate(Pixmap pixmap, Tile[][] tiles){
@ -50,14 +34,11 @@ public class Generator{
Block block = Blocks.air; Block block = Blocks.air;
int color = pixmap.getPixel(x, pixmap.getHeight()-1-y); int color = pixmap.getPixel(x, pixmap.getHeight()-1-y);
BlockPair pair = ColorMapper.get(color);
if(colors.containsKey(color)){ if(pair != null){
//TODO less hacky method block = pair.wall;
if(!(colors.get(color) instanceof Floor)){ floor = pair.floor;
block = colors.get(color);
}else{
floor = colors.get(color);
}
}else if(color == start){ }else if(color == start){
Vars.control.setCore(Vars.world.tile(x, y)); Vars.control.setCore(Vars.world.tile(x, y));
}else if(color == spawn){ }else if(color == spawn){
@ -65,18 +46,8 @@ public class Generator{
floor = Blocks.dirt; floor = Blocks.dirt;
} }
if(block == Blocks.air){ if(block == Blocks.air && Mathf.chance(0.025) && rocks.containsKey(floor)){
if(floor == Blocks.stone && Mathf.chance(0.02)){ block = rocks.get(floor);
block = Blocks.rock;
}
if(floor == Blocks.snow && Mathf.chance(0.02)){
block = Blocks.icerock;
}
if(floor == Blocks.blackstone && Mathf.chance(0.03)){
block = Blocks.blackrock;
}
} }
if(floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone || if(floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone ||
@ -98,32 +69,11 @@ public class Generator{
} }
} }
if(block == Blocks.grassblock){
floor = Blocks.grass;
}
if(block == Blocks.snowblock){
floor = Blocks.snow;
}
if(block == Blocks.sandblock){
floor = Blocks.sand;
}
if(floor == Blocks.grass && Mathf.chance(0.03) && block == Blocks.air){
block = Blocks.shrub;
}
if(color == Hue.rgb(Color.PURPLE)){ if(color == Hue.rgb(Color.PURPLE)){
if(!Vars.android) new TargetEnemy().set(x * Vars.tilesize, y * Vars.tilesize).add(); if(!Vars.android) new TargetEnemy().set(x * Vars.tilesize, y * Vars.tilesize).add();
floor = Blocks.stone; floor = Blocks.stone;
} }
//preformance debugging
if(debugBlockspam && Vector2.dst(0, 0, x, y) < 260){
block = Mathf.choose(ProductionBlocks.omnidrill, DistributionBlocks.conveyor, DistributionBlocks.router, WeaponBlocks.turret);
}
tiles[x][y].setBlock(block, 0); tiles[x][y].setBlock(block, 0);
tiles[x][y].setFloor(floor); tiles[x][y].setFloor(floor);
} }

View File

@ -1,49 +1,25 @@
package io.anuke.mindustry.world; package io.anuke.mindustry.world;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
public enum Map{ public class Map{
maze("desc"), public int id;
fortress("desc"), public String name;
sinkhole("desc"), public boolean visible = true;
caves("desc"), public boolean flipBase = false;
volcano("desc", true), public boolean custom = false;
caldera("desc"),
scorch("desc", Color.valueOf("e5d8bb")),
desert("desc"),
islands("desc", Color.valueOf("e5d8bb")),
grassland("desc", Color.valueOf("5ab464")),
tundra("desc"),
spiral("desc", Color.valueOf("f7feff")),
tutorial(false),
test1(false),
test2(false),
test3(false);
public final boolean visible;
public final String description;
public final boolean flipBase;
public int width, height;
public Color backgroundColor = Color.valueOf("646464"); public Color backgroundColor = Color.valueOf("646464");
private Map(boolean visible){ public transient Pixmap pixmap;
this.visible = visible; public transient Texture texture;
this.flipBase = false;
this.description = "Test map!"; public int getWidth(){
return pixmap.getWidth();
} }
private Map(String description){ public int getHeight(){
this(description, false); return pixmap.getHeight();
}
private Map(String description, boolean flipBase){
this.visible = true;
this.flipBase = flipBase;
this.description = description;
}
private Map(String description, Color background){
this(description);
backgroundColor = background;
} }
} }

View File

@ -0,0 +1,119 @@
package io.anuke.mindustry.world;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.*;
import com.badlogic.gdx.utils.Json.Serializer;
import com.badlogic.gdx.utils.JsonWriter.OutputType;
import io.anuke.mindustry.Vars;
import io.anuke.ucore.graphics.Pixmaps;
public class Maps implements Disposable{
private IntMap<Map> maps = new IntMap<>();
private ObjectMap<String, Map> mapNames = new ObjectMap<>();
private int lastID;
private Json json = new Json();
public Maps() {
json.setOutputType(OutputType.json);
json.setElementType(ArrayContainer.class, "maps", Map.class);
json.setSerializer(Color.class, new ColorSerializer());
}
public Iterable<Map> list(){
return maps.values();
}
public Map getMap(int id){
return maps.get(id);
}
public Map getMap(String name){
return mapNames.get(name);
}
public void loadMaps(){
if(!loadMapFile(Gdx.files.internal("maps/maps.json"))){
throw new RuntimeException("Failed to load maps!");
}
if(!loadMapFile(Vars.customMapDirectory.child("maps.json"))){
try{
Vars.customMapDirectory.child("maps.json").writeString("{}", false);
}catch(Exception e){
throw new RuntimeException("Failed to create custom map directory!");
}
}
}
public void saveMaps(Array<Map> array, FileHandle file){
json.toJson(new ArrayContainer(array), file);
}
public void saveCustomMap(Map toSave){
Array<Map> out = new Array<>();
for(Map map : maps.values()){
if(map.custom)
out.add(map);
}
Pixmaps.write(toSave.pixmap, Vars.customMapDirectory.child(toSave.name + ".png"));
saveMaps(out, Vars.customMapDirectory.child("maps.json"));
}
private boolean loadMapFile(FileHandle file){
try{
Array<Map> arr = json.fromJson(ArrayContainer.class, file).maps;
if(arr != null){ //can be an empty map file
for(Map map : arr){
map.pixmap = new Pixmap(file.sibling(map.name + ".png"));
map.texture = new Texture(map.pixmap);
maps.put(map.id, map);
mapNames.put(map.name, map);
}
}
return true;
}catch(Exception e){
e.printStackTrace();
Gdx.app.error("Mindustry-Maps", "Failed loading map file: " + file);
return false;
}
}
@Override
public void dispose(){
for(Map map : maps.values()){
map.texture.dispose();
map.pixmap.dispose();
}
maps.clear();
}
private static class ArrayContainer{
Array<Map> maps;
ArrayContainer() {
}
ArrayContainer(Array<Map> maps) {
this.maps = maps;
}
}
private class ColorSerializer implements Serializer<Color>{
@Override
public void write(Json json, Color object, Class knownType){
json.writeValue(object.toString().substring(0, 6));
}
@Override
public Color read(Json json, JsonValue jsonData, Class type){
return Color.valueOf(jsonData.asString());
}
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -23,7 +23,7 @@ public class DesktopLauncher {
config.setMaximized(true); config.setMaximized(true);
config.setWindowedMode(960, 540); config.setWindowedMode(960, 540);
config.setWindowIcon("sprites/icon.png"); config.setWindowIcon("sprites/icon.png");
config.useVsync(false); config.useVsync(true);
Mindustry.platforms = new PlatformFunction(){ Mindustry.platforms = new PlatformFunction(){
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm"); SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm");