From 9f3d7be7b4c1277b6a942e6f64f36bf5ff243ef5 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 25 Sep 2017 18:53:04 -0400 Subject: [PATCH] Major improvements to Android touch controls, many bugfixes --- build.gradle | 2 +- core/assets-raw/ui/icon-cursor.png | Bin 0 -> 186 bytes core/assets-raw/ui/icon-rotate-arrow.png | Bin 0 -> 177 bytes core/assets-raw/ui/icon-touch.png | Bin 0 -> 188 bytes core/assets/ui/uiskin.atlas | 77 ++++--- core/assets/ui/uiskin.png | Bin 12967 -> 13100 bytes core/src/io/anuke/mindustry/Control.java | 6 +- core/src/io/anuke/mindustry/EffectLoader.java | 15 ++ core/src/io/anuke/mindustry/Renderer.java | 211 +++++++++--------- core/src/io/anuke/mindustry/UI.java | 91 +++++++- core/src/io/anuke/mindustry/Vars.java | 2 +- .../mindustry/entities/enemies/Enemy.java | 2 +- .../mindustry/entities/enemies/FastEnemy.java | 2 +- .../mindustry/entities/enemies/TankEnemy.java | 18 +- .../anuke/mindustry/input/AndroidInput.java | 17 +- .../anuke/mindustry/input/GestureHandler.java | 25 ++- .../io/anuke/mindustry/input/PlaceMode.java | 5 + .../io/anuke/mindustry/resource/Weapon.java | 4 + .../src/io/anuke/mindustry/ui/LoadDialog.java | 44 ++-- .../src/io/anuke/mindustry/ui/SaveDialog.java | 13 +- core/src/io/anuke/mindustry/world/Block.java | 44 +--- .../anuke/mindustry/world/blocks/Blocks.java | 18 +- .../mindustry/world/blocks/types/Conduit.java | 2 + .../mindustry/world/blocks/types/Floor.java | 57 +++++ desktop/mindustry-saves/0.mins | Bin 1237 -> 1140 bytes desktop/mindustry-saves/1.mins | Bin 1241 -> 1357 bytes .../mindustry/desktop/DesktopLauncher.java | 2 +- 27 files changed, 425 insertions(+), 232 deletions(-) create mode 100644 core/assets-raw/ui/icon-cursor.png create mode 100644 core/assets-raw/ui/icon-rotate-arrow.png create mode 100644 core/assets-raw/ui/icon-touch.png create mode 100644 core/src/io/anuke/mindustry/input/PlaceMode.java create mode 100644 core/src/io/anuke/mindustry/world/blocks/types/Floor.java 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 0000000000000000000000000000000000000000..7f8d2c80d8f4b787d0014a68a47248a6b9c63061 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0y~yU;weXIM^5%7aBGVL(bBe{k kXDwe9Wt+!kp8K_?RZ=-&wn~LI0|Nttr>mdKI;Vst0C|l!cK`qY literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c2ea8f2703df11de463c115d5b08a0111218741f GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0y~yVBiB`4mJh`26+$Niwq15oCO|{#S9GG!XV7ZFl&wk z0|NtliKnkC`$JAiF?I2Rf)C9M3=9FDE{-7@=hsfM=3+49aCu(&-`al_Yw(dZLe>+1 zF8WfHGyVIF29?hF3d}L0{CY7=#)cc-N}lQ5c!vGRmeO56_f1OD5(zFZu~Rpf=~cV` c=M&SE%d)~O4JVZt7#J8lUHx3vIVCg!00kE{xBvhE literal 0 HcmV?d00001 diff --git a/core/assets-raw/ui/icon-touch.png b/core/assets-raw/ui/icon-touch.png new file mode 100644 index 0000000000000000000000000000000000000000..4e96232fabd075e022f3ce6c7d4324280f66fcd8 GIT binary patch literal 188 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≪*rV}sV(M^U%8 z&eK*@D5>9(@h{_hYvuY`&o6wGR6MhF;-OR)7lwct_FL{(%(4CTU*i9||6Mm@1$=6z zDkvzpFLcL9qaWjKMxYB%yHkLC?46&UxNfJT|3?5Dl27%ic8cx+N@_2eLK*CI6 z0)xUX7Y8v$h8K(srV$)>)7cna*tiKZd`V#zVQ64I`~Q=_Ka<<7&ykFF|FsK^|114} zq^El3kK~jsAAef1eE7-@@eohxSM^f@4o%Dr?Jw1*Rv$j^Gna$mm7i9Efn~1#kq=e| zlejEI7%G^udp4xUpSv=5`GUXI$1gUd-;(?Ieyz@n9?h=E)%$y|pI21a(J+ydAt6C< z;SL6eE$@xv7zDn4RbePlVJLb1&pMis;k9=OgM?w-rceI@`d>aa_}+egM%_X#Miz!G z5&<@0EIh0XhG+SznJ!d3)vK5z_hT+^@!#`1YW^LZ>&^d=$#ue0-jcu9BMwdg=Ya!4 z3>vRJ?euiC3u5U=PtrzKR zSQNGA_<=`GX{tbk?G&r=`yB=M^@t=iy>0_Y~dH^|w4Z%LJH zC(XZ?+WuhMC+7nS46{xPEC_={${J247w2u8*&WuMKV_xM&T#a7U7g70)_LH3X~U4< z`1yF=51;k&XXW*7AKLu!YWBm=-;)9Y&gIG2OBno^S1x_uAI-DcKhvj?+{w2 z{jr$if>sv8gAh=&98`7jv4X2?Mh0k=U0}n|(e&(oLA3&R{NcIF8N{D{WC?q=y5DWy zyU+G#eg5*6Dc?N$MfY-Lk5*iID*7`BJXK2BDP&%<;$0)KoGs7$og4_GDm?i>fxM2tN4y@im#o-KY2u zpIr*BbhgAridM*4vx{o^u{EqS|Jtxk_Rh9h|9NYV9iDLfbgt?Dhd);@bl=ap&8gw) xv-{6x@fDP|zt%PWztVVK!~WbqyEPd;{O>w9Klf{!=`YY`7*AI}mvv4FO#nzL%(wsm literal 12967 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 { + 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 4c0edb10d6e6b1949b6e5b32f0a387e0f743e32b..da7b8173529a0de6d776f5b78a9627dfbb42a8a4 100644 GIT binary patch literal 1140 zcmZQzU|?flV2s;!|7tD+0|TS0G4D+m4h9D2{;P85nG&p$zRgForyoVK5)cFoZEI6+j|_3=EQrAO=4JgV91LLrDq5 z5MW>sTmoY7Gcc&DfEWS{3<^u347n8`20sIXK8&HE0}>HrV9?QpGR)S382k(jBI}?G z83QOoVhfC624if4GQ@U(7=jE83Ohjzeg+1y-5>_Yc54uWpMgQn2E-6#V36AjVhAuW z2-|@ef(#61V1@t#gXKP`i0FP0Lx6#S%>l~L1Ba^s1A`G*M38|&;~-SZ$PvmAIRpxI zRS*vp@}f>4t}KWEaY4eOU=>;*rUpnH#9$C%U=VWxu>=_y1e`$(kmHVk$pIz&^-cT2r@7j!5HRXDM1DXbFhd21B1a) zs2XD!L*y99C2)s{x`DW;t^ljR^rXZws9B=!P=?M4C`0HZhyn7pCx`)Z0hl4cz#w%B zBqG4TAmasM2r@8;pN2Bzy+I5C1_r+KAO=VZ%mBsY1*nK%Ac!Hrz#sx+s9uDM$Xx<4 z1Q{5VgP{y{7(+1>BqG4Tpm-I;5M*F5z7A#RM1U9q3=9%CK@33#2HsmBh5!SDG?*dC zz`%DKBmzp0F(3v%0|Wnk5JP~0K`b81kb4MaXu%lj$siGa1_psAAcg<~15YZ5A;`cW z@f5`1XJ9Y`GXxnJq@O`W)WHlv1_qNfkca>SgK9d60m^63K@5;N86bur1A_{f!Oy^; i1!f2`Flc2$rOaM}7@!3H2F3uDEDVAS3^sWn5kUY4mtDR9 literal 1237 zcmZQzU|?lnV2qn{J2jDkfq~K0Ql!L%gMq<$`2hw728I*{Rwf3ymIf9O!3ZK4Km;?0 z0Le2jFw84sU|=X?V9=Tl5)fcuP@Vx|2r@9JfEoM@3`&wv5gjmtpMk*?#?YAslHzAz z(3OHRdQcH_7(;J8NJNl< zfqw&t0dnd_C_@;=Fx(6h5nx~t+5%$mGcfRPhcX0rfEWS{3{qeQKLdmDE|3U61B1+7 z5JP~0LBSr%P=PU2!4U%rgo98ib|)x9oVzkz{41gr=l3bGPSAxH?UN}R!Z*2(`2 z3=Bp`p^g=F12F^{7=(|37y=9oBF8|sz%3PZ191_?L!A#+gyMW*cc=k|U z!2}{07#R2&7@V~fU0v!x8W@Zi7+u(IO2K(dE`hi9yHxAtFfcF}F)%o*i*JX^F}kp+ z@W6RYE^&U$f4F15?2FfcI4F*3TauixrY>-q-FV{!@Hn(R_}>pY0Z zz~HPpJp^tFqYG=`TR0D5W-Y%d)J)BfiBLI^nQSJ}a2}IO;4@B_>M4y7GZ~e785kI{ z85nfMLEhqLU@(C(6lX(4)TE&d4H!dp4oF0Rfk6Yt(31g)@G~%&!x*~rpduFYK@33# z1|0`;&P9UxI zh`=cjLy&=i?=*-Zz`!7L7RnGk2W5!+gBT!PFoqJCA;7>O9|V;$g)xLKgG2-v7^Gng zm0+ldDOg01fkEX8NJNl~p$tPXLx6$7 z;5Jl5>JF44b{E6|NyS1LQgI*#D9-MK7y=9o3JD+vKLdmI0}w-yfk7l0%8+^tV(>FC zs6B-;bW=eL0R{%H=THVOj3NC3B*M?YUOzeBurSPWtaFfa%%0WtU(7^Id$8HO;1j5*AUU|>)LGx!-8g!V(F$OaV8)7o-fYQx15JP~0!7vQO;Adbk0gHeV#|@AO z9|MC}1c(8$Gz!GvXJC-O1!4#=FxY@aKp89+B*M?YAa)PR;J*)L$blJr3=AqsAQ3(W z2Jt5#h5!Qt=Tj&{2F&1NU{Fc}iGcF?GY~_7fq^?6%HRPr_!$_?!3@!4BK!dROk>;t 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");