diff --git a/TODO.md b/TODO.md index c80c593414..d58b54452f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,15 +1,5 @@ _Keep in mind that this is just a basic outline of planned features, and will be constantly changing!_ -### 3.0 Release -- [DONE] New tutorial with the power blocks -- [DONE] New SFX for specific blocks, especially turrets -- [DONE] Block drawing layers. Refactor/remove `Block#drawOver()`, add `Layer` enum. Should fix 'glitchy' lasers and conveyor clipping -- [DONE] Balance nuclear reactor, improve effectiveness as they are currently underpowered -- [DONE] Make generation frame independent -- [DONE/MOVED] Investigate issue #5 (enemies stuck in blocks) - looks like it's caused by map loading lag, needs to be fixed with a slightly different physics system -- [DONE] Faster mech movement, possibly with a "boost" key -- [DONE] Balance enemy difficulty - ### 3.x Planned - New save system: toggleable autosave, named slots, less clunky save UI - Teleporter UI changes, more colors (?) @@ -21,7 +11,7 @@ _Keep in mind that this is just a basic outline of planned features, and will be - More indicators for when the core is damaged and/or under attack - Fix bugs with junction not accepting blocks(low FPS) - Fix bugs with tunnel merging and/or removing items (low FPS) - +- Investigate #6 ### 4.0 Planned - Multiplayer framework, possibly implementation diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 8150f67ba9..8739a0eb36 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="31" + android:versionName="3.04" > diff --git a/build.gradle b/build.gradle index 2ad182dd72..e1039633e4 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ project(":core") { apply plugin: "java" dependencies { - compile 'com.github.Anuken:ucore:dfceb01' + compile 'com.github.Anuken:ucore:a1a3bd9' compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-ai:1.8.1" } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 1a90a853e5..b11e1fe3c8 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -7,7 +7,6 @@ import java.util.Arrays; import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.reflect.ClassReflection; @@ -20,8 +19,8 @@ import io.anuke.mindustry.entities.enemies.BlastEnemy; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.HealerEnemy; import io.anuke.mindustry.input.AndroidInput; -import io.anuke.mindustry.input.GestureHandler; import io.anuke.mindustry.input.Input; +import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Weapon; @@ -61,6 +60,7 @@ public class Control extends Module{ boolean shouldUpdateItems = false; float respawntime; + InputHandler input; public Control(){ if(Mindustry.args.contains("-debug", false)) @@ -81,10 +81,13 @@ public class Control extends Module{ Gdx.input.setCatchBackKey(true); if(android){ - Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler())); - Inputs.addProcessor(new AndroidInput()); + input = new AndroidInput(); + }else{ + input = new Input(); } + Inputs.addProcessor(input); + Effects.setShakeFalloff(10000f); Core.atlas = new Atlas("sprites.atlas"); @@ -190,6 +193,10 @@ public class Control extends Module{ this.core = tile; } + public InputHandler getInput(){ + return input; + } + public void addSpawnPoint(Tile tile){ SpawnPoint point = new SpawnPoint(); point.start = tile; @@ -518,11 +525,7 @@ public class Control extends Module{ Profiler.end("entityUpdate"); } - if(!android){ - Input.doInput(); - }else{ - AndroidInput.doInput(); - } + input.update(); } } diff --git a/core/src/io/anuke/mindustry/core/Network.java b/core/src/io/anuke/mindustry/core/Network.java new file mode 100644 index 0000000000..8b0de963ea --- /dev/null +++ b/core/src/io/anuke/mindustry/core/Network.java @@ -0,0 +1,7 @@ +package io.anuke.mindustry.core; + +import io.anuke.ucore.modules.Module; + +public class Network extends Module{ + //TODO implementation +} diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index c18ae0f841..c43b4dbcf5 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -4,10 +4,8 @@ import static io.anuke.mindustry.Vars.*; import static io.anuke.ucore.core.Core.camera; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Input.Buttons; import com.badlogic.gdx.graphics.*; import com.badlogic.gdx.graphics.profiling.GLProfiler; -import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.FloatArray; @@ -17,8 +15,6 @@ import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.effect.Shaders; import io.anuke.mindustry.entities.enemies.Enemy; -import io.anuke.mindustry.input.AndroidInput; -import io.anuke.mindustry.input.Input; import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.SpawnPoint; @@ -35,7 +31,6 @@ import io.anuke.ucore.graphics.CacheBatch; import io.anuke.ucore.graphics.Surface; 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.*; public class Renderer extends RendererModule{ @@ -88,9 +83,7 @@ public class Renderer extends RendererModule{ if(Mathf.in(camera.zoom, targetzoom, 0.005f)){ camera.zoom = 1f; Graphics.setCameraScale(targetscale); - - AndroidInput.mousex = Gdx.graphics.getWidth() / 2; - AndroidInput.mousey = Gdx.graphics.getHeight() / 2; + control.input.resetCursor(); } } @@ -99,6 +92,7 @@ public class Renderer extends RendererModule{ }else{ boolean smoothcam = Settings.getBool("smoothcam"); + //TODO identify the source of this bug if(control.core == null){ ui.showGameError(); GameState.set(State.menu); @@ -160,15 +154,13 @@ public class Renderer extends RendererModule{ camera.position.set(lastx - deltax, lasty - deltay, 0); - //if(Vars.debug){ - record(); - //} + record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't } } @Override public void draw(){ - //clera shield surface + //clears shield surface Graphics.surface(shieldSurface); Graphics.surface(); @@ -205,9 +197,7 @@ public class Renderer extends RendererModule{ @Override public void resize(int width, int height){ super.resize(width, height); - - AndroidInput.mousex = Gdx.graphics.getWidth() / 2; - AndroidInput.mousey = Gdx.graphics.getHeight() / 2; + control.input.resetCursor(); camera.position.set(player.x, player.y, 0); } @@ -481,86 +471,35 @@ public class Renderer extends RendererModule{ } Draw.reset(); } + + int tilex = control.input.getBlockX(); + int tiley = control.input.getBlockY(); //draw placement box - if(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && (!ui.hasMouse() || android) && AndroidInput.mode == PlaceMode.cursor){ - float x = 0; - float y = 0; + if(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && (!ui.hasMouse() || android)){ - int tilex = 0; - int tiley = 0; - - if(android){ - Vector2 vec = Graphics.world(AndroidInput.mousex, AndroidInput.mousey); - tilex = Mathf.scl2(vec.x, tilesize); - tiley = Mathf.scl2(vec.y, tilesize); - }else{ - tilex = Input.tilex(); - tiley = Input.tiley(); - } - - x = tilex * tilesize; - y = tiley * tilesize; - - boolean valid = world.validPlace(tilex, tiley, player.recipe.result) && (android || Input.cursorNear()); - - Vector2 offset = player.recipe.result.getPlaceOffset(); - - float si = MathUtils.sin(Timers.time() / 6f) + 1; - - Draw.color(valid ? Color.PURPLE : Color.SCARLET); - Draw.thickness(2f); - Draw.linecrect(x + offset.x, y + offset.y, tilesize * player.recipe.result.width + si, tilesize * player.recipe.result.height + si); - - player.recipe.result.drawPlace(tilex, tiley, player.rotation, valid); - Draw.thickness(2f); - - if(player.recipe.result.rotate){ - Draw.color("orange"); - Tmp.v1.set(7, 0).rotate(player.rotation * 90); - Draw.line(x, y, x + Tmp.v1.x, y + Tmp.v1.y); - } + player.placeMode.draw(tilex, tiley, control.input.getBlockEndX(), control.input.getBlockEndY()); //TODO proper end points Draw.thickness(1f); - Draw.color("scarlet"); + Draw.color(Color.SCARLET); for(SpawnPoint spawn : control.getSpawnPoints()){ Draw.dashCircle(spawn.start.worldx(), spawn.start.worldy(), enemyspawnspace); } - if(valid) - Cursors.setHand(); - else - Cursors.restoreCursor(); - Draw.reset(); } - - //block breaking - if(Inputs.buttonDown(Buttons.RIGHT) && world.validBreak(Input.tilex(), Input.tiley())){ - Tile tile = world.tile(Input.tilex(), Input.tiley()); - if(tile.isLinked()) - tile = tile.getLinked(); - Vector2 offset = tile.block().getPlaceOffset(); - - Draw.color(Color.YELLOW, Color.SCARLET, player.breaktime / tile.getBreakTime()); - Draw.linecrect(tile.worldx() + offset.x, tile.worldy() + offset.y, tile.block().width * Vars.tilesize, tile.block().height * Vars.tilesize); - Draw.reset(); - }else if(android && player.breaktime > 0){ //android block breaking + + if(Vars.android){ Vector2 vec = Graphics.world(Gdx.input.getX(0), Gdx.input.getY(0)); - - if(world.validBreak(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize))){ - Tile tile = world.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize)); - - float fract = player.breaktime / tile.getBreakTime(); - Draw.color(Color.YELLOW, Color.SCARLET, fract); - Draw.circle(tile.worldx(), tile.worldy(), 4 + (1f - fract) * 26); - Draw.reset(); - } + tilex = Mathf.scl2(vec.x, tilesize); + tiley = Mathf.scl2(vec.y, tilesize); } + + PlaceMode.breaker.draw(tilex, tiley, 0, 0); //draw selected block health if(player.recipe == null && !ui.hasMouse()){ - Tile tile = world.tile(Input.tilex(), Input.tiley()); + Tile tile = world.tile(tilex, tiley); if(tile != null && tile.block() != Blocks.air){ Tile target = tile; diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java index caa9df31c6..b87106b50f 100644 --- a/core/src/io/anuke/mindustry/entities/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/BulletType.java @@ -36,7 +36,7 @@ public abstract class BulletType extends BaseBulletType{ }, iron = new BulletType(1.7f, 2){ public void draw(Bullet b){ - Draw.color("gray"); + Draw.color(Color.GRAY); Draw.rect("bullet", b.x, b.y, b.angle()); Draw.reset(); } @@ -241,7 +241,7 @@ public abstract class BulletType extends BaseBulletType{ }, smallSlow = new BulletType(1.2f, 2){ public void draw(Bullet b){ - Draw.color("orange"); + Draw.color(Color.ORANGE); Draw.rect("shot", b.x, b.y, b.angle() - 45); Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 0a862bdff6..75829d569f 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -3,30 +3,30 @@ package io.anuke.mindustry.entities; import static io.anuke.mindustry.Vars.*; import com.badlogic.gdx.Input.Buttons; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.effect.Fx; -import io.anuke.mindustry.input.Input; +import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.resource.Mech; import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.resource.Weapon; import io.anuke.ucore.core.*; import io.anuke.ucore.entities.DestructibleEntity; import io.anuke.ucore.util.Angles; +import io.anuke.ucore.util.Mathf; public class Player extends DestructibleEntity{ + private static final float speed = 1.1f; + private static final float dashSpeed = 1.8f; + public Weapon weapon; public Mech mech = Mech.standard; - public float breaktime = 0; + public float angle; - public Recipe recipe; - public int rotation; - - private Vector2 direction = new Vector2(); - private float speed = 1.1f; - private float dashSpeed = 1.8f; + public transient float breaktime = 0; + public transient Recipe recipe; + public transient int rotation; + public transient PlaceMode placeMode = PlaceMode.touch; public Player(){ hitbox.setSize(5); @@ -59,9 +59,9 @@ public class Player extends DestructibleEntity{ if(Vars.debug && (!Vars.showPlayer || !Vars.showUI)) return; if(Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){ - Draw.rect("mech-"+mech.name(), (int)x, (int)y, direction.angle()-90); + Draw.rect("mech-"+mech.name(), (int)x, (int)y, angle-90); }else{ - Draw.rect("mech-"+mech.name(), x, y, direction.angle()-90); + Draw.rect("mech-"+mech.name(), x, y, angle-90); } } @@ -69,15 +69,7 @@ public class Player extends DestructibleEntity{ @Override public void update(){ - float speed = this.speed; - - if(Inputs.keyDown("dash")){ - speed = dashSpeed; - - if(Vars.debug){ - // speed *= 3f; - } - } + float speed = Inputs.keyDown("dash") ? Player.dashSpeed : Player.speed; if(health < maxhealth && Timers.get(this, "regen", 50)) health ++; @@ -93,7 +85,8 @@ public class Player extends DestructibleEntity{ if(Inputs.keyDown("right")) vector.x += speed; - boolean shooting = !Inputs.keyDown("dash") && Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse() && !Input.onConfigurable(); + boolean shooting = !Inputs.keyDown("dash") && Inputs.buttonDown(Buttons.LEFT) && recipe == null + && !ui.hasMouse() && !control.getInput().onConfigurable(); if(shooting && Timers.get(this, "reload", weapon.reload)){ weapon.shoot(this); @@ -101,7 +94,7 @@ public class Player extends DestructibleEntity{ } if(Inputs.keyDown("dash") && Timers.get(this, "dashfx", 3) && vector.len() > 0){ - Angles.translation(direction.angle() + 180, 3f); + Angles.translation(angle + 180, 3f); Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y()); } @@ -115,14 +108,10 @@ public class Player extends DestructibleEntity{ } if(!shooting){ - direction.add(vector); - direction.limit(speed*6); + angle = Mathf.lerpAngDelta(angle, vector.angle(), 0.13f); }else{ float angle = Angles.mouseAngle(x, y); - direction.lerp(vector.set(0, 1).setAngle(angle), 0.26f); - if(MathUtils.isEqual(angle, direction.angle(), 0.05f)){ - direction.setAngle(angle); - } + this.angle = Mathf.lerpAngDelta(this.angle, angle, 0.1f); } } } diff --git a/core/src/io/anuke/mindustry/entities/effect/Fx.java b/core/src/io/anuke/mindustry/entities/effect/Fx.java index 12fdad1c64..5bdc05b918 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fx.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fx.java @@ -455,7 +455,7 @@ public class Fx{ ind = new Effect(100, e -> { Draw.thickness(3f); - Draw.color("royal"); + Draw.color(Color.ROYAL); Draw.circle(e.x, e.y, 3); Draw.reset(); }), diff --git a/core/src/io/anuke/mindustry/input/AndroidInput.java b/core/src/io/anuke/mindustry/input/AndroidInput.java index a9093dafd6..0f66669ea4 100644 --- a/core/src/io/anuke/mindustry/input/AndroidInput.java +++ b/core/src/io/anuke/mindustry/input/AndroidInput.java @@ -4,7 +4,7 @@ import static io.anuke.mindustry.Vars.*; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.Vars; @@ -14,17 +14,26 @@ import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Configurable; import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.core.Inputs; import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.ui.layout.Unit; 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; +public class AndroidInput extends InputHandler{ + public float mousex, mousey; + public boolean brokeBlock = false; + private float lmousex, lmousey; + private float warmup; + private float warmupDelay = 20; + + public AndroidInput(){ + Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler(this))); + } + + @Override public float getCursorEndX(){ return Gdx.input.getX(0); } + @Override public float getCursorEndY(){ return Gdx.input.getY(0); } + @Override public float getCursorX(){ return mousex; } + @Override public float getCursorY(){ return mousey; } @Override public boolean keyDown(int keycode){ @@ -62,13 +71,24 @@ public class AndroidInput extends InputAdapter{ } return false; } + + @Override + public void resetCursor(){ + mousex = Gdx.graphics.getWidth()/2; + mousey = Gdx.graphics.getHeight()/2; + } + + @Override + public boolean cursorNear(){ + return true; + } - public static Tile selected(){ + public Tile selected(){ Vector2 vec = Graphics.world(mousex, mousey); return Vars.world.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize)); } - public static void breakBlock(){ + public void breakBlock(){ Tile tile = selected(); player.breaktime += Timers.delta(); @@ -79,7 +99,7 @@ public class AndroidInput extends InputAdapter{ } } - public static void place(){ + public void place(){ Vector2 vec = Graphics.world(mousex, mousey); int tilex = Mathf.scl2(vec.x, tilesize); @@ -95,7 +115,8 @@ public class AndroidInput extends InputAdapter{ } } - public static void doInput(){ + @Override + public void update(){ if(Gdx.input.isTouched(0) && Mathf.near2d(lmousex, lmousey, Gdx.input.getX(0), Gdx.input.getY(0), Unit.dp.inPixels(50)) && !ui.hasMouse()){ @@ -133,7 +154,7 @@ public class AndroidInput extends InputAdapter{ } } - public static int touches(){ + public int touches(){ int sum = 0; for(int i = 0; i < 10; i++){ if(Gdx.input.isTouched(i)) diff --git a/core/src/io/anuke/mindustry/input/GestureHandler.java b/core/src/io/anuke/mindustry/input/GestureHandler.java index 1073adecec..50117222f8 100644 --- a/core/src/io/anuke/mindustry/input/GestureHandler.java +++ b/core/src/io/anuke/mindustry/input/GestureHandler.java @@ -9,35 +9,33 @@ import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.Vars; import io.anuke.ucore.core.Core; import io.anuke.ucore.scene.ui.layout.Unit; +import io.anuke.ucore.util.Mathf; public class GestureHandler extends GestureAdapter{ + AndroidInput input; Vector2 pinch1 = new Vector2(-1, -1), pinch2 = pinch1.cpy(); Vector2 vector = new Vector2(); float initzoom = -1; boolean zoomed = false; + GestureHandler(AndroidInput input){ + this.input = input; + } + @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){ - Effects.effect("break", tile.worldx(), tile.worldy()); - Effects.shake(3f, 1f); - 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 && - Vars.control.hasItems(player.recipe.requirements) && !Vars.ui.hasMouse() && !AndroidInput.brokeBlock){ - AndroidInput.mousex = x; - AndroidInput.mousey = y; - AndroidInput.place(); + if(!ui.hasMouse() && player.recipe != null && + Vars.control.hasItems(player.recipe.requirements) && !Vars.ui.hasMouse() && !input.brokeBlock){ + + player.placeMode.tapped(Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize), Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize)); + + input.mousex = x; + input.mousey = y; return true; } return false; @@ -45,12 +43,12 @@ public class GestureHandler extends GestureAdapter{ @Override public boolean pan(float x, float y, float deltaX, float deltaY){ - if(player.recipe == null || !Vars.control.hasItems(player.recipe.requirements) || AndroidInput.mode == PlaceMode.touch){ + if(player.recipe == null || !Vars.control.hasItems(player.recipe.requirements) || !player.placeMode.lockCamera){ player.x -= deltaX*Core.camera.zoom/Core.cameraScale; player.y += deltaY*Core.camera.zoom/Core.cameraScale; - }else if(AndroidInput.mode == PlaceMode.cursor){ - AndroidInput.mousex += deltaX; - AndroidInput.mousey += deltaY; + }else if(player.placeMode.lockCamera){ + input.mousex += deltaX; + input.mousey += deltaY; } return false; diff --git a/core/src/io/anuke/mindustry/input/Input.java b/core/src/io/anuke/mindustry/input/Input.java index 95bd5d2910..3f1eb2e6ae 100644 --- a/core/src/io/anuke/mindustry/input/Input.java +++ b/core/src/io/anuke/mindustry/input/Input.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.input; import static io.anuke.mindustry.Vars.*; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Buttons; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.math.Vector2; @@ -19,11 +20,36 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.utils.Cursors; import io.anuke.ucore.util.Mathf; -public class Input{ +public class Input extends InputHandler{ + float mousex, mousey; - public static void doInput(){ - //player is dead - if(player.health <= 0) return; + @Override public float getCursorEndX(){ return Gdx.input.getX(); } + @Override public float getCursorEndY(){ return Gdx.input.getY(); } + @Override public float getCursorX(){ return mousex; } + @Override public float getCursorY(){ return mousey; } + + @Override + public boolean touchDown (int screenX, int screenY, int pointer, int button) { + if(button == Buttons.LEFT){ + mousex = screenX; + mousey = screenY; + } + return false; + } + + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + player.placeMode.tapped(getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY()); + return false; + } + + @Override + public void update(){ + if(player.isDead()) return; + + if(!Inputs.buttonDown(Buttons.LEFT)){ + mousex = Gdx.input.getX(); + mousey = Gdx.input.getY(); + } if(Inputs.scrolled() && Inputs.keyDown("zoom_hold") && !GameState.is(State.menu) && !Vars.ui.onDialog()){ Vars.renderer.scaleCamera(Inputs.scroll()); @@ -52,21 +78,7 @@ public class Input{ Tile cursor = Vars.world.tile(tilex(), tiley()); - if(Inputs.buttonUp(Buttons.LEFT) && player.recipe != null && - Vars.world.validPlace(tilex(), tiley(), player.recipe.result) && !ui.hasMouse() && cursorNear() && - Vars.control.hasItems(player.recipe.requirements)){ - - Vars.world.placeBlock(tilex(), tiley(), player.recipe.result, player.rotation, true); - - for(ItemStack stack : player.recipe.requirements){ - Vars.control.removeItem(stack); - } - - if(!Vars.control.hasItems(player.recipe.requirements)){ - Cursors.restoreCursor(); - } - - }else if(Inputs.buttonUp(Buttons.LEFT)){ + if(Inputs.buttonUp(Buttons.LEFT) && cursor != null){ Tile linked = cursor.isLinked() ? cursor.getLinked() : cursor; if(linked != null && linked.block() instanceof Configurable){ Vars.ui.showConfig(linked); @@ -98,28 +110,40 @@ public class Input{ } - public static boolean cursorNear(){ - return Vector2.dst(player.x, player.y, tilex() * tilesize, tiley() * tilesize) <= placerange; + public void tryPlaceBlock(int x, int y){ + if(player.recipe != null && + Vars.world.validPlace(x, y, player.recipe.result) && !ui.hasMouse() && cursorNear() && + Vars.control.hasItems(player.recipe.requirements)){ + + Vars.world.placeBlock(x, y, player.recipe.result, player.rotation, true); + + for(ItemStack stack : player.recipe.requirements){ + Vars.control.removeItem(stack); + } + + if(!Vars.control.hasItems(player.recipe.requirements)){ + Cursors.restoreCursor(); + } + } } - public static boolean onConfigurable(){ - Tile tile = Vars.world.tile(tilex(), tiley()); - return tile != null && (tile.block() instanceof Configurable || (tile.isLinked() && tile.getLinked().block() instanceof Configurable)); + public boolean cursorNear(){ + return Vector2.dst(player.x, player.y, tilex() * tilesize, tiley() * tilesize) <= placerange; } - public static int tilex(){ + public int tilex(){ return (player.recipe != null && player.recipe.result.isMultiblock() && player.recipe.result.width % 2 == 0) ? Mathf.scl(Graphics.mouseWorld().x, tilesize) : Mathf.scl2(Graphics.mouseWorld().x, tilesize); } - public static int tiley(){ + public int tiley(){ return (player.recipe != null && player.recipe.result.isMultiblock() && player.recipe.result.height % 2 == 0) ? Mathf.scl(Graphics.mouseWorld().y, tilesize) : Mathf.scl2(Graphics.mouseWorld().y, tilesize); } - public static int currentWeapon(){ + public int currentWeapon(){ int i = 0; for(Weapon weapon : control.getWeapons()){ if(player.weapon == weapon) diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java new file mode 100644 index 0000000000..f8b1c51c00 --- /dev/null +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -0,0 +1,53 @@ +package io.anuke.mindustry.input; + +import static io.anuke.mindustry.Vars.*; + +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.math.Vector2; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.resource.ItemStack; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.types.Configurable; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.scene.utils.Cursors; +import io.anuke.ucore.util.Mathf; + +public abstract class InputHandler extends InputAdapter{ + public abstract void update(); + public abstract float getCursorX(); + public abstract float getCursorY(); + public abstract float getCursorEndX(); + public abstract float getCursorEndY(); + public int getBlockX(){ return Mathf.scl2(Graphics.world(getCursorX(), getCursorY()).x, Vars.tilesize); } + public int getBlockY(){ return Mathf.scl2(Graphics.world(getCursorX(), getCursorY()).y, Vars.tilesize); } + public int getBlockEndX(){ return Mathf.scl2(Graphics.world(getCursorEndX(), getCursorEndY()).x, Vars.tilesize); } + public int getBlockEndY(){ return Mathf.scl2(Graphics.world(getCursorEndX(), getCursorEndY()).y, Vars.tilesize); } + public void resetCursor(){} + + public boolean onConfigurable(){ + Tile tile = Vars.world.tile(getBlockX(), getBlockY()); + return tile != null && (tile.block() instanceof Configurable || (tile.isLinked() && tile.getLinked().block() instanceof Configurable)); + } + + public boolean cursorNear(){ + return Vector2.dst(player.x, player.y, getBlockX() * tilesize, getBlockY() * tilesize) <= placerange; + } + + public void tryPlaceBlock(int x, int y){ + if(player.recipe != null && + Vars.world.validPlace(x, y, player.recipe.result) && !ui.hasMouse() && cursorNear() && + Vars.control.hasItems(player.recipe.requirements)){ + + Vars.world.placeBlock(x, y, player.recipe.result, player.rotation, true); + + for(ItemStack stack : player.recipe.requirements){ + Vars.control.removeItem(stack); + } + + if(!Vars.control.hasItems(player.recipe.requirements)){ + Cursors.restoreCursor(); + } + } + } +} diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java index b180aa3c55..798eab6705 100644 --- a/core/src/io/anuke/mindustry/input/PlaceMode.java +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -1,5 +1,144 @@ package io.anuke.mindustry.input; +import static io.anuke.mindustry.Vars.*; + +import com.badlogic.gdx.Input.Buttons; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector2; + +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Draw; +import io.anuke.ucore.core.Inputs; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.scene.utils.Cursors; +import io.anuke.ucore.util.Tmp; + public enum PlaceMode{ - cursor, touch; + cursor{ + public void draw(int tilex, int tiley, int endx, int endy){ + float x = tilex * Vars.tilesize; + float y = tiley * Vars.tilesize; + + boolean valid = world.validPlace(tilex, tiley, player.recipe.result) && (android || control.getInput().cursorNear()); + + Vector2 offset = player.recipe.result.getPlaceOffset(); + + float si = MathUtils.sin(Timers.time() / 6f) + 1; + + Draw.color(valid ? Color.PURPLE : Color.SCARLET); + Draw.thickness(2f); + Draw.linecrect(x + offset.x, y + offset.y, tilesize * player.recipe.result.width + si, tilesize * player.recipe.result.height + si); + + player.recipe.result.drawPlace(tilex, tiley, player.rotation, valid); + Draw.thickness(2f); + + if(player.recipe.result.rotate){ + Draw.color(Color.ORANGE); + Tmp.v1.set(7, 0).rotate(player.rotation * 90); + Draw.line(x, y, x + Tmp.v1.x, y + Tmp.v1.y); + } + + if(valid) + Cursors.setHand(); + else + Cursors.restoreCursor(); + } + }, + touch{ + { + lockCamera = true; + } + + public void draw(int tilex, int tiley, int endx, int endy){ + + float t = Vars.tilesize; + + float x = tilex * t, y = tiley * t, + x2 = endx * t, y2 = endy * t; + + if(x2 < x){ + float d = x; + x = x2; + x2 = d; + } + + if(y2 < y){ + float d = y; + y = y2; + y2 = d; + } + + if(x2 >= x){ + x -= t/2; + x2 += t/2; + } + + if(y2 >= y){ + y -= t/2; + y2 += t/2; + } + + if(tilex == endx && tiley == endy){ + cursor.draw(tilex, tiley, endx, endy); + }else{ + Draw.color(Color.GREEN); + Draw.linerect(x, y, x2 - x, y2 - y); + Draw.alpha(0.3f); + Draw.crect("blank", x, y, x2 - x, y2 - y); + Draw.reset(); + } + } + + public void tapped(int tilex, int tiley, int endx, int endy){ + if(endx < tilex){ + int t = endx; + endx = tilex; + tilex = t; + } + if(endy < tiley){ + int t = endy; + endy = tiley; + tiley = t; + } + + for(int x = tilex; x <= endx; x ++){ + for(int y = tiley; y <= endy; y ++){ + control.getInput().tryPlaceBlock(x, y); + } + } + + } + }, + breaker{ + public void draw(int tilex, int tiley, int endx, int endy){ + Tile tile = world.tile(tilex, tiley); + + if(tile != null && world.validBreak(tilex, tiley)){ + if(tile.isLinked()) + tile = tile.getLinked(); + Vector2 offset = tile.block().getPlaceOffset(); + float fract = player.breaktime / tile.getBreakTime(); + + if(Inputs.buttonDown(Buttons.RIGHT)){ + Draw.color(Color.YELLOW, Color.SCARLET, fract); + Draw.linecrect(tile.worldx() + offset.x, tile.worldy() + offset.y, tile.block().width * Vars.tilesize, tile.block().height * Vars.tilesize); + }else if(android && player.breaktime > 0){ + Draw.color(Color.YELLOW, Color.SCARLET, fract); + Draw.circle(tile.worldx(), tile.worldy(), 4 + (1f - fract) * 26); + } + Draw.reset(); + } + } + }; + public boolean lockCamera; + + public void draw(int tilex, int tiley, int endx, int endy){ + + } + + public void tapped(int tilex, int tiley, int endx, int endy){ + + } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 19900479a5..9b1bd0c0ca 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -6,7 +6,6 @@ import com.badlogic.gdx.utils.Align; import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.input.AndroidInput; import io.anuke.mindustry.input.PlaceMode; import io.anuke.ucore.scene.builders.imagebutton; import io.anuke.ucore.scene.builders.label; @@ -29,7 +28,7 @@ public class PlacementFragment implements Fragment{ new table("pane"){{ get().setTouchable(Touchable.enabled); - new label(()->"Placement Mode: [orange]" + AndroidInput.mode.name()).pad(4).units(Unit.dp); + new label(()->"Placement Mode: [orange]" + player.placeMode.name()).pad(4).units(Unit.dp); row(); aleft(); @@ -42,7 +41,7 @@ public class PlacementFragment implements Fragment{ for(PlaceMode mode : PlaceMode.values()){ new imagebutton("icon-" + mode.name(), "toggle", Unit.dp.inPixels(10*3), ()->{ - AndroidInput.mode = mode; + player.placeMode = mode; }){{ group.add(get()); }}; @@ -50,7 +49,7 @@ public class PlacementFragment implements Fragment{ new imagebutton("icon-cancel", Unit.dp.inPixels(14*3), ()->{ player.recipe = null; - }).visible(()->player.recipe != null && AndroidInput.mode == PlaceMode.touch); + }).visible(()->player.recipe != null && player.placeMode == PlaceMode.touch); new imagebutton("icon-rotate-arrow", Unit.dp.inPixels(14*3), ()->{ player.rotation ++; @@ -58,7 +57,7 @@ public class PlacementFragment implements Fragment{ }).update(i->{ i.getImage().setOrigin(Align.center); i.getImage().setRotation(player.rotation*90); - }).visible(()->player.recipe != null && AndroidInput.mode == PlaceMode.touch + }).visible(()->player.recipe != null && player.placeMode == PlaceMode.touch && player.recipe.result.rotate); }}.left().end(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java index 149719e5d7..6bd0a66536 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ToolFragment.java @@ -7,7 +7,6 @@ import com.badlogic.gdx.utils.Align; import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.input.AndroidInput; import io.anuke.mindustry.input.PlaceMode; import io.anuke.ucore.core.Core; import io.anuke.ucore.scene.ui.layout.Table; @@ -28,18 +27,19 @@ public class ToolFragment implements Fragment{ }); tools.addIButton("icon-check", Unit.dp.inPixels(42), ()->{ - AndroidInput.place(); + player.placeMode.tapped(control.getInput().getBlockX(), control.getInput().getBlockY(), + control.getInput().getBlockEndX(), control.getInput().getBlockEndY()); }); Core.scene.add(tools); tools.setVisible(()-> !GameState.is(State.menu) && android && player.recipe != null && control.hasItems(player.recipe.requirements) && - AndroidInput.mode == PlaceMode.cursor + player.placeMode == PlaceMode.cursor ); tools.update(()->{ - tools.setPosition(AndroidInput.mousex, Gdx.graphics.getHeight()-AndroidInput.mousey-15*Core.cameraScale, Align.top); + tools.setPosition(control.getInput().getCursorX(), Gdx.graphics.getHeight() - control.getInput().getCursorY() - 15*Core.cameraScale, Align.top); }); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java index f2c9527b79..ce0987ca1a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/PowerTurret.java @@ -42,7 +42,7 @@ public class PowerTurret extends Turret implements PowerAcceptor{ public void drawSelect(Tile tile){ Vector2 offset = getPlaceOffset(); - Draw.color("green"); + Draw.color(Color.GREEN); Draw.dashCircle(tile.worldx() + offset.x, tile.worldy() + offset.y, range); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java index 2b5333200f..854b084985 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.types.defense; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -69,7 +70,7 @@ public class RepairTurret extends PowerTurret{ @Override public void drawSelect(Tile tile){ - Draw.color("green"); + Draw.color(Color.GREEN); Draw.dashCircle(tile.worldx(), tile.worldy(), range); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java index 6b7fba046a..92ea2b8ca2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.types.distribution; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -26,14 +27,14 @@ public class PowerBooster extends Generator{ public void drawSelect(Tile tile){ super.drawSelect(tile); - Draw.color("yellow"); + Draw.color(Color.YELLOW); Draw.dashCircle(tile.worldx(), tile.worldy(), powerRange * Vars.tilesize); Draw.reset(); } @Override public void drawPlace(int x, int y, int rotation, boolean valid){ - Draw.color("purple"); + Draw.color(Color.PURPLE); Draw.thick(1f); Draw.dashCircle(x * Vars.tilesize, y * Vars.tilesize, powerRange * Vars.tilesize); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java index c6397fc292..11e7e523d4 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java @@ -57,7 +57,7 @@ public class Generator extends PowerBlock{ if(drawRangeOverlay){ int rotation = tile.getRotation(); if(hasLasers){ - Draw.color("yellow"); + Draw.color(Color.YELLOW); Draw.thick(2f); for(int i = 0; i < laserDirections; i++){ @@ -81,7 +81,7 @@ public class Generator extends PowerBlock{ @Override public void drawPlace(int x, int y, int rotation, boolean valid){ if(hasLasers){ - Draw.color("purple"); + Draw.color(Color.PURPLE); Draw.thick(2f); for(int i = 0; i < laserDirections; i++){