diff --git a/TODO.md b/TODO.md index ac5c9879c2..d2b97054e6 100644 --- a/TODO.md +++ b/TODO.md @@ -2,12 +2,12 @@ _Keep in mind that this is just a basic outline of planned features, and will be ### 3.0 Release - New tutorial with the power blocks -- New SFX for specific blocks, especially turrets +- [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 -- Make generation frame independent -- Investigate issue #5 (enemies stuck in blocks) -- Faster mech movement, possibly with a "boost" key +- [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 - Balance enemy difficulty ### 3.x Planned diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 5c457088f3..6d87d0aef3 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -13,19 +13,20 @@ import android.util.DisplayMetrics; import io.anuke.mindustry.io.Formatter; import io.anuke.ucore.scene.ui.layout.Unit; -public class AndroidLauncher extends AndroidApplication { - +public class AndroidLauncher extends AndroidApplication{ + boolean doubleScaleTablets = false; + @SuppressLint("SimpleDateFormat") @Override - protected void onCreate (Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); config.useImmersiveMode = true; - + Mindustry.formatter = new Formatter(){ @SuppressLint("SimpleDateFormat") SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm"); - + @Override public String format(Date date){ return format.format(date); @@ -36,23 +37,25 @@ public class AndroidLauncher extends AndroidApplication { return NumberFormat.getIntegerInstance().format(number); } }; - - DisplayMetrics metrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(metrics); - float yInches= metrics.heightPixels/metrics.ydpi; - float xInches= metrics.widthPixels/metrics.xdpi; - double diagonalInches = Math.sqrt(xInches*xInches + yInches*yInches); - if (diagonalInches>=6.5){ - // 6.5inch device or bigger - Unit.dp.multiplier = 2f; - }else{ - // smaller device - Unit.dp.multiplier = 1f; + if(doubleScaleTablets){ + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + + float yInches = metrics.heightPixels / metrics.ydpi; + float xInches = metrics.widthPixels / metrics.xdpi; + double diagonalInches = Math.sqrt(xInches * xInches + yInches * yInches); + if(diagonalInches >= 6.5){ + // 6.5inch device or bigger + Unit.dp.multiplier = 2f; + }else{ + // smaller device + Unit.dp.multiplier = 1f; + } } - + //Mindustry.args.add("-debug"); - + initialize(new Mindustry(), config); } } diff --git a/core/assets/sounds/bang.wav b/core/assets/sounds/bang.wav new file mode 100644 index 0000000000..a88d7f5fb2 Binary files /dev/null and b/core/assets/sounds/bang.wav differ diff --git a/core/assets/sounds/bang2.wav b/core/assets/sounds/bang2.wav new file mode 100644 index 0000000000..821a4de9b0 Binary files /dev/null and b/core/assets/sounds/bang2.wav differ diff --git a/core/assets/sounds/bigshot.wav b/core/assets/sounds/bigshot.wav new file mode 100644 index 0000000000..4b92e37086 Binary files /dev/null and b/core/assets/sounds/bigshot.wav differ diff --git a/core/assets/sounds/blast.wav b/core/assets/sounds/blast.wav new file mode 100644 index 0000000000..d0d4856cdc Binary files /dev/null and b/core/assets/sounds/blast.wav differ diff --git a/core/assets/sounds/laser.wav b/core/assets/sounds/laser.wav new file mode 100644 index 0000000000..4165915464 Binary files /dev/null and b/core/assets/sounds/laser.wav differ diff --git a/core/assets/sounds/lasershot.wav b/core/assets/sounds/lasershot.wav new file mode 100644 index 0000000000..2e8d49514f Binary files /dev/null and b/core/assets/sounds/lasershot.wav differ diff --git a/core/assets/sounds/ping.wav b/core/assets/sounds/ping.wav new file mode 100644 index 0000000000..60cd945a8f Binary files /dev/null and b/core/assets/sounds/ping.wav differ diff --git a/core/assets/sounds/railgun.wav b/core/assets/sounds/railgun.wav new file mode 100644 index 0000000000..eb8f85f2b4 Binary files /dev/null and b/core/assets/sounds/railgun.wav differ diff --git a/core/assets/sounds/tesla.wav b/core/assets/sounds/tesla.wav new file mode 100644 index 0000000000..19316e1152 Binary files /dev/null and b/core/assets/sounds/tesla.wav differ diff --git a/core/assets/sounds/waveend.wav b/core/assets/sounds/waveend.wav new file mode 100644 index 0000000000..78cf77e41e Binary files /dev/null and b/core/assets/sounds/waveend.wav differ diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index ec2f87178c..86769e34ae 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -22,8 +22,10 @@ public class Vars{ public static final float respawnduration = 60*4; //time between waves in frames (on normal mode) public static final float wavespace = 50*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; + //waves can last no longer than 5 minutes, otherwise the next one spawns + public static final float maxwavespace = 60*60*5; + //advance time the pathfinding starts at + public static final float aheadPathfinding = 60*20; //how far away from spawn points the player can't place blocks public static final float enemyspawnspace = 65; //scale of the font @@ -43,7 +45,7 @@ public class Vars{ //whether to draw chunk borders public static boolean debugChunks = false; //whether turrets have infinite ammo (only with debug) - public static boolean infiniteAmmo = false; + public static boolean infiniteAmmo = true; //whether to show paths of enemies public static boolean showPaths = false; //if false, player is always hidden diff --git a/core/src/io/anuke/mindustry/ai/Pathfind.java b/core/src/io/anuke/mindustry/ai/Pathfind.java index 76d27d05ec..8940d60625 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfind.java +++ b/core/src/io/anuke/mindustry/ai/Pathfind.java @@ -109,6 +109,15 @@ public class Pathfind{ } } + public boolean finishedUpdating(){ + for(SpawnPoint point : Vars.control.getSpawnPoints()){ + if(point.pathTiles == null){ + return false; + } + } + return true; + } + public void updatePath(){ for(SpawnPoint point : Vars.control.getSpawnPoints()){ point.finder = new IndexedAStarPathFinder(graph); diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 0660e32610..22c46924ea 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -50,6 +50,7 @@ public class Control extends Module{ Array spawns = new Array<>(); int wave = 1; + int lastUpdated = -1; float wavetime; float extrawavetime; int enemies = 0; @@ -90,7 +91,8 @@ public class Control extends Module{ Sounds.load("shoot.wav", "place.wav", "explosion.wav", "enemyshoot.wav", "corexplode.wav", "break.wav", "spawn.wav", "flame.wav", "die.wav", - "respawn.wav", "purchase.wav", "flame2.wav"); + "respawn.wav", "purchase.wav", "flame2.wav", "bigshot.wav", "laser.wav", "lasershot.wav", + "ping.wav", "tesla.wav", "waveend.wav", "railgun.wav", "blast.wav", "bang2.wav"); Sounds.setFalloff(9000f); @@ -103,7 +105,8 @@ public class Control extends Module{ "right", Keys.D, "zoom_hold", Keys.CONTROL_LEFT, "menu", Gdx.app.getType() == ApplicationType.Android ? Keys.BACK : Keys.ESCAPE, - "pause", Keys.SPACE + "pause", Keys.SPACE, + "dash", Keys.SHIFT_LEFT ); for(int i = 0; i < Vars.saveSlots; i ++){ @@ -129,6 +132,7 @@ public class Control extends Module{ weapons.add(Weapon.blaster); player.weapon = weapons.first(); + lastUpdated = -1; wave = 1; extrawavetime = maxwavespace; wavetime = waveSpacing(); @@ -232,7 +236,10 @@ public class Control extends Module{ public void runWave(){ Sounds.play("spawn"); - world.pathfinder().updatePath(); + if(lastUpdated < wave + 1){ + world.pathfinder().updatePath(); + lastUpdated = wave + 1; + } for(EnemySpawn spawn : spawns){ for(int lane = 0; lane < spawnpoints.size; lane ++){ @@ -471,6 +478,15 @@ public class Control extends Module{ if(enemies <= 0){ wavetime -= delta(); + + if(Vars.debug && Inputs.keyDown(Keys.I)){ + wavetime -= delta() * 10f; + } + + if(lastUpdated < wave + 1 && wavetime < Vars.aheadPathfinding){ //start updatingbeforehand + world.pathfinder().updatePath(); + lastUpdated = wave + 1; + } } } diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index d508abdf0e..b0371e17a4 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -280,8 +280,8 @@ public class Renderer extends RendererModule{ Graphics.end(); - int crangex = Math.round(camera.viewportWidth * camera.zoom / (chunksize * tilesize)); - int crangey = Math.round(camera.viewportHeight * camera.zoom / (chunksize * tilesize)); + int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1; + int crangey = (int)(camera.viewportHeight * camera.zoom / (chunksize * tilesize))+1; drawCache(0, crangex, crangey); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 3421334dbf..fb393c8680 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -3,7 +3,6 @@ package io.anuke.mindustry.entities; import static io.anuke.mindustry.Vars.*; import com.badlogic.gdx.Input.Buttons; -import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; @@ -26,7 +25,8 @@ public class Player extends DestructibleEntity{ public int rotation; private Vector2 direction = new Vector2(); - private float speed = 1f; + private float speed = 1.1f; + private float dashSpeed = 1.8f; public Player(){ hitbox.setSize(5); @@ -71,8 +71,13 @@ public class Player extends DestructibleEntity{ float speed = this.speed; - if(Vars.debug && Inputs.keyDown(Keys.SHIFT_LEFT)) - speed *= 3f; + if(Inputs.keyDown("dash")){ + speed = dashSpeed; + + if(Vars.debug){ + // speed *= 3f; + } + } if(health < maxhealth && Timers.get(this, "regen", 50)) health ++; @@ -88,13 +93,18 @@ public class Player extends DestructibleEntity{ if(Inputs.keyDown("right")) vector.x += speed; - boolean shooting = Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse() && !Input.onConfigurable(); + boolean shooting = !Inputs.keyDown("dash") && Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse() && !Input.onConfigurable(); if(shooting && Timers.get(this, "reload", weapon.reload)){ weapon.shoot(this); Sounds.play(weapon.shootsound); } + if(Inputs.keyDown("dash") && Timers.get(this, "dashfx", 3) && vector.len() > 0){ + Angles.translation(direction.angle() + 180, 3f); + Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y()); + } + vector.limit(speed); if(!Vars.noclip){ diff --git a/core/src/io/anuke/mindustry/entities/effect/Fx.java b/core/src/io/anuke/mindustry/entities/effect/Fx.java index 9dfefbbbb7..12fdad1c64 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fx.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fx.java @@ -438,6 +438,14 @@ public class Fx{ Draw.reset(); }), + dashsmoke = new Effect(30, e -> { + Draw.color(Color.CORAL, Color.GRAY, e.ifract()); + //Draw.alpha(e.fract()); + float size = e.fract()*4f; + Draw.rect("circle", e.x, e.y, size, size); + Draw.reset(); + }), + spawn = new Effect(23, e -> { Draw.thickness(2f); Draw.color(Color.DARK_GRAY, Color.SCARLET, e.ifract()); diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 4252601223..820f874e09 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -203,7 +203,7 @@ public class Enemy extends DestructibleEntity{ public void onDeath(){ Effects.effect(Fx.explosion, this); Effects.shake(3f, 4f, this); - Effects.sound("explosion", this); + Effects.sound("bang2", this); remove(); dead = true; } diff --git a/core/src/io/anuke/mindustry/entities/enemies/HealerEnemy.java b/core/src/io/anuke/mindustry/entities/enemies/HealerEnemy.java index 210a32ea53..4dead7d896 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/HealerEnemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/HealerEnemy.java @@ -83,7 +83,7 @@ public class HealerEnemy extends Enemy{ void explode(){ Bullet b = new Bullet(BulletType.blast, this, x, y, 0).add(); - b.damage = BulletType.blast.damage + (tier-1) * 40; + b.damage = BulletType.blast.damage + (tier-1) * 30; damage(999); } diff --git a/core/src/io/anuke/mindustry/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index 60c54bc669..c4086ffe2d 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -69,6 +69,10 @@ public enum Weapon{ }, railgun(40, BulletType.sniper, "Shoots one long-range bullet.", stack(Item.steel, 60), stack(Item.iron, 60)){ + { + shootsound = "railgun"; + } + @Override public void shoot(Player p){ float ang = mouseAngle(p); @@ -79,6 +83,10 @@ public enum Weapon{ }, mortar(100, BulletType.shell, "Shoots a slow, but damaging shell.", stack(Item.titanium, 40), stack(Item.steel, 60)){ + { + shootsound = "bigshot"; + } + @Override public void shoot(Player p){ float ang = mouseAngle(p); diff --git a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java index c0ad67eabf..fb40289ecb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java @@ -99,6 +99,7 @@ public class WeaponBlocks{ sniperturret = new Turret("sniperturret"){ { + shootsound = "railgun"; formalName = "railgun turret"; range = 120; reload = 50f; @@ -113,6 +114,7 @@ public class WeaponBlocks{ mortarturret = new Turret("mortarturret"){ { + shootsound = "bigshot"; rotatespeed = 0.1f; formalName = "flak turret"; range = 120; @@ -131,6 +133,7 @@ public class WeaponBlocks{ laserturret = new LaserTurret("laserturret"){ { + shootsound = "laser"; beamColor = Color.SKY; formalName = "laser turret"; range = 60; @@ -145,6 +148,7 @@ public class WeaponBlocks{ teslaturret = new PowerTurret("waveturret"){ { + shootsound = "tesla"; formalName = "tesla turret"; range = 70; reload = 15f; @@ -166,6 +170,7 @@ public class WeaponBlocks{ plasmaturret = new Turret("plasmaturret"){ { + shootsound = "flame2"; inaccuracy = 7f; formalName = "plasma turret"; range = 60f; @@ -181,6 +186,7 @@ public class WeaponBlocks{ chainturret = new Turret("chainturret"){ { + shootsound = "bigshot"; inaccuracy = 8f; formalName = "chain turret"; range = 80f; @@ -219,6 +225,7 @@ public class WeaponBlocks{ titanturret = new Turret("titancannon"){ { + shootsound = "blast"; formalName = "titan cannon"; range = 120f; reload = 23f; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java index 90efbee78e..ae91403ddd 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java @@ -25,6 +25,7 @@ public class LaserTurret extends PowerTurret{ super(name); shootsound = null; layer2 = Layer.laser; + soundReload = 20; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index e9def863c7..2d066a4153 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -33,6 +33,7 @@ public class Turret extends Block{ protected final int timerTarget = timers++; protected final int timerReload = timers++; + protected final int timerSound = timers++; protected float range = 50f; protected float reload = 10f; @@ -48,6 +49,7 @@ public class Turret extends Block{ protected float shootCone = 5f; protected Effect shootEffect = null; protected float shootShake = 0f; + protected int soundReload = 0; public Turret(String name) { super(name); @@ -161,7 +163,7 @@ public class Turret extends Block{ float reload = Vars.multiplier*this.reload; if(Angles.angleDist(entity.rotation, targetRot) < shootCone && entity.timer.get(timerReload, reload)){ - if(shootsound != null) Effects.sound(shootsound, entity); + if(shootsound != null && entity.timer.get(timerSound, soundReload)) Effects.sound(shootsound, entity); shoot(tile); consumeAmmo(tile); entity.ammo --; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java index 34127bf75c..c9d0b22d71 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/ItemPowerGenerator.java @@ -72,8 +72,8 @@ public class ItemPowerGenerator extends Generator{ public void update(Tile tile){ PowerEntity entity = tile.entity(); - float maxPower = Math.min(powerCapacity - entity.power, powerOutput); - float mfract = maxPower/powerOutput; + float maxPower = Math.min(powerCapacity - entity.power, powerOutput * Timers.delta()); + float mfract = maxPower/(powerOutput * Timers.delta()); if(entity.time > 0f){ entity.time -= 1f/itemDuration*mfract; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java index caaec77ae4..5b8a4b6534 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java @@ -65,9 +65,8 @@ public class LiquidPowerGenerator extends Generator implements LiquidAcceptor{ public void update(Tile tile){ LiquidPowerEntity entity = tile.entity(); - //TODO don't generate when full of energy if(entity.liquidAmount > 0){ - float used = Math.min(entity.liquidAmount, maxLiquidGenerate); + float used = Math.min(entity.liquidAmount, maxLiquidGenerate * Timers.delta()); used = Math.min(used, (powerCapacity - entity.power)/powerPerLiquid); entity.liquidAmount -= used; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java index 486767ca85..2ae2f53b9a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java @@ -54,7 +54,8 @@ public class NuclearReactor extends LiquidItemPowerGenerator{ if(fuel > 0){ entity.heat += fullness * heating; - entity.power += powerMultiplier * fullness; + entity.power += powerMultiplier * fullness * Timers.delta(); + entity.power = Mathf.clamp(entity.power); if(entity.timer.get(timerFuel, fuelUseTime)){ entity.removeItem(generateItem, 1); }