diff --git a/core/assets/sounds/boom.ogg b/core/assets/sounds/boom.ogg new file mode 100644 index 0000000000..d024eb74c0 Binary files /dev/null and b/core/assets/sounds/boom.ogg differ diff --git a/core/assets/sounds/buttonClick.ogg b/core/assets/sounds/buttonClick.ogg new file mode 100755 index 0000000000..fb48038764 Binary files /dev/null and b/core/assets/sounds/buttonClick.ogg differ diff --git a/core/assets/sounds/empty.ogg b/core/assets/sounds/empty.ogg new file mode 100644 index 0000000000..917d0e3611 Binary files /dev/null and b/core/assets/sounds/empty.ogg differ diff --git a/core/assets/sounds/message.ogg b/core/assets/sounds/message.ogg new file mode 100755 index 0000000000..84937baf4d Binary files /dev/null and b/core/assets/sounds/message.ogg differ diff --git a/core/assets/sounds/place.ogg b/core/assets/sounds/place.ogg index 381e3bfd5c..2fca68203c 100644 Binary files a/core/assets/sounds/place.ogg and b/core/assets/sounds/place.ogg differ diff --git a/core/assets/sounds/shootSnap.ogg b/core/assets/sounds/shootSnap.ogg new file mode 100644 index 0000000000..5b58211031 Binary files /dev/null and b/core/assets/sounds/shootSnap.ogg differ diff --git a/core/assets/sounds/unlock.ogg b/core/assets/sounds/unlock.ogg new file mode 100755 index 0000000000..04fe1efae0 Binary files /dev/null and b/core/assets/sounds/unlock.ogg differ diff --git a/core/assets/sounds/windowHide.ogg b/core/assets/sounds/windowHide.ogg new file mode 100755 index 0000000000..92fbd146e8 Binary files /dev/null and b/core/assets/sounds/windowHide.ogg differ diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index ec1fc6043a..66e95da67b 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.core; import io.anuke.arc.*; +import io.anuke.arc.Application.*; import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.input.*; @@ -175,6 +176,10 @@ public class Control implements ApplicationListener{ Events.on(ZoneConfigureCompleteEvent.class, e -> { ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave)); }); + + if(Core.app.getType() == ApplicationType.Android){ + Sounds.empty.loop(0f, 1f, 0f); + } } void createPlayer(){ diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 298272522e..22d7f667de 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -23,6 +23,7 @@ import io.anuke.arc.util.*; import io.anuke.mindustry.core.GameState.*; import io.anuke.mindustry.editor.*; import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.gen.*; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.fragments.*; @@ -88,6 +89,8 @@ public class UI implements ApplicationListener{ Core.app.post(() -> showError("Failed to access local storage.\nSettings will not be saved.")); }); + ClickListener.clicked = () -> Sounds.press.play(); + Colors.put("accent", Pal.accent); Colors.put("highlight", Pal.accent.cpy().lerp(Color.WHITE, 0.3f)); Colors.put("stat", Pal.stat); diff --git a/core/src/io/anuke/mindustry/game/MusicControl.java b/core/src/io/anuke/mindustry/game/MusicControl.java index c9e0147f5c..c2364ee8d3 100644 --- a/core/src/io/anuke/mindustry/game/MusicControl.java +++ b/core/src/io/anuke/mindustry/game/MusicControl.java @@ -14,7 +14,7 @@ import static io.anuke.mindustry.Vars.*; /** Controls playback of multiple music tracks.*/ public class MusicControl{ - private static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.25f, musicWaveChance = 0.2f; + private static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.3f, musicWaveChance = 0.24f; /** normal, ambient music, plays at any time */ public final Array ambientMusic = Array.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6); @@ -30,6 +30,7 @@ public class MusicControl{ private boolean silenced; public MusicControl(){ + //only run music 10 seconds after a wave spawns Events.on(WaveEvent.class, e -> Time.run(60f * 10f, () -> { if(Mathf.chance(musicWaveChance)){ playRandom(); @@ -40,6 +41,7 @@ public class MusicControl{ /** Update and play the right music track.*/ public void update(){ if(state.is(State.menu)){ + silenced = false; if(ui.deploy.isShown()){ play(Musics.launch); }else if(ui.editor.isShown()){ @@ -48,6 +50,7 @@ public class MusicControl{ play(Musics.menu); } }else if(state.rules.editor){ + silenced = false; play(Musics.editor); }else{ //this just fades out the last track to make way for ingame music @@ -79,17 +82,13 @@ public class MusicControl{ return true; } - if(state.enemies() > 25){ - //many enemies -> dark - return true; - } - //it may be dark based on wave if(Mathf.chance((float)(Math.log10((state.wave - 17f)/19f) + 1) / 4f)){ return true; } - return false; + //dark based on enemies + return Mathf.chance(state.enemies() / 70f); } /** Plays and fades in a music track. This must be called every frame. diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java index 99b05d1ea4..1f5dfc8679 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -56,11 +56,11 @@ public class DatabaseDialog extends FloatingDialog{ UnlockableContent unlock = (UnlockableContent)array.get(i); Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-locked", Pal.gray); - image.addListener(new HandCursorListener()); list.add(image).size(unlocked(unlock) ? 8*4 : Vars.iconsize).pad(3); ClickListener listener = new ClickListener(); image.addListener(listener); - if(!Vars.mobile){ + if(!Vars.mobile && unlocked(unlock)){ + image.addListener(new HandCursorListener()); image.update(() -> image.getColor().lerp(!listener.isOver() ? Color.LIGHT_GRAY : Color.WHITE, 0.4f * Time.delta())); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java index e8958d770f..748d0e93a6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.*; import io.anuke.arc.input.*; -import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.ui.*; import io.anuke.arc.util.*; import io.anuke.mindustry.core.GameState.*; @@ -33,7 +32,6 @@ public class FloatingDialog extends Dialog{ } Sounds.back.play(); }); - ClickListener.clicked = () -> Sounds.press.play(); shown(() -> { if(shouldPause && !state.is(State.menu)){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java index 154725ddf3..4af3810a1f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -15,6 +15,7 @@ import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.util.*; import io.anuke.mindustry.content.*; import io.anuke.mindustry.content.TechTree.*; +import io.anuke.mindustry.gen.*; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.type.*; import io.anuke.mindustry.ui.*; @@ -237,6 +238,7 @@ public class TechTreeDialog extends FloatingDialog{ treeLayout(); rebuild(); Core.scene.act(); + Sounds.unlock.play(); } void rebuild(){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java index a3d0ce2c9a..071b81d406 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -1,15 +1,16 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.scene.ui.Button; -import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; import io.anuke.mindustry.game.*; -import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.gen.*; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.type.*; -import io.anuke.mindustry.type.Zone.ZoneRequirement; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.type.Zone.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.Block.*; import static io.anuke.mindustry.Vars.*; @@ -142,6 +143,7 @@ public class ZoneInfoDialog extends FloatingDialog{ Button button = cont.addButton(zone.locked() ? "$uncover" : "$launch", () -> { if(!data.isUnlocked(zone)){ + Sounds.unlock.play(); data.unlockContent(zone); ui.deploy.setup(); setup(zone); diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index c86bb19d30..b0a82220b2 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -44,6 +44,7 @@ public class HudFragment extends Fragment{ private float lastCoreHP; private Team lastTeam; private float coreAttackOpacity = 0f; + private long lastToast; public void build(Group parent){ @@ -372,25 +373,43 @@ public class HudFragment extends Fragment{ } } - public void showToast(String text){ - Table table = new Table("button"); - table.update(() -> { - if(state.is(State.menu)){ - table.remove(); - } - }); - table.margin(12); - table.addImage("icon-check").size(iconsize).pad(3); - table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center); - table.pack(); + private void scheduleToast(Runnable run){ + long duration = (int)(3.5 * 1000); + long since = Time.timeSinceMillis(lastToast); + if(since > duration){ + lastToast = Time.millis(); + run.run(); + }else{ + Time.runTask((duration - since) / 1000f * 60f, run); + lastToast += duration; + } + } - //create container table which will align and move - Table container = Core.scene.table(); - container.top().add(table); - container.setTranslation(0, table.getPrefHeight()); - container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(4f), - //nesting actions() calls is necessary so the right prefHeight() is used - Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.remove()))); + public void showToast(String text){ + if(state.is(State.menu)) return; + + scheduleToast(() -> { + Sounds.message.play(); + + Table table = new Table("button"); + table.update(() -> { + if(state.is(State.menu)){ + table.remove(); + } + }); + table.margin(12); + table.addImage("icon-check").size(iconsize).pad(3); + table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center); + table.pack(); + + //create container table which will align and move + Table container = Core.scene.table(); + container.top().add(table); + container.setTranslation(0, table.getPrefHeight()); + container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(2.5f), + //nesting actions() calls is necessary so the right prefHeight() is used + Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.remove()))); + }); } public boolean shown(){ @@ -400,46 +419,50 @@ public class HudFragment extends Fragment{ /** Show unlock notification for a new recipe. */ public void showUnlock(UnlockableContent content){ //some content may not have icons... yet - if(content.getContentIcon() == null) return; + if(content.getContentIcon() == null || state.is(State.menu)) return; + + Sounds.message.play(); //if there's currently no unlock notification... if(lastUnlockTable == null){ - Table table = new Table("button"); - table.update(() -> { - if(state.is(State.menu)){ - table.remove(); - lastUnlockLayout = null; + scheduleToast(() -> { + Table table = new Table("button"); + table.update(() -> { + if(state.is(State.menu)){ + table.remove(); + lastUnlockLayout = null; + lastUnlockTable = null; + } + }); + table.margin(12); + + Table in = new Table(); + + //create texture stack for displaying + Image image = new Image(content.getContentIcon()); + image.setScaling(Scaling.fit); + + in.add(image).size(48f).pad(2); + + //add to table + table.add(in).padRight(8); + table.add("$unlocked"); + table.pack(); + + //create container table which will align and move + Table container = Core.scene.table(); + container.top().add(table); + container.setTranslation(0, table.getPrefHeight()); + container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(2.5f), + //nesting actions() calls is necessary so the right prefHeight() is used + Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.run(() -> { lastUnlockTable = null; - } + lastUnlockLayout = null; + }), Actions.remove()))); + + lastUnlockTable = container; + lastUnlockLayout = in; }); - table.margin(12); - - Table in = new Table(); - - //create texture stack for displaying - Image image = new Image(content.getContentIcon()); - image.setScaling(Scaling.fit); - - in.add(image).size(48f).pad(2); - - //add to table - table.add(in).padRight(8); - table.add("$unlocked"); - table.pack(); - - //create container table which will align and move - Table container = Core.scene.table(); - container.top().add(table); - container.setTranslation(0, table.getPrefHeight()); - container.actions(Actions.translateBy(0, -table.getPrefHeight(), 1f, Interpolation.fade), Actions.delay(4f), - //nesting actions() calls is necessary so the right prefHeight() is used - Actions.run(() -> container.actions(Actions.translateBy(0, table.getPrefHeight(), 1f, Interpolation.fade), Actions.run(() -> { - lastUnlockTable = null; - lastUnlockLayout = null; - }), Actions.remove()))); - - lastUnlockTable = container; - lastUnlockLayout = in; }else{ //max column size int col = 3; diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 5f42308d55..79eb2fc657 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -1,25 +1,22 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.*; -import io.anuke.arc.collection.EnumSet; +import io.anuke.arc.collection.*; import io.anuke.arc.graphics.g2d.*; -import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.content.Mechs; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.traits.SpawnerTrait; +import io.anuke.arc.math.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.EventType.*; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shaders; +import io.anuke.mindustry.gen.*; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.*; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockFlag; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.meta.*; import static io.anuke.mindustry.Vars.*;