package io.anuke.mindustry; import static io.anuke.mindustry.Vars.*; 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.ObjectMap; import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.Constructor; import io.anuke.mindustry.GameState.State; import io.anuke.mindustry.ai.Pathfind; import io.anuke.mindustry.entities.EnemySpawn; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.enemies.*; import io.anuke.mindustry.input.AndroidInput; import io.anuke.mindustry.input.GestureHandler; import io.anuke.mindustry.input.Input; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.*; import io.anuke.ucore.UCore; import io.anuke.ucore.core.*; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.graphics.Atlas; import io.anuke.ucore.modules.Module; import io.anuke.ucore.util.Mathf; public class Control extends Module{ int targetscale = baseCameraScale; Tutorial tutorial = new Tutorial(); boolean hiscore = false; final Array weapons = new Array<>(); final ObjectMap items = new ObjectMap<>(); Array spawns = new Array<>(); int wave = 1; float wavetime; float extrawavetime; int enemies = 0; float respawntime; public Control(){ if(Mindustry.args.contains("-debug", false)){ Vars.debug = true; } UCore.log("Total blocks loaded: " + Block.getAllBlocks().size); Gdx.input.setCatchBackKey(true); if(android){ Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler())); Inputs.addProcessor(new AndroidInput()); } Effects.setShakeFalloff(10000f); Core.atlas = new Atlas("sprites.atlas"); 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"); Sounds.setFalloff(9000f); Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3"); World.loadMaps(); KeyBinds.defaults( "up", Keys.W, "left", Keys.A, "down", Keys.S, "right", Keys.D, "rotate", Keys.R, "rotate_back", Keys.E, "menu", Gdx.app.getType() == ApplicationType.Android ? Keys.BACK : Keys.ESCAPE, "pause", Keys.SPACE ); Settings.loadAll("io.anuke.moment"); for(Map map : Map.values()){ Settings.defaults("hiscore" + map.name(), 0); } player = new Player(); spawns = Array.with( new EnemySpawn(Enemy.class){{ scaling = 3; tierscaleback = 3; }}, new EnemySpawn(FastEnemy.class){{ after = 2; scaling = 3; }}, new EnemySpawn(FlamerEnemy.class){{ after = 14; spacing = 5; scaling = 2; }}, new EnemySpawn(BlastEnemy.class){{ after = 12; spacing = 2; scaling = 3; }}, new EnemySpawn(RapidEnemy.class){{ after = 7; spacing = 3; scaling = 3; }}, new EnemySpawn(TankEnemy.class){{ after = 4; spacing = 2; scaling = 3; }}, new EnemySpawn(MortarEnemy.class){{ after = 20; spacing = 3; scaling = 5; }} ); } public void reset(){ weapons.clear(); Vars.renderer.clearTiles(); weapons.add(Weapon.blaster); player.weapon = weapons.first(); wave = 1; extrawavetime = maxwavespace; wavetime = waveSpacing(); Entities.clear(); enemies = 0; if(!android) player.add(); player.heal(); clearItems(); World.spawnpoints.clear(); respawntime = -1; hiscore = false; ui.updateItems(); ui.updateWeapons(); } public void play(){ Vars.renderer.clearTiles(); player.x = World.core.worldx(); player.y = World.core.worldy() - Vars.tilesize*2 - ((int)(Gdx.graphics.getWidth() / (float)Core.cameraScale * 2) % 2 == 0 ? 0.5f : 0); Core.camera.position.set(player.x, player.y, 0); //multiplying by 2 so you start with more time in the beginning wavetime = waveSpacing()*2; GameState.set(State.playing); } public void playMap(Map map){ Vars.ui.showLoading(); Timers.run(16, ()->{ Vars.control.reset(); World.loadMap(map); Vars.control.play(); }); Timers.run(18, ()->{ Vars.ui.hideLoading(); }); } public boolean hasWeapon(Weapon weapon){ return weapons.contains(weapon, true); } public void addWeapon(Weapon weapon){ weapons.add(weapon); } public Array getWeapons(){ return weapons; } public void setWaveData(int enemies, int wave, float wavetime){ this.wave = wave; this.wavetime = wavetime; this.enemies = enemies; this.extrawavetime = maxwavespace; } void runWave(){ Sounds.play("spawn"); Pathfind.updatePath(); for(EnemySpawn spawn : spawns){ for(int lane = 0; lane < World.spawnpoints.size; lane ++){ int fl = lane; Tile tile = World.spawnpoints.get(lane); int spawnamount = spawn.evaluate(wave, lane); for(int i = 0; i < spawnamount; i ++){ int index = i; Timers.run(index*50f, ()->{ try{ Constructor c = ClassReflection.getConstructor(spawn.type, int.class); Enemy enemy = (Enemy)c.newInstance(fl); enemy.set(tile.worldx(), tile.worldy()); enemy.tier = spawn.tier(wave, fl); Effects.effect("spawn", enemy); enemy.add(); enemies ++; }catch (Exception e){ throw new RuntimeException(e); } }); } } } wave ++; int last = Settings.getInt("hiscore" + World.getMap().name()); if(wave > last){ Settings.putInt("hiscore" + World.getMap().name(), wave); Settings.save(); hiscore = true; } wavetime = waveSpacing(); extrawavetime = maxwavespace; } void printEnemies(int wave){ int total = 0; for(EnemySpawn spawn : spawns){ int spawnamount = spawn.evaluate(wave, 0); total += spawnamount; if(spawnamount > 0){ UCore.log(ClassReflection.getSimpleName(spawn.type) + " t" + spawn.tier(wave, 0) + " x" + spawnamount); } } UCore.log("Total: " + total); } public void enemyDeath(){ enemies --; } public void coreDestroyed(){ Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); Sounds.play("corexplode"); Tile core = World.core; for(int i = 0; i < 16; i ++){ Timers.run(i*2, ()->{ Effects.effect("explosion", core.worldx()+Mathf.range(40), core.worldy()+Mathf.range(40)); }); } Effects.effect("coreexplosion", core.worldx(), core.worldy()); Timers.run(60, ()->{ ui.showRestart(); }); } float waveSpacing(){ int scale = Settings.getInt("difficulty"); float out = (scale == 0 ? 2f : scale == 1f ? 1f : 0.5f); return wavespace*out; } public boolean isHighScore(){ return hiscore; } public int getEnemiesRemaining(){ return enemies; } public float getWaveCountdown(){ return wavetime; } public float getRespawnTime(){ return respawntime; } public void setRespawnTime(float respawntime){ this.respawntime = respawntime; } public int getWave(){ return wave; } public Tutorial getTutorial(){ return tutorial; } public void clearItems(){ items.clear(); items.put(Item.stone, 40); if(debug){ for(Item item : Item.values()) items.put(item, 2000000); } } public int getAmount(Item item){ return items.get(item, 0); } public void addItem(Item item, int amount){ items.put(item, items.get(item, 0)+amount); ui.updateItems(); } public boolean hasItems(ItemStack[] items){ for(ItemStack stack : items) if(!hasItem(stack)) return false; return true; } public boolean hasItem(ItemStack req){ return items.get(req.item, 0) >= req.amount; } public void removeItem(ItemStack req){ items.put(req.item, items.get(req.item, 0)-req.amount); ui.updateItems(); } public void removeItems(ItemStack... reqs){ for(ItemStack req : reqs) items.put(req.item, items.get(req.item, 0)-req.amount); ui.updateItems(); } public ObjectMap getItems(){ return items; } @Override public void init(){ Musics.shuffleAll(); Entities.initPhysics(); Entities.setCollider(tilesize, (x, y)->{ return World.solid(x, y); }); EffectCreator.create(); } @Override public void update(){ if(debug){ if(Inputs.keyUp(Keys.O)){ Timers.mark(); SaveIO.write(Gdx.files.local("mapsave.mins")); log("Save time taken: " + Timers.elapsed()); } if(Inputs.keyUp(Keys.P)){ Timers.mark(); SaveIO.load(Gdx.files.local("mapsave.mins")); log("Load time taken: " + Timers.elapsed()); Vars.renderer.clearTiles(); } if(Inputs.keyUp(Keys.C)){ for(Entity entity : Entities.all()){ if(entity instanceof Enemy){ entity.remove(); } } } if(Inputs.keyUp(Keys.Y)){ new FastEnemy(0).set(player.x, player.y).add(); } } if(!GameState.is(State.menu)){ if(Inputs.keyUp("pause") && (GameState.is(State.paused) || GameState.is(State.playing))){ GameState.set(GameState.is(State.playing) ? State.paused : State.playing); } if(Inputs.keyUp("menu")){ if(GameState.is(State.paused)){ ui.hideMenu(); GameState.set(State.playing); }else{ ui.showMenu(); GameState.set(State.paused); } } if(!GameState.is(State.paused)){ if(respawntime > 0){ respawntime -= delta(); if(respawntime <= 0){ player.set(World.core.worldx(), World.core.worldy()-Vars.tilesize*2); player.heal(); player.add(); Effects.sound("respawn"); ui.fadeRespawn(false); } } if(!tutorial.active()){ extrawavetime -= delta(); if(enemies <= 0){ wavetime -= delta(); } }else{ tutorial.update(); } if(wavetime <= 0 || (debug && Inputs.keyUp(Keys.F)) || extrawavetime <= 0){ runWave(); } Entities.update(); } if(!android){ Input.doInput(); }else{ AndroidInput.doInput(); } } } @Override public void dispose(){ World.disposeMaps(); } }