diff --git a/build.gradle b/build.gradle index 069758fa8e..356a58ccfa 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ project(":core") { apply plugin: "java" dependencies { - compile 'com.github.anuken:ucore:be4ae33e40' + compile 'com.github.anuken:ucore:f77bdb38e4' compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-ai:1.8.1" } diff --git a/core/assets-raw/ui/icon-cursor.png b/core/assets-raw/ui/icon-cursor.png new file mode 100644 index 0000000000..7f8d2c80d8 Binary files /dev/null and b/core/assets-raw/ui/icon-cursor.png differ diff --git a/core/assets-raw/ui/icon-rotate-arrow.png b/core/assets-raw/ui/icon-rotate-arrow.png new file mode 100644 index 0000000000..c2ea8f2703 Binary files /dev/null and b/core/assets-raw/ui/icon-rotate-arrow.png differ diff --git a/core/assets-raw/ui/icon-touch.png b/core/assets-raw/ui/icon-touch.png new file mode 100644 index 0000000000..4e96232fab Binary files /dev/null and b/core/assets-raw/ui/icon-touch.png differ diff --git a/core/assets/ui/uiskin.atlas b/core/assets/ui/uiskin.atlas index 5d7a2ea96d..9926e77897 100644 --- a/core/assets/ui/uiskin.atlas +++ b/core/assets/ui/uiskin.atlas @@ -13,7 +13,7 @@ blank index: -1 border rotate: false - xy: 344, 25 + xy: 360, 35 size: 12, 12 split: 4, 4, 4, 4 orig: 12, 12 @@ -43,7 +43,7 @@ border-dark-blue index: -1 border-error rotate: false - xy: 43, 7 + xy: 37, 7 size: 3, 3 split: 1, 1, 1, 1 orig: 3, 3 @@ -222,7 +222,7 @@ color-picker-bar-selector index: -1 color-picker-cross rotate: false - xy: 332, 11 + xy: 360, 23 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -250,14 +250,14 @@ cursor index: -1 cursor-normal rotate: false - xy: 344, 13 + xy: 374, 37 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 default-pane rotate: false - xy: 382, 44 + xy: 389, 37 size: 5, 3 split: 1, 1, 1, 1 orig: 5, 3 @@ -281,7 +281,7 @@ default-select index: -1 default-select-selection rotate: false - xy: 43, 2 + xy: 37, 2 size: 3, 3 split: 1, 1, 1, 1 orig: 3, 3 @@ -336,44 +336,51 @@ icon-close-over orig: 40, 40 offset: 0, 0 index: -1 +icon-cursor + rotate: false + xy: 332, 11 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 icon-defense rotate: false - xy: 358, 37 + xy: 344, 11 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 358, 25 + xy: 356, 11 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 356, 13 + xy: 368, 11 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 370, 37 + xy: 372, 23 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play rotate: false - xy: 370, 25 + xy: 380, 11 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-production rotate: false - xy: 368, 13 + xy: 384, 23 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -385,16 +392,30 @@ icon-rotate orig: 14, 14 offset: 0, 0 index: -1 +icon-rotate-arrow + rotate: false + xy: 344, 23 + size: 14, 14 + orig: 14, 14 + offset: 0, 0 + index: -1 icon-settings rotate: false - xy: 382, 30 + xy: 396, 30 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +icon-touch + rotate: false + xy: 396, 18 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 list-selection rotate: false - xy: 205, 83 + xy: 386, 36 size: 1, 1 orig: 1, 1 offset: 0, 0 @@ -507,14 +528,14 @@ scroll-knob-vertical index: -1 select-box-list-bg rotate: false - xy: 328, 20 + xy: 205, 83 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 window-bg rotate: false - xy: 328, 20 + xy: 205, 83 size: 1, 1 orig: 1, 1 offset: 0, 0 @@ -535,35 +556,35 @@ select-up index: -1 selection rotate: false - xy: 495, 92 + xy: 328, 20 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 separator rotate: false - xy: 505, 44 + xy: 404, 15 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 tree-over rotate: false - xy: 505, 44 + xy: 404, 15 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 separator-menu rotate: false - xy: 508, 44 + xy: 392, 20 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 34, 2 + xy: 386, 39 size: 1, 8 orig: 1, 8 offset: 0, 0 @@ -627,14 +648,14 @@ splitpane-over index: -1 splitpane-vertical rotate: false - xy: 37, 2 + xy: 34, 2 size: 1, 8 orig: 1, 8 offset: 0, 0 index: -1 splitpane-vertical-over rotate: false - xy: 40, 2 + xy: 356, 39 size: 1, 8 orig: 1, 8 offset: 0, 0 @@ -664,7 +685,7 @@ textfield-over index: -1 tooltip-bg rotate: false - xy: 75, 5 + xy: 408, 37 size: 3, 3 split: 1, 1, 1, 1 orig: 3, 3 @@ -679,7 +700,7 @@ touchpad-knob index: -1 tree-minus rotate: false - xy: 394, 30 + xy: 392, 6 size: 10, 10 orig: 10, 10 offset: 0, 0 @@ -693,7 +714,7 @@ tree-plus index: -1 tree-selection rotate: false - xy: 382, 25 + xy: 413, 37 size: 3, 3 split: 1, 1, 1, 1 orig: 3, 3 @@ -701,7 +722,7 @@ tree-selection index: -1 white rotate: false - xy: 380, 20 + xy: 75, 5 size: 3, 3 orig: 3, 3 offset: 0, 0 @@ -716,7 +737,7 @@ window index: -1 window-border-bg rotate: false - xy: 406, 37 + xy: 495, 90 size: 3, 3 split: 1, 1, 1, 1 orig: 3, 3 diff --git a/core/assets/ui/uiskin.png b/core/assets/ui/uiskin.png index 83be1eb604..ec2d7481c7 100644 Binary files a/core/assets/ui/uiskin.png and b/core/assets/ui/uiskin.png differ diff --git a/core/src/io/anuke/mindustry/Control.java b/core/src/io/anuke/mindustry/Control.java index 902be9be7f..b828f521c2 100644 --- a/core/src/io/anuke/mindustry/Control.java +++ b/core/src/io/anuke/mindustry/Control.java @@ -114,7 +114,7 @@ public class Control extends Module{ }}, new EnemySpawn(RapidEnemy.class){{ after = 7; - spacing = 5; + spacing = 4; }}, new EnemySpawn(TankEnemy.class){{ after = 4; @@ -129,13 +129,13 @@ public class Control extends Module{ ); + /* //TODO remove this debugging for(int i = 1; i < 60; i ++){ UCore.log("\n\n--WAVE " + i); printEnemies(i); } - - + */ } public void reset(){ diff --git a/core/src/io/anuke/mindustry/EffectLoader.java b/core/src/io/anuke/mindustry/EffectLoader.java index a9d41e5e53..c0882fb5ba 100644 --- a/core/src/io/anuke/mindustry/EffectLoader.java +++ b/core/src/io/anuke/mindustry/EffectLoader.java @@ -121,6 +121,21 @@ public class EffectLoader{ Draw.spikes(e.x, e.y, e.ifract() * 2f, 1, 5); Draw.reset(); }); + + Effects.create("railshoot", 8, e -> { + Draw.thickness(2f - e.ifract()*2f); + Draw.color(Hue.mix(Color.WHITE, Color.LIGHT_GRAY, e.ifract())); + Draw.spikes(e.x, e.y, 1f + e.ifract() * 4f, 1, 5); + Draw.reset(); + }); + + Effects.create("mortarshoot", 9, e -> { + Draw.thickness(1.3f - e.ifract()); + Draw.color(Hue.mix(Color.WHITE, Color.ORANGE, e.ifract())); + Draw.spikes(e.x, e.y, e.ifract() * 4f, 2, 6); + Draw.circle(e.x, e.y, e.ifract() * 5f + 1f); + Draw.reset(); + }); Effects.create("explosion", 15, e -> { Draw.thickness(2f); diff --git a/core/src/io/anuke/mindustry/Renderer.java b/core/src/io/anuke/mindustry/Renderer.java index 4e5cefc658..6933d9ad13 100644 --- a/core/src/io/anuke/mindustry/Renderer.java +++ b/core/src/io/anuke/mindustry/Renderer.java @@ -13,6 +13,7 @@ import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.GameState.State; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.input.AndroidInput; +import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.World; import io.anuke.mindustry.world.blocks.Blocks; @@ -26,145 +27,142 @@ import io.anuke.ucore.graphics.Caches; import io.anuke.ucore.modules.RendererModule; import io.anuke.ucore.scene.ui.layout.Unit; import io.anuke.ucore.scene.utils.Cursors; -import io.anuke.ucore.util.GridMap; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; public class Renderer extends RendererModule{ int targetscale = baseCameraScale; int chunksize = 32; - GridMap caches = new GridMap<>(); - - public Renderer(){ + Cache[][] floorCache; + + public Renderer() { Core.cameraScale = baseCameraScale; pixelate(); - + Draw.addSurface("shadow", Core.cameraScale); Shaders.create(); } - + @Override public void update(){ if(Core.cameraScale != targetscale){ - float targetzoom = (float)Core.cameraScale / targetscale; - camera.zoom = Mathf.lerp(camera.zoom, targetzoom, 0.2f*Timers.delta()); - + float targetzoom = (float) Core.cameraScale / targetscale; + camera.zoom = Mathf.lerp(camera.zoom, targetzoom, 0.2f * Timers.delta()); + if(Mathf.in(camera.zoom, targetzoom, 0.005f)){ camera.zoom = 1f; Core.cameraScale = targetscale; camera.viewportWidth = Gdx.graphics.getWidth() / Core.cameraScale; camera.viewportHeight = Gdx.graphics.getHeight() / Core.cameraScale; - - AndroidInput.mousex = Gdx.graphics.getWidth()/2; - AndroidInput.mousey = Gdx.graphics.getHeight()/2; + + AndroidInput.mousex = Gdx.graphics.getWidth() / 2; + AndroidInput.mousey = Gdx.graphics.getHeight() / 2; } } - + if(GameState.is(State.menu)){ clearScreen(); }else{ - + if(World.core.block() == ProductionBlocks.core){ smoothCamera(player.x, player.y, android ? 0.3f : 0.14f); }else{ smoothCamera(World.core.worldx(), World.core.worldy(), 0.4f); } - + float prex = camera.position.x, prey = camera.position.y; - + updateShake(0.75f); float prevx = camera.position.x, prevy = camera.position.y; clampCamera(-tilesize / 2f, -tilesize / 2f, World.pixsize - tilesize / 2f, World.pixsize - tilesize / 2f); - + float deltax = camera.position.x - prex, deltay = camera.position.y - prey; - + if(android){ - player.x += camera.position.x-prevx; - player.y += camera.position.y-prevy; + player.x += camera.position.x - prevx; + player.y += camera.position.y - prevy; } - + float lastx = camera.position.x, lasty = camera.position.y; - + if(android){ - camera.position.set((int)camera.position.x, (int)camera.position.y, 0); - - if(Gdx.graphics.getHeight()/Core.cameraScale % 2 == 1){ + camera.position.set((int) camera.position.x, (int) camera.position.y, 0); + + if(Gdx.graphics.getHeight() / Core.cameraScale % 2 == 1){ camera.position.add(0, -0.5f, 0); } } - + drawDefault(); - + camera.position.set(lastx - deltax, lasty - deltay, 0); - + if(Vars.debug){ record(); } } } - + @Override public void draw(){ renderTiles(); Entities.draw(); renderPixelOverlay(); } - + @Override public void resize(int width, int height){ super.resize(width, height); - - AndroidInput.mousex = Gdx.graphics.getWidth()/2; - AndroidInput.mousey = Gdx.graphics.getHeight()/2; + + AndroidInput.mousex = Gdx.graphics.getWidth() / 2; + AndroidInput.mousey = Gdx.graphics.getHeight() / 2; camera.position.set(player.x, player.y, 0); } - + void renderTiles(){ - int chunksx = World.width()/chunksize, chunksy = World.height()/chunksize; - + int chunksx = World.width() / chunksize, chunksy = World.height() / chunksize; + //render the entire map - if(caches.size() == 0){ - for(int cx = 0; cx < chunksx; cx ++){ - for(int cy = 0; cy < chunksy; cy ++){ - Caches.begin(1600); - - for(int tilex = cx*chunksize; tilex < (cx+1)*chunksize; tilex++){ - for(int tiley = cy*chunksize; tiley < (cy+1)*chunksize; tiley++){ - World.tile(tilex, tiley).floor().drawCache(World.tile(tilex, tiley)); - } - } - caches.put(cx, cy, Caches.end()); - } - } + if(floorCache == null || floorCache.length != chunksx || floorCache[0].length != chunksy){ + floorCache = new Cache[chunksx][chunksy]; } - + OrthographicCamera camera = Core.camera; - + Draw.end(); - - int crangex = (int)(camera.viewportWidth/(chunksize*tilesize))+1; - int crangey = (int)(camera.viewportHeight/(chunksize*tilesize))+1; - + + int crangex = (int) (camera.viewportWidth / (chunksize * tilesize)) + 1; + int crangey = (int) (camera.viewportHeight / (chunksize * tilesize)) + 1; + for(int x = -crangex; x <= crangex; x++){ for(int y = -crangey; y <= crangey; y++){ - int worldx = Mathf.scl(camera.position.x, chunksize*tilesize) + x; - int worldy = Mathf.scl(camera.position.y, chunksize*tilesize) + y; - - if(caches.containsKey(worldx, worldy)) - caches.get(worldx, worldy).render(); + int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; + int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; + + if(!Mathf.inBounds(worldx, worldy, floorCache)) + continue; + + if(floorCache[worldx][worldy] == null){ + renderCache(worldx, worldy); + } + + floorCache[worldx][worldy].render(); } } - + Draw.begin(); - + Draw.reset(); - int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2)+2; - int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2)+2; - + int rangex = (int) (camera.viewportWidth * camera.zoom / tilesize / 2) + 2; + int rangey = (int) (camera.viewportHeight * camera.zoom / tilesize / 2) + 2; + boolean noshadows = Settings.getBool("noshadows"); - - for(int l = (noshadows ? 1 : 0); l < 4; l++){ + + //0 = shadows + //1 = normal blocks + //2 = over blocks + for(int l = (noshadows ? 1 : 0); l < 3; l++){ if(l == 0){ Draw.surface("shadow"); } @@ -174,14 +172,15 @@ public class Renderer extends RendererModule{ int worldx = Mathf.scl(camera.position.x, tilesize) + x; int worldy = Mathf.scl(camera.position.y, tilesize) + y; - if( World.tile(worldx, worldy) != null){ + if(World.tile(worldx, worldy) != null){ Tile tile = World.tile(worldx, worldy); if(l == 0){ - if(tile.block() != Blocks.air) + if(tile.block() != Blocks.air){ Draw.rect(tile.block().shadow, worldx * tilesize, worldy * tilesize); + } }else if(l == 1){ tile.block().draw(tile); - }else{ + }else if(l == 2){ tile.block().drawOver(tile); } } @@ -195,23 +194,34 @@ public class Renderer extends RendererModule{ } } } - - public void clearTiles(){ - for(Cache cache : caches.values()) - cache.dispose(); + + void renderCache(int cx, int cy){ + Caches.begin(1600); + + for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ + for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ + Tile tile = World.tile(tilex, tiley); + tile.floor().drawCache(tile); + + } + } + floorCache[cx][cy] = Caches.end(); - caches.clear(); } - + + public void clearTiles(){ + floorCache = null; + } + void renderPixelOverlay(){ - - if(player.recipe != null && Inventory.hasItems(player.recipe.requirements) && (!ui.hasMouse() || android)){ + + if(player.recipe != null && Inventory.hasItems(player.recipe.requirements) && (!ui.hasMouse() || android) && AndroidInput.mode == PlaceMode.cursor){ float x = 0; float y = 0; - + int tilex = 0; int tiley = 0; - + if(android){ Vector2 vec = Graphics.world(AndroidInput.mousex, AndroidInput.mousey); x = Mathf.round2(vec.x, tilesize); @@ -230,7 +240,7 @@ public class Renderer extends RendererModule{ Draw.color(valid ? Color.PURPLE : Color.SCARLET); Draw.thickness(2f); Draw.square(x, y, tilesize / 2 + MathUtils.sin(Timers.time() / 6f) + 1); - + player.recipe.result.drawPlace(tilex, tiley, valid); if(player.recipe.result.rotate){ @@ -238,7 +248,7 @@ public class Renderer extends RendererModule{ Tmp.v1.set(7, 0).rotate(player.rotation * 90); Draw.line(x, y, x + Tmp.v1.x, y + Tmp.v1.y); } - + Draw.thickness(1f); Draw.color("scarlet"); for(Tile spawn : World.spawnpoints){ @@ -249,7 +259,7 @@ public class Renderer extends RendererModule{ Cursors.setHand(); else Cursors.restoreCursor(); - + Draw.reset(); } @@ -262,13 +272,14 @@ public class Renderer extends RendererModule{ Draw.reset(); } } - + if(android && player.breaktime > 0){ - Tile tile = AndroidInput.selected(); + Vector2 vec = Graphics.world(Gdx.input.getX(0), Gdx.input.getY(0)); + Tile tile = World.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize)); if(tile.breakable() && tile.block() != ProductionBlocks.core){ float fract = player.breaktime / tile.block().breaktime; Draw.color(Color.YELLOW, Color.SCARLET, fract); - Draw.circle(tile.worldx(), tile.worldy(), 4 + (1f-fract)*26); + Draw.circle(tile.worldx(), tile.worldy(), 4 + (1f - fract) * 26); Draw.reset(); } } @@ -278,8 +289,8 @@ public class Renderer extends RendererModule{ if(tile != null && tile.block() != Blocks.air){ if(tile.entity != null) - drawHealth(tile.entity.x, tile.entity.y, tile.entity.health, tile.entity.maxhealth); - + drawHealth(tile.entity.x, tile.entity.y, tile.entity.health, tile.entity.maxhealth); + tile.block().drawPixelOverlay(tile); } } @@ -292,20 +303,20 @@ public class Renderer extends RendererModule{ } } } - + void drawHealth(float x, float y, float health, float maxhealth){ - drawBar(Color.RED, x, y, health/maxhealth); + drawBar(Color.RED, x, y, health / maxhealth); } - + public void drawBar(Color color, float x, float y, float fraction){ float len = 3; float offset = 7; - - float w = (int)(len * 2 * fraction) + 0.5f; - + + float w = (int) (len * 2 * fraction) + 0.5f; + x -= 0.5f; y += 0.5f; - + Draw.thickness(3f); Draw.color(Color.SLATE); Draw.line(x - len + 1, y - offset, x + len + 1.5f, y - offset); @@ -317,20 +328,20 @@ public class Renderer extends RendererModule{ Draw.line(x - len + 1, y - offset, x - len + w, y - offset); Draw.reset(); } - + public void setCameraScale(int amount){ targetscale = amount; clampScale(); Draw.getSurface("pixel").setScale(targetscale); Draw.getSurface("shadow").setScale(targetscale); } - + public void scaleCamera(int amount){ setCameraScale(targetscale + amount); } - + public void clampScale(){ - targetscale = Mathf.clamp(targetscale, Math.round(Unit.dp.inPixels(3)), Math.round(Unit.dp.inPixels((5)))); + targetscale = Mathf.clamp(targetscale, Math.round(Unit.dp.inPixels(2)), Math.round(Unit.dp.inPixels((5)))); } - + } diff --git a/core/src/io/anuke/mindustry/UI.java b/core/src/io/anuke/mindustry/UI.java index 03ed3321a2..142e10fe6b 100644 --- a/core/src/io/anuke/mindustry/UI.java +++ b/core/src/io/anuke/mindustry/UI.java @@ -16,6 +16,7 @@ import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.GameState.State; import io.anuke.mindustry.input.AndroidInput; +import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.resource.*; import io.anuke.mindustry.ui.*; import io.anuke.ucore.core.Core; @@ -25,6 +26,7 @@ import io.anuke.ucore.function.VisibilityProvider; import io.anuke.ucore.modules.SceneModule; import io.anuke.ucore.scene.actions.Actions; import io.anuke.ucore.scene.builders.*; +import io.anuke.ucore.scene.event.Touchable; import io.anuke.ucore.scene.ui.*; import io.anuke.ucore.scene.ui.Window.WindowStyle; import io.anuke.ucore.scene.ui.layout.*; @@ -129,12 +131,16 @@ public class UI extends SceneModule{ prefs.checkPref("noshadows", "Disable shadows", false); prefs.hidden(()->{ - GameState.set(State.playing); + if(!GameState.is(State.menu)){ + GameState.set(State.playing); + } }); prefs.shown(()->{ - GameState.set(State.paused); - menu.hide(); + if(!GameState.is(State.menu)){ + GameState.set(State.paused); + menu.hide(); + } }); keys = new KeybindDialog(); @@ -214,7 +220,7 @@ public class UI extends SceneModule{ player.recipe = null; } }); - add(button).fill().height(54).padTop(-10).units(Unit.dp); + add(button).fill().height(54).padRight(-0.1f).padTop(-10).units(Unit.dp); button.getImageCell().size(40).padBottom(4).units(Unit.dp); group.add(button); @@ -244,7 +250,7 @@ public class UI extends SceneModule{ //image.setDisabled(!has); image.setChecked(player.recipe == r); //image.setTouchable(has ? Touchable.enabled : Touchable.disabled); - image.getImage().setColor(has ? Color.WHITE : Color.GRAY); + image.getImage().setColor(has ? Color.WHITE : Color.DARK_GRAY); }); if(i % rows == rows-1) @@ -306,7 +312,6 @@ public class UI extends SceneModule{ }); new imagebutton("icon-pause", isize, ()->{ - //TODO pause GameState.set(GameState.is(State.paused) ? State.playing : State.paused); }){{ get().update(()->{ @@ -333,7 +338,7 @@ public class UI extends SceneModule{ atop(); new table("pane"){{ - new label("[orange]< paused >").scale(0.75f).pad(6); + new label("[orange]< paused >").scale(Unit.dp.inPixels(0.75f)).pad(6).units(Unit.dp); }}.end(); }}.end(); @@ -419,12 +424,14 @@ public class UI extends SceneModule{ }}.end(); } + //respawn background table new table("white"){{ respawntable = get(); respawntable.setColor(Color.CLEAR); }}.end(); + //respawn table new table(){{ new table("pane"){{ @@ -435,7 +442,55 @@ public class UI extends SceneModule{ }}.end(); }}.end(); + if(android){ + //placement table + new table(){{ + visible(()->player.recipe != null); + abottom(); + aleft(); + + + new table("pane"){{ + new label(()->"Placement Mode: [orange]" + AndroidInput.mode.name()).pad(4).units(Unit.dp); + row(); + + aleft(); + + new table(){{ + aleft(); + ButtonGroup group = new ButtonGroup<>(); + + defaults().size(58, 62).pad(6).units(Unit.dp); + + for(PlaceMode mode : PlaceMode.values()){ + new imagebutton("icon-" + mode.name(), "toggle", Unit.dp.inPixels(10*3), ()->{ + AndroidInput.mode = mode; + }){{ + group.add(get()); + }}; + } + + new imagebutton("icon-cancel", Unit.dp.inPixels(14*3), ()->{ + player.recipe = null; + }).visible(()->player.recipe != null && AndroidInput.mode == PlaceMode.touch); + + new imagebutton("icon-rotate-arrow", Unit.dp.inPixels(14*3), ()->{ + player.rotation ++; + player.rotation %= 4; + }).update(i->{ + i.getImage().setOrigin(Align.center); + i.getImage().setRotation(player.rotation*90); + }).visible(()->player.recipe != null && AndroidInput.mode == PlaceMode.touch + && player.recipe.result.rotate); + + }}.left().end(); + }}.end(); + }}.end(); + + } + loadingtable = new table("loadDim"){{ + get().setTouchable(Touchable.enabled); new table("button"){{ new label("[orange]Loading..."){{ get().setName("namelabel"); @@ -449,20 +504,22 @@ public class UI extends SceneModule{ tools.addIButton("icon-cancel", Unit.dp.inPixels(42), ()->{ player.recipe = null; }); + tools.addIButton("icon-rotate", Unit.dp.inPixels(42), ()->{ - player.rotation++; - + player.rotation ++; player.rotation %= 4; }); + tools.addIButton("icon-check", Unit.dp.inPixels(42), ()->{ AndroidInput.place(); }); scene.add(tools); - tools.setVisible(()->{ - return !GameState.is(State.menu) && android && player.recipe != null && Inventory.hasItems(player.recipe.requirements); - }); + tools.setVisible(()-> + !GameState.is(State.menu) && android && player.recipe != null && Inventory.hasItems(player.recipe.requirements) && + AndroidInput.mode == PlaceMode.cursor + ); tools.update(()->{ tools.setPosition(AndroidInput.mousex, Gdx.graphics.getHeight()-AndroidInput.mousey-15*Core.cameraScale, Align.top); @@ -578,6 +635,16 @@ public class UI extends SceneModule{ }); } + public void showError(String text){ + new Dialog("[crimson]An error has occured", "dialog"){{ + content().pad(Unit.dp.inPixels(15)); + content().add(text); + getButtonTable().addButton("OK", ()->{ + hide(); + }).size(90, 50).pad(4).units(Unit.dp); + }}.show(); + } + public void showLoading(){ showLoading("[orange]Loading.."); } diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 7fad0ae946..7da5cbb7f1 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -14,7 +14,7 @@ public class Vars{ //respawn time in frames public static final float respawnduration = 60*4; //time between waves in frames - public static final float wavespace = 35*60*(android ? 2 : 1); + public static final float wavespace = 25*60*(android ? 1 : 1); //waves can last no longer than 6 minutes, otherwise the next one spawns public static final float maxwavespace = 60*60*6; //how far away from spawn points the player can't place blocks diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index d338075034..133b58ea97 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -47,7 +47,7 @@ public class Enemy extends DestructibleEntity{ hitsize = 5; - maxhealth = 30; + maxhealth = 50; heal(); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/FastEnemy.java b/core/src/io/anuke/mindustry/entities/enemies/FastEnemy.java index 276a842fc6..1922a421d7 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/FastEnemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/FastEnemy.java @@ -8,7 +8,7 @@ public class FastEnemy extends Enemy{ speed = 0.7f; reload = 30; - maxhealth = 20; + maxhealth = 30; heal(); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/TankEnemy.java b/core/src/io/anuke/mindustry/entities/enemies/TankEnemy.java index a995e350f9..52a95bbb59 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/TankEnemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/TankEnemy.java @@ -1,6 +1,9 @@ package io.anuke.mindustry.entities.enemies; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; +import io.anuke.ucore.util.Angles; public class TankEnemy extends Enemy{ @@ -9,8 +12,19 @@ public class TankEnemy extends Enemy{ maxhealth = 400; speed = 0.2f; - reload = 140f; - bullet = BulletType.iron; + reload = 90f; + bullet = BulletType.small; + } + + void shoot(){ + vector.set(length, 0).rotate(direction.angle()); + + Angles.shotgun(3, 4f, direction.angle(), f->{ + Bullet out = new Bullet(bullet, this, x+vector.x, y+vector.y, f).add(); + out.damage = (int)(damage*Vars.multiplier); + }); + + } } diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java index 15e5fce27a..78bfadbb40 100644 --- a/core/src/io/anuke/mindustry/input/AndroidInput.java +++ b/core/src/io/anuke/mindustry/input/AndroidInput.java @@ -18,6 +18,8 @@ import io.anuke.ucore.util.Mathf; public class AndroidInput extends InputAdapter{ public static float mousex, mousey; + public static PlaceMode mode = PlaceMode.cursor; + public static boolean brokeBlock = false; private static float lmousex, lmousey; private static float warmup; private static float warmupDelay = 20; @@ -30,6 +32,12 @@ public class AndroidInput extends InputAdapter{ return false; } + @Override + public boolean touchUp (int screenX, int screenY, int pointer, int button) { + brokeBlock = false; + return false; + } + @Override public boolean touchDown (int screenX, int screenY, int pointer, int button) { ui.hideTooltip(); @@ -49,7 +57,9 @@ public class AndroidInput extends InputAdapter{ public static void breakBlock(){ Tile tile = selected(); player.breaktime += Timers.delta(); + if(player.breaktime >= tile.block().breaktime){ + brokeBlock = true; if(tile.block().drops != null){ Inventory.addItem(tile.block().drops.item, tile.block().drops.amount); } @@ -92,9 +102,11 @@ public class AndroidInput extends InputAdapter{ public static void doInput(){ if(Gdx.input.isTouched(0) && Mathf.near2d(lmousex, lmousey, Gdx.input.getX(0), Gdx.input.getY(0), 50) - && !ui.hasMouse() && player.recipe == null){ + && !ui.hasMouse() /*&& (player.recipe == null || mode == PlaceMode.touch)*/){ warmup += Timers.delta(); + float lx = mousex, ly = mousey; + mousex = Gdx.input.getX(0); mousey = Gdx.input.getY(0); @@ -110,6 +122,9 @@ public class AndroidInput extends InputAdapter{ player.breaktime = 0; } } + + mousex = lx; + mousey = ly; }else{ warmup = 0; lmousex = Gdx.input.getX(0); diff --git a/core/src/io/anuke/mindustry/input/GestureHandler.java b/core/src/io/anuke/mindustry/input/GestureHandler.java index 22e2af2dd7..2dca30f2cb 100644 --- a/core/src/io/anuke/mindustry/input/GestureHandler.java +++ b/core/src/io/anuke/mindustry/input/GestureHandler.java @@ -6,13 +6,9 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.input.GestureDetector.GestureAdapter; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.GameState; -import io.anuke.mindustry.GameState.State; import io.anuke.mindustry.Inventory; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.World; -import io.anuke.mindustry.world.blocks.Blocks; -import io.anuke.ucore.core.*; +import io.anuke.mindustry.Vars; +import io.anuke.ucore.core.Core; import io.anuke.ucore.scene.ui.layout.Unit; public class GestureHandler extends GestureAdapter{ @@ -23,6 +19,7 @@ public class GestureHandler extends GestureAdapter{ @Override public boolean longPress(float x, float y){ + /* Tile tile = World.cursorTile(); player.breaktime += Timers.delta(); if(!GameState.is(State.menu) && player.breaktime >= tile.block().breaktime){ @@ -31,16 +28,28 @@ public class GestureHandler extends GestureAdapter{ tile.setBlock(Blocks.air); player.breaktime = 0f; Sounds.play("break"); + }*/ + return false; + } + + @Override + public boolean tap (float x, float y, int count, int button) { + if(AndroidInput.mode == PlaceMode.touch && !ui.hasMouse() && player.recipe != null && + Inventory.hasItems(player.recipe.requirements) && !Vars.ui.hasMouse() && !AndroidInput.brokeBlock){ + AndroidInput.mousex = x; + AndroidInput.mousey = y; + AndroidInput.place(); + return true; } return false; } @Override public boolean pan(float x, float y, float deltaX, float deltaY){ - if(player.recipe == null || !Inventory.hasItems(player.recipe.requirements)){ + if(player.recipe == null || !Inventory.hasItems(player.recipe.requirements) || AndroidInput.mode == PlaceMode.touch){ player.x -= deltaX*Core.camera.zoom/Core.cameraScale; player.y += deltaY*Core.camera.zoom/Core.cameraScale; - }else{ + }else if(AndroidInput.mode == PlaceMode.cursor){ AndroidInput.mousex += deltaX; AndroidInput.mousey += deltaY; } diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java new file mode 100644 index 0000000000..b180aa3c55 --- /dev/null +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -0,0 +1,5 @@ +package io.anuke.mindustry.input; + +public enum PlaceMode{ + cursor, touch; +} diff --git a/core/src/io/anuke/mindustry/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index 3e9cc9453e..afa490a9b0 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; @@ -72,6 +73,7 @@ public enum Weapon{ float ang = mouseAngle(p); bullet(p, p.x, p.y, ang); + Effects.effect("railshoot", p.x + vector.x, p.y+vector.y); } }, mortar(100, BulletType.shell, "Shoots a slow, but damaging shell.", stack(Item.titanium, 40), stack(Item.steel, 60)){ @@ -80,6 +82,8 @@ public enum Weapon{ public void shoot(Player p){ float ang = mouseAngle(p); bullet(p, p.x, p.y, ang); + Effects.effect("mortarshoot", p.x + vector.x, p.y+vector.y); + Effects.shake(2f, 2f, Vars.player); } }; public float reload; diff --git a/core/src/io/anuke/mindustry/ui/LoadDialog.java b/core/src/io/anuke/mindustry/ui/LoadDialog.java index 1454c9ae06..1fb0039a62 100644 --- a/core/src/io/anuke/mindustry/ui/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/LoadDialog.java @@ -16,52 +16,58 @@ public class LoadDialog extends Dialog{ public LoadDialog() { super("Load Game"); setup(); - - shown(()->{ + + shown(() -> { setup(); }); - - getButtonTable().addButton("Back", ()->{ + + getButtonTable().addButton("Back", () -> { hide(); }).pad(2).size(180, 44).units(Unit.dp); } - + private void setup(){ content().clear(); - + content().add("Select a save slot.").padBottom(2); content().row(); - - for(int i = 0; i < Vars.saveSlots; i ++){ + + for(int i = 0; i < Vars.saveSlots; i++){ final int slot = i; - - TextButton button = new TextButton("[orange]Slot " + (i+1)); + + TextButton button = new TextButton("[orange]Slot " + (i + 1)); button.getLabelCell().top().left().growX(); button.row(); button.pad(Unit.dp.inPixels(10)); button.add("[gray]" + (!SaveIO.isSaveValid(i) ? "" : "Last Saved: " + SaveIO.getTimeString(i))).padBottom(2); - button.getLabel().setFontScale(0.75f); - button.setDisabled(!SaveIO.isSaveValid(i) ); - - button.clicked(()->{ + button.getLabel().setFontScale(Unit.dp.inPixels(0.75f)); + button.setDisabled(!SaveIO.isSaveValid(i)); + + button.clicked(() -> { if(!button.isDisabled()){ Vars.ui.showLoading(); - + Timer.schedule(new Task(){ + @Override public void run(){ - SaveIO.loadFromSlot(slot); Vars.ui.hideLoading(); hide(); + try{ + SaveIO.loadFromSlot(slot); + }catch(Exception e){ + Vars.ui.showError("[orange]Save file corrupted or invalid!"); + return; + } Vars.ui.hideMenu(); GameState.set(State.playing); } - }, 2f/60f); + }, 3f/60f); } }); - + content().add(button).size(400, 78).units(Unit.dp).pad(2); content().row(); } - + } } diff --git a/core/src/io/anuke/mindustry/ui/SaveDialog.java b/core/src/io/anuke/mindustry/ui/SaveDialog.java index 04a5c50bca..ec3df63741 100644 --- a/core/src/io/anuke/mindustry/ui/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/SaveDialog.java @@ -40,7 +40,7 @@ public class SaveDialog extends Dialog{ button.row(); button.pad(Unit.dp.inPixels(10)); button.add((!SaveIO.isSaveValid(i) ? "[gray]" : "[LIGHT_GRAY]Last Saved: " + SaveIO.getTimeString(i))).padBottom(2); - button.getLabel().setFontScale(0.75f); + button.getLabel().setFontScale(Unit.dp.inPixels(0.75f)); button.clicked(()->{ if(SaveIO.isSaveValid(slot)){ @@ -62,16 +62,21 @@ public class SaveDialog extends Dialog{ } void save(int slot){ - Vars.ui.showLoading("[yellow]Saving..."); + Vars.ui.showLoading("[orange]Saving..."); Timer.schedule(new Task(){ @Override public void run(){ - SaveIO.saveToSlot(slot); hide(); + try{ + SaveIO.saveToSlot(slot); + }catch (Exception e){ + Vars.ui.showError("[orange]Failed to save game!"); + return; + } Vars.ui.hideLoading(); } - }, 8f/60f); + }, 5f/60f); } } diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index b0aae34428..0234347db3 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -9,8 +8,6 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.ItemStack; import io.anuke.ucore.core.Draw; -import io.anuke.ucore.graphics.Caches; -import io.anuke.ucore.util.Mathf; public class Block{ private static int lastid; @@ -157,48 +154,11 @@ public class Block{ } public void drawCache(Tile tile){ - MathUtils.random.setSeed(tile.id()); - Caches.draw(vary ? (name() + MathUtils.random(1, 3)) : name(), tile.worldx(), tile.worldy()); - - for(int dx = -1; dx <= 1; dx ++){ - for(int dy = -1; dy <= 1; dy ++){ - - if(dx == 0 && dy == 0) continue; - - Tile other = World.tile(tile.x+dx, tile.y+dy); - - if(other == null) continue; - - Block floor = other.floor(); - - if(floor.id <= this.id) continue; - - TextureRegion region = Draw.hasRegion(floor.name() + "edge") ? Draw.region(floor.name() + "edge") : - Draw.region(floor.edge + "edge"); - - int sx = -dx*8+2, sy = -dy*8+2; - int x = Mathf.clamp(sx, 0, 12); - int y = Mathf.clamp(sy, 0, 12); - int w = Mathf.clamp(sx+8, 0, 12)-x, h = Mathf.clamp(sy+8, 0, 12)-y; - - float rx = Mathf.clamp(dx*8, 0, 8-w); - float ry = Mathf.clamp(dy*8, 0, 8-h); - - temp.setTexture(region.getTexture()); - temp.setRegion(region.getRegionX()+x, region.getRegionY()+y+h, w, -h); - - Caches.draw(temp, tile.worldx()-4 + rx, tile.worldy()-4 + ry, w, h); - } - } } - + public void draw(Tile tile){ - if(tile.floor() == this){ - throw new RuntimeException("Rendering non-cached tiles is disabled."); - }else{ - Draw.rect(name(), tile.worldx(), tile.worldy(), rotate ? tile.rotation * 90 : 0); - } + Draw.rect(name(), tile.worldx(), tile.worldy(), rotate ? tile.rotation * 90 : 0); } diff --git a/core/src/io/anuke/mindustry/world/blocks/Blocks.java b/core/src/io/anuke/mindustry/world/blocks/Blocks.java index e5daab6146..7f8c3e23d9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Blocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/Blocks.java @@ -4,6 +4,7 @@ import io.anuke.mindustry.resource.Item; 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.Floor; import io.anuke.mindustry.world.blocks.types.Wall; public class Blocks{ @@ -11,38 +12,39 @@ public class Blocks{ air = new Block("air"){ //no drawing here + public void drawCache(Tile tile){} public void draw(Tile tile){} }, - deepwater = new Block("deepwater"){{ + deepwater = new Floor("deepwater"){{ vary = false; solid = true; }}, - water = new Block("water"){{ + water = new Floor("water"){{ vary = false; solid = true; }}, - stone = new Block("stone"){{ + stone = new Floor("stone"){{ drops = new ItemStack(Item.stone, 1); }}, - iron = new Block("iron"){{ + iron = new Floor("iron"){{ drops = new ItemStack(Item.iron, 1); }}, - coal = new Block("coal"){{ + coal = new Floor("coal"){{ drops = new ItemStack(Item.coal, 1); }}, - titanium = new Block("titanium"){{ + titanium = new Floor("titanium"){{ drops = new ItemStack(Item.titanium, 1); }}, - dirt = new Block("dirt"), + dirt = new Floor("dirt"), - grass = new Block("grass"), + grass = new Floor("grass"), stoneblock = new Block("stoneblock"){{ solid = true; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/Conduit.java b/core/src/io/anuke/mindustry/world/blocks/types/Conduit.java index f4efa850ea..2adb9ab5ba 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/Conduit.java @@ -26,12 +26,14 @@ public class Conduit extends Block{ ConduitEntity entity = tile.entity(); Draw.rect(name() + "bottom", tile.worldx(), tile.worldy(), tile.rotation * 90); + if(entity.liquid != null && entity.liquidAmount > 0.01f){ Draw.color(entity.liquid.color); Draw.alpha(entity.liquidAmount / liquidCapacity); Draw.rect("conduitliquid", tile.worldx(), tile.worldy(), tile.rotation * 90); Draw.color(); } + Draw.rect(name() + "top", tile.worldx(), tile.worldy(), tile.rotation * 90); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/Floor.java b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java new file mode 100644 index 0000000000..68033ccc4c --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/types/Floor.java @@ -0,0 +1,57 @@ +package io.anuke.mindustry.world.blocks.types; + +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.MathUtils; + +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.World; +import io.anuke.ucore.core.Draw; +import io.anuke.ucore.graphics.Caches; +import io.anuke.ucore.util.Mathf; + +public class Floor extends Block{ + + public Floor(String name) { + super(name); + } + + @Override + public void drawCache(Tile tile){ + MathUtils.random.setSeed(tile.id()); + + Caches.draw(vary ? (name() + MathUtils.random(1, 3)) : name(), tile.worldx(), tile.worldy()); + + for(int dx = -1; dx <= 1; dx ++){ + for(int dy = -1; dy <= 1; dy ++){ + + if(dx == 0 && dy == 0) continue; + + Tile other = World.tile(tile.x+dx, tile.y+dy); + + if(other == null) continue; + + Block floor = other.floor(); + + if(floor.id <= this.id) continue; + + TextureRegion region = Draw.hasRegion(floor.name() + "edge") ? Draw.region(floor.name() + "edge") : + Draw.region(floor.edge + "edge"); + + int sx = -dx*8+2, sy = -dy*8+2; + int x = Mathf.clamp(sx, 0, 12); + int y = Mathf.clamp(sy, 0, 12); + int w = Mathf.clamp(sx+8, 0, 12)-x, h = Mathf.clamp(sy+8, 0, 12)-y; + + float rx = Mathf.clamp(dx*8, 0, 8-w); + float ry = Mathf.clamp(dy*8, 0, 8-h); + + temp.setTexture(region.getTexture()); + temp.setRegion(region.getRegionX()+x, region.getRegionY()+y+h, w, -h); + + Caches.draw(temp, tile.worldx()-4 + rx, tile.worldy()-4 + ry, w, h); + } + } + } + +} diff --git a/desktop/mindustry-saves/0.mins b/desktop/mindustry-saves/0.mins index 4c0edb10d6..da7b817352 100644 Binary files a/desktop/mindustry-saves/0.mins and b/desktop/mindustry-saves/0.mins differ diff --git a/desktop/mindustry-saves/1.mins b/desktop/mindustry-saves/1.mins index 3e02882e44..2b3704d019 100644 Binary files a/desktop/mindustry-saves/1.mins and b/desktop/mindustry-saves/1.mins differ diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 1ccc698348..21e0476c8a 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -16,7 +16,7 @@ public class DesktopLauncher { Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); config.setTitle("Mindustry"); config.setMaximized(true); - //config.useVsync(false); + config.useVsync(false); config.setWindowedMode(800, 600); config.setWindowIcon("sprites/icon.png");