mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-22 12:38:05 +07:00
Random in-game music, untested
This commit is contained in:
parent
4ef60af4a8
commit
2341da995e
@ -25,7 +25,7 @@ public class Annotations{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Indicates that a method return or field cannot be null.*/
|
/** Indicates that a method return or field cannot be null.*/
|
||||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface NonNull{
|
public @interface NonNull{
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
@ -1448,7 +1448,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
size = 2;
|
size = 2;
|
||||||
range = 150f;
|
range = 150f;
|
||||||
reload = 30f;
|
reload = 38f;
|
||||||
restitution = 0.03f;
|
restitution = 0.03f;
|
||||||
ammoEjectBack = 3f;
|
ammoEjectBack = 3f;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
|
@ -358,18 +358,7 @@ public class Control implements ApplicationListener{
|
|||||||
//autosave global data if it's modified
|
//autosave global data if it's modified
|
||||||
data.checkSave();
|
data.checkSave();
|
||||||
|
|
||||||
if(state.is(State.menu)){
|
music.update();
|
||||||
if(ui.deploy.isShown()){
|
|
||||||
music.play(Musics.launch);
|
|
||||||
}else if(ui.editor.isShown()){
|
|
||||||
music.play(Musics.editor);
|
|
||||||
}else{
|
|
||||||
music.play(Musics.menu);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
//TODO game music
|
|
||||||
music.silence();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!state.is(State.menu)){
|
if(!state.is(State.menu)){
|
||||||
input.update();
|
input.update();
|
||||||
|
@ -3,44 +3,162 @@ package io.anuke.mindustry.game;
|
|||||||
import io.anuke.annotations.Annotations.*;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.audio.*;
|
import io.anuke.arc.audio.*;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.mindustry.core.GameState.*;
|
||||||
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
|
import io.anuke.mindustry.gen.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/** Controls playback of multiple music tracks.*/
|
/** Controls playback of multiple music tracks.*/
|
||||||
public class MusicControl{
|
public class MusicControl{
|
||||||
private static final float finTime = 120f, foutTime = 120f;
|
private static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.25f, musicWaveChance = 0.2f;
|
||||||
|
|
||||||
|
/** normal, ambient music, plays at any time */
|
||||||
|
public final Array<Music> ambientMusic = Array.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6);
|
||||||
|
/** darker music, used in times of conflict */
|
||||||
|
public final Array<Music> darkMusic = Array.with(Musics.game2, Musics.game5, Musics.game7);
|
||||||
|
/** all music, both dark and ambient */
|
||||||
|
public final Array<Music> allMusic = Array.withArrays(ambientMusic, darkMusic);
|
||||||
|
|
||||||
|
private Music lastRandomPlayed;
|
||||||
|
private Interval timer = new Interval();
|
||||||
private @Nullable Music current;
|
private @Nullable Music current;
|
||||||
private float fade;
|
private float fade;
|
||||||
|
private boolean silenced;
|
||||||
|
|
||||||
public void play(@Nullable Music music){
|
public MusicControl(){
|
||||||
if(current != null){
|
Events.on(WaveEvent.class, e -> Time.run(60f * 10f, () -> {
|
||||||
current.setVolume(fade * Core.settings.getInt("musicvol") / 100f);
|
if(Mathf.chance(musicWaveChance)){
|
||||||
}
|
playRandom();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
if(current == null && music != null){
|
/** Update and play the right music track.*/
|
||||||
current = music;
|
public void update(){
|
||||||
current.setLooping(true);
|
if(state.is(State.menu)){
|
||||||
current.setVolume(fade = 0f);
|
if(ui.deploy.isShown()){
|
||||||
current.play();
|
play(Musics.launch);
|
||||||
}else if(current == music && music != null){
|
}else if(ui.editor.isShown()){
|
||||||
fade = Mathf.clamp(fade + Time.delta()/finTime);
|
play(Musics.editor);
|
||||||
}else if(current != null){
|
}else{
|
||||||
fade = Mathf.clamp(fade - Time.delta()/foutTime);
|
play(Musics.menu);
|
||||||
|
}
|
||||||
|
}else if(state.rules.editor){
|
||||||
|
play(Musics.editor);
|
||||||
|
}else{
|
||||||
|
//this just fades out the last track to make way for ingame music
|
||||||
|
silence();
|
||||||
|
|
||||||
if(fade <= 0.01f){
|
//play music at intervals
|
||||||
current.stop();
|
if(timer.get(musicInterval)){
|
||||||
current = null;
|
//chance to play it per interval
|
||||||
if(music != null){
|
if(Mathf.chance(musicChance)){
|
||||||
current = music;
|
playRandom();
|
||||||
current.setVolume(fade = 0f);
|
|
||||||
current.setLooping(true);
|
|
||||||
current.play();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void silence(){
|
/** Plays a random track.*/
|
||||||
|
private void playRandom(){
|
||||||
|
if(isDark()){
|
||||||
|
playOnce(darkMusic.random(lastRandomPlayed));
|
||||||
|
}else{
|
||||||
|
playOnce(ambientMusic.random(lastRandomPlayed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether to play dark music.*/
|
||||||
|
private boolean isDark(){
|
||||||
|
if(!state.teams.get(player.getTeam()).cores.isEmpty() && state.teams.get(player.getTeam()).cores.first().entity.healthf() < 0.85f){
|
||||||
|
//core damaged -> dark
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Plays and fades in a music track. This must be called every frame.
|
||||||
|
* If something is already playing, fades out that track and fades in this new music.*/
|
||||||
|
private void play(@Nullable Music music){
|
||||||
|
//update volume of current track
|
||||||
|
if(current != null){
|
||||||
|
current.setVolume(fade * Core.settings.getInt("musicvol") / 100f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//do not update once the track has faded out completely, just stop
|
||||||
|
if(silenced){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current == null && music != null){
|
||||||
|
//begin playing in a new track
|
||||||
|
current = music;
|
||||||
|
current.setLooping(true);
|
||||||
|
current.setVolume(fade = 0f);
|
||||||
|
current.play();
|
||||||
|
silenced = false;
|
||||||
|
}else if(current == music && music != null){
|
||||||
|
//fade in the playing track
|
||||||
|
fade = Mathf.clamp(fade + Time.delta()/finTime);
|
||||||
|
}else if(current != null){
|
||||||
|
//fade out the current track
|
||||||
|
fade = Mathf.clamp(fade - Time.delta()/foutTime);
|
||||||
|
|
||||||
|
if(fade <= 0.01f){
|
||||||
|
//stop current track when it hits 0 volume
|
||||||
|
current.stop();
|
||||||
|
current = null;
|
||||||
|
silenced = true;
|
||||||
|
if(music != null){
|
||||||
|
//play newly scheduled track
|
||||||
|
current = music;
|
||||||
|
current.setVolume(fade = 0f);
|
||||||
|
current.setLooping(true);
|
||||||
|
current.play();
|
||||||
|
silenced = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Plays a music track once and only once. If something is already playing, does nothing.*/
|
||||||
|
private void playOnce(@NonNull Music music){
|
||||||
|
if(current != null) return; //do not interrupt already-playing tracks
|
||||||
|
|
||||||
|
//save last random track played to prevent duplicates
|
||||||
|
lastRandomPlayed = music;
|
||||||
|
|
||||||
|
//set fade to 1 and play it, stopping the current when it's done
|
||||||
|
fade = 1f;
|
||||||
|
current = music;
|
||||||
|
current.setVolume(1f);
|
||||||
|
current.setLooping(false);
|
||||||
|
current.setCompletionListener(m -> {
|
||||||
|
if(current == m){
|
||||||
|
current = null;
|
||||||
|
fade = 0f;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
current.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fades out the current track, unless it has already been silenced. */
|
||||||
|
private void silence(){
|
||||||
play(null);
|
play(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.function.Predicate;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.Supplier;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.scene.ui.TextButton;
|
import io.anuke.arc.input.*;
|
||||||
|
import io.anuke.arc.scene.ui.*;
|
||||||
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class LoadoutDialog extends FloatingDialog{
|
public class LoadoutDialog extends FloatingDialog{
|
||||||
private Runnable hider;
|
private Runnable hider;
|
||||||
@ -14,24 +16,58 @@ public class LoadoutDialog extends FloatingDialog{
|
|||||||
private Runnable resetter;
|
private Runnable resetter;
|
||||||
private Runnable updater;
|
private Runnable updater;
|
||||||
private Predicate<Item> filter;
|
private Predicate<Item> filter;
|
||||||
|
private Table items;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
|
||||||
public LoadoutDialog(){
|
public LoadoutDialog(){
|
||||||
super("$configure");
|
super("$configure");
|
||||||
setFillParent(false);
|
setFillParent(true);
|
||||||
addCloseButton();
|
|
||||||
|
keyDown(key -> {
|
||||||
|
if(key == KeyCode.ESCAPE || key == KeyCode.BACK){
|
||||||
|
Core.app.post(this::hide);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cont.add(items = new Table()).left();
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
hidden(() -> {
|
hidden(() -> {
|
||||||
if(hider != null){
|
if(hider != null){
|
||||||
hider.run();
|
hider.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
buttons.row();
|
|
||||||
buttons.addButton("$settings.reset", () -> {
|
cont.row();
|
||||||
|
|
||||||
|
cont.addButton("$add", () -> {
|
||||||
|
FloatingDialog dialog = new FloatingDialog("");
|
||||||
|
dialog.setFillParent(false);
|
||||||
|
for(Item item : content.items().select(item -> filter.test(item) && item.type == ItemType.material && supplier.get().find(stack -> stack.item == item) == null)){
|
||||||
|
TextButton button = dialog.cont.addButton("", "clear", () -> {
|
||||||
|
dialog.hide();
|
||||||
|
supplier.get().add(new ItemStack(item, 0));
|
||||||
|
updater.run();
|
||||||
|
setup();
|
||||||
|
}).size(300f, 36f).get();
|
||||||
|
button.clearChildren();
|
||||||
|
button.left();
|
||||||
|
button.addImage(item.icon(Item.Icon.medium)).size(8 * 3).pad(4);
|
||||||
|
button.add(item.localizedName);
|
||||||
|
dialog.cont.row();
|
||||||
|
}
|
||||||
|
dialog.show();
|
||||||
|
}).size(100f, 40).left().disabled(b -> !content.items().contains(item -> filter.test(item) && !supplier.get().contains(stack -> stack.item == item)));
|
||||||
|
|
||||||
|
cont.row();
|
||||||
|
cont.addButton("$settings.reset", () -> {
|
||||||
resetter.run();
|
resetter.run();
|
||||||
updater.run();
|
updater.run();
|
||||||
setup();
|
setup();
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f);
|
||||||
|
|
||||||
|
cont.row();
|
||||||
|
cont.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f, 64f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show(int capacity, Supplier<Array<ItemStack>> supplier, Runnable reseter, Runnable updater, Runnable hider, Predicate<Item> filter){
|
public void show(int capacity, Supplier<Array<ItemStack>> supplier, Runnable reseter, Runnable updater, Runnable hider, Predicate<Item> filter){
|
||||||
@ -45,50 +81,31 @@ public class LoadoutDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
cont.clear();
|
items.clearChildren();
|
||||||
|
items.left();
|
||||||
float bsize = 40f;
|
float bsize = 40f;
|
||||||
int step = 50;
|
int step = 50;
|
||||||
|
|
||||||
for(ItemStack stack : supplier.get()){
|
for(ItemStack stack : supplier.get()){
|
||||||
cont.addButton("x", "clear-partial", () -> {
|
items.addButton("x", "clear-partial", () -> {
|
||||||
supplier.get().remove(stack);
|
supplier.get().remove(stack);
|
||||||
updater.run();
|
updater.run();
|
||||||
setup();
|
setup();
|
||||||
}).size(bsize);
|
}).size(bsize);
|
||||||
|
|
||||||
cont.addButton("-", "clear-partial", () -> {
|
items.addButton("-", "clear-partial", () -> {
|
||||||
stack.amount = Math.max(stack.amount - step, 0);
|
stack.amount = Math.max(stack.amount - step, 0);
|
||||||
updater.run();
|
updater.run();
|
||||||
}).size(bsize);
|
}).size(bsize);
|
||||||
cont.addButton("+", "clear-partial", () -> {
|
items.addButton("+", "clear-partial", () -> {
|
||||||
stack.amount = Math.min(stack.amount + step, capacity);
|
stack.amount = Math.min(stack.amount + step, capacity);
|
||||||
updater.run();
|
updater.run();
|
||||||
}).size(bsize);
|
}).size(bsize);
|
||||||
|
|
||||||
cont.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4);
|
items.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4).padLeft(4);
|
||||||
cont.label(() -> stack.amount + "").left();
|
items.label(() -> stack.amount + "").left();
|
||||||
|
|
||||||
cont.row();
|
items.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
cont.addButton("$add", () -> {
|
|
||||||
FloatingDialog dialog = new FloatingDialog("");
|
|
||||||
dialog.setFillParent(false);
|
|
||||||
for(Item item : content.items().select(item -> filter.test(item) && item.type == ItemType.material && supplier.get().find(stack -> stack.item == item) == null)){
|
|
||||||
TextButton button = dialog.cont.addButton("", "clear", () -> {
|
|
||||||
supplier.get().add(new ItemStack(item, 0));
|
|
||||||
updater.run();
|
|
||||||
setup();
|
|
||||||
dialog.hide();
|
|
||||||
}).size(300f, 36f).get();
|
|
||||||
button.clearChildren();
|
|
||||||
button.left();
|
|
||||||
button.addImage(item.icon(Item.Icon.medium)).size(8 * 3).pad(4);
|
|
||||||
button.add(item.localizedName);
|
|
||||||
dialog.cont.row();
|
|
||||||
}
|
|
||||||
dialog.show();
|
|
||||||
}).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> filter.test(item) && !supplier.get().contains(stack -> stack.item == item)));
|
|
||||||
pack();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,12 +147,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
Array<Map> maps = world.maps.customMaps().size == 0 ? world.maps.defaultMaps() : world.maps.customMaps();
|
Array<Map> maps = world.maps.customMaps().size == 0 ? world.maps.defaultMaps() : world.maps.customMaps();
|
||||||
|
|
||||||
Map previous = world.getMap();
|
Map previous = world.getMap();
|
||||||
Map map = previous;
|
Map map = maps.random(previous);
|
||||||
if(maps.size > 1){
|
|
||||||
while(map == previous) map = maps.random();
|
|
||||||
}else if(!previous.custom && !world.maps.customMaps().isEmpty()){
|
|
||||||
map = maps.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
Call.onInfoMessage((state.rules.pvp
|
Call.onInfoMessage((state.rules.pvp
|
||||||
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
|
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
|
||||||
@ -162,9 +157,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
|
|
||||||
info("Selected next map to be {0}.", map.name());
|
info("Selected next map to be {0}.", map.name());
|
||||||
|
|
||||||
Map fmap = map;
|
play(true, () -> world.loadMap(map));
|
||||||
|
|
||||||
play(true, () -> world.loadMap(fmap));
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
netServer.kickAll(KickReason.gameover);
|
netServer.kickAll(KickReason.gameover);
|
||||||
|
Loading…
Reference in New Issue
Block a user