finished fx audio volume

This commit is contained in:
Bas de Jong
2025-10-06 22:27:14 +02:00
parent f525fc7ffc
commit 95c4a2fc8e
18 changed files with 82 additions and 6 deletions

View File

@@ -38,6 +38,9 @@ public final class OptionsPopup extends Popup {
final var volumeHeader = NodeBuilder.header(AppContext.getString("volume")); final var volumeHeader = NodeBuilder.header(AppContext.getString("volume"));
final var volumeSeparator = NodeBuilder.separator(); final var volumeSeparator = NodeBuilder.separator();
final var fxVolumeHeader = NodeBuilder.header(AppContext.getString("fxVolume"));
final var fxVolumeSeparator = NodeBuilder.separator();
final var themeHeader = NodeBuilder.header(AppContext.getString("theme")); final var themeHeader = NodeBuilder.header(AppContext.getString("theme"));
final var themeSeparator = NodeBuilder.separator(); final var themeSeparator = NodeBuilder.separator();
@@ -47,6 +50,7 @@ public final class OptionsPopup extends Popup {
final var optionsContainer = new VerticalContainer(5); final var optionsContainer = new VerticalContainer(5);
optionsContainer.addNodes(languageHeader, languageChoiceBox(), languageSeparator); optionsContainer.addNodes(languageHeader, languageChoiceBox(), languageSeparator);
optionsContainer.addNodes(volumeHeader, volumeSlider(), volumeSeparator); optionsContainer.addNodes(volumeHeader, volumeSlider(), volumeSeparator);
optionsContainer.addNodes(fxVolumeHeader, fxVolumeSlider(), fxVolumeSeparator);
optionsContainer.addNodes(themeHeader, themeChoiceBox(), themeSeparator); optionsContainer.addNodes(themeHeader, themeChoiceBox(), themeSeparator);
optionsContainer.addNodes(layoutSizeHeader, layoutSizeChoiceBox(), layoutSizeSeparator); optionsContainer.addNodes(layoutSizeHeader, layoutSizeChoiceBox(), layoutSizeSeparator);
optionsContainer.addNodes(fullscreenToggle()); optionsContainer.addNodes(fullscreenToggle());
@@ -104,6 +108,14 @@ public final class OptionsPopup extends Popup {
}); });
} }
private Slider fxVolumeSlider() {
return NodeBuilder.slider(100, settings.getFxVolume(), (volume) -> {
settings.setFxVolume(volume);
new EventFlow().addPostEvent(new AudioEvents.ChangeFxVolume(volume.doubleValue())).asyncPostEvent();
});
}
private Label fullscreenToggle() { private Label fullscreenToggle() {
return NodeBuilder.toggle(AppContext.getString("windowed"), AppContext.getString("fullscreen"), !isWindowed, (fullscreen) -> { return NodeBuilder.toggle(AppContext.getString("windowed"), AppContext.getString("fullscreen"), !isWindowed, (fullscreen) -> {
isWindowed = !fullscreen; isWindowed = !fullscreen;

View File

@@ -28,6 +28,7 @@ serverPort=\u0645\u0646\u0641\u0630 \u0627\u0644\u062e\u0627\u062f\u0645
start=\u0627\u0628\u062f\u0623 start=\u0627\u0628\u062f\u0623
tictactoe=\u062a\u064a\u0643 \u062a\u0627\u0643 \u062a\u0648 tictactoe=\u062a\u064a\u0643 \u062a\u0627\u0643 \u062a\u0648
volume=\u0627\u0644\u0635\u0648\u062a volume=\u0627\u0644\u0635\u0648\u062a
fxVolume=Fx Volume
windowed=\u0646\u0627\u0641\u0630\u064a windowed=\u0646\u0627\u0641\u0630\u064a
yes=\u0646\u0639\u0645 yes=\u0646\u0639\u0645

View File

@@ -28,6 +28,7 @@ serverPort=Server-Port
start=Start start=Start
tictactoe=Tic Tac Toe tictactoe=Tic Tac Toe
volume=Lautst\u00e4rke volume=Lautst\u00e4rke
fxVolume=Fx Volume
windowed=Fenstermodus windowed=Fenstermodus
yes=Ja yes=Ja

View File

@@ -28,6 +28,7 @@ serverPort=Server Port
start=Start start=Start
tictactoe=Tic Tac Toe tictactoe=Tic Tac Toe
volume=Volume volume=Volume
fxVolume=Fx Volume
windowed=Windowed windowed=Windowed
yes=Yes yes=Yes

View File

@@ -28,6 +28,7 @@ serverPort=Servidor-puerto
start=Iniciar start=Iniciar
tictactoe=Tres en Raya tictactoe=Tres en Raya
volume=Volumen volume=Volumen
fxVolume=Fx Volume
windowed=Ventana windowed=Ventana
yes=S\u00ed yes=S\u00ed

View File

@@ -28,6 +28,7 @@ serverPort=Serveur-Port
start=D\u00e9marrer start=D\u00e9marrer
tictactoe=Morpion tictactoe=Morpion
volume=Volume volume=Volume
fxVolume=Fx Volume
windowed=Fen\u00eatre windowed=Fen\u00eatre
yes=Oui yes=Oui

View File

@@ -29,6 +29,7 @@ serverPort=\u0938\u0930\u094d\u0935\u0930 \u092a\u094b\u0930\u094d\u091f
start=\u092b\u093f\u0930\u0942 start=\u092b\u093f\u0930\u0942
tictactoe=\u091f\u093f\u0915 \u091f\u0948\u0915 \u091f\u094b tictactoe=\u091f\u093f\u0915 \u091f\u0948\u0915 \u091f\u094b
volume=\u0935\u0949\u0932\u094d\u092f\u0947\u092e volume=\u0935\u0949\u0932\u094d\u092f\u0947\u092e
fxVolume=Fx Volume
windowed=\u0915\u094d\u0930\u094d\u0939 \u092e\u0947\u0902 windowed=\u0915\u094d\u0930\u094d\u0939 \u092e\u0947\u0902
yes=\u0939\u093e\u0907 yes=\u0939\u093e\u0907

View File

@@ -28,6 +28,7 @@ serverPort=Porta del server
start=Inizia start=Inizia
tictactoe=Tic Tac Toe tictactoe=Tic Tac Toe
volume=Volume volume=Volume
fxVolume=Fx Volume
windowed=Finestra windowed=Finestra
yes=S\u00ec yes=S\u00ec

View File

@@ -28,6 +28,7 @@ serverPort=\u30b5\u30fc\u30d0\u30fc \u30dd\u30fc\u30c8
start=\u59cb\u307e\u308a start=\u59cb\u307e\u308a
tictactoe=\u30bf\u30a4\u30af\u30bf\u30c3\u30c8\u30c8\u30a6 tictactoe=\u30bf\u30a4\u30af\u30bf\u30c3\u30c8\u30c8\u30a6
volume=\u30dc\u30ea\u30e5\u30fc\u30e0 volume=\u30dc\u30ea\u30e5\u30fc\u30e0
fxVolume=Fx Volume
windowed=\u30a6\u30a3\u30f3\u30c9\u30a6 windowed=\u30a6\u30a3\u30f3\u30c9\u30a6
yes=\u306f\u3044 yes=\u306f\u3044

View File

@@ -28,6 +28,7 @@ serverPort=\u10e1\u10d0\u10e0\u10d7\u10d4\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d7\u
start=\u10e0\u10d0\u10d3\u10d4\u10e1 start=\u10e0\u10d0\u10d3\u10d4\u10e1
tictactoe=\u10e2\u10d8\u10d9\u10d8 \u10e2\u10d8\u10e9\u10d8 \u10e2\u10d8 tictactoe=\u10e2\u10d8\u10d9\u10d8 \u10e2\u10d8\u10e9\u10d8 \u10e2\u10d8
volume=\u10d7\u10d0\u10e7\u10d8 volume=\u10d7\u10d0\u10e7\u10d8
fxVolume=Fx Volume
windowed=\u10e1\u10d0\u10db\u10d7\u10d8 windowed=\u10e1\u10d0\u10db\u10d7\u10d8
yes=\u10d3\u10d0 yes=\u10d3\u10d0

View File

@@ -28,6 +28,7 @@ serverPort=\uc11c\ubc84 \ud3ec\ud2b8
start=\uc2dc\uc791 start=\uc2dc\uc791
tictactoe=\ud2f0\ud06c\ud0d0\ud1a0 tictactoe=\ud2f0\ud06c\ud0d0\ud1a0
volume=\ubcf4\ub7ec\uc6b4 volume=\ubcf4\ub7ec\uc6b4
fxVolume=Fx Volume
windowed=\ucc3d \ubaa8\ub4dc windowed=\ucc3d \ubaa8\ub4dc
yes=\ub124 yes=\ub124

View File

@@ -28,6 +28,7 @@ serverPort=Serverpoort
start=Start start=Start
tictactoe=Boter Kaas en Eieren tictactoe=Boter Kaas en Eieren
volume=Volume volume=Volume
fxVolume=Fx Volume
windowed=Venstermodus windowed=Venstermodus
yes=Ja yes=Ja

View File

@@ -28,6 +28,7 @@ serverPort=\u041f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430
start=\u0421\u0442\u0430\u0440\u0442 start=\u0421\u0442\u0430\u0440\u0442
tictactoe=\u041a\u0440\u0435\u0441\u0442\u0438\u043a\u0438 tictactoe=\u041a\u0440\u0435\u0441\u0442\u0438\u043a\u0438
volume=\u0413\u0440\u0430\u043c\u043c\u043e\u0444\u043e\u043d volume=\u0413\u0440\u0430\u043c\u043c\u043e\u0444\u043e\u043d
fxVolume=Fx Volume
windowed=\u041e\u043a\u043d\u043e windowed=\u041e\u043a\u043d\u043e
yes=\u0414\u0430 yes=\u0414\u0430

View File

@@ -28,6 +28,7 @@ serverPort=\u670d\u52a1\u5668 \u7aef\u53e3
start=\u5f00\u59cb start=\u5f00\u59cb
tictactoe=Tic Tac Toe tictactoe=Tic Tac Toe
volume=\u97f3\u91cf volume=\u97f3\u91cf
fxVolume=Fx Volume
windowed=\u7a97\u53e3\u6a21\u5f0f windowed=\u7a97\u53e3\u6a21\u5f0f
yes=\u662f yes=\u662f

View File

@@ -16,6 +16,10 @@ public class SettingsAsset extends JsonAsset<Settings> {
return getContent().volume; return getContent().volume;
} }
public int getFxVolume() {
return getContent().fxVolume;
}
public Locale getLocale() { public Locale getLocale() {
return Locale.forLanguageTag(getContent().locale); return Locale.forLanguageTag(getContent().locale);
} }
@@ -37,6 +41,11 @@ public class SettingsAsset extends JsonAsset<Settings> {
save(); save();
} }
public void setFxVolume(int fxVolume) {
getContent().fxVolume = fxVolume;
save();
}
public void setLocale(String locale) { public void setLocale(String locale) {
getContent().locale = locale; getContent().locale = locale;
save(); save();

View File

@@ -25,6 +25,7 @@ public class SoundManager {
private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator
private double volume = 1.0; private double volume = 1.0;
private double fxVolume = 1.0;
public SoundManager() { public SoundManager() {
// Get all Audio Resources and add them to a list. // Get all Audio Resources and add them to a list.
@@ -40,7 +41,9 @@ public class SoundManager {
.listen(this::handleStopSound) .listen(this::handleStopSound)
.listen(this::handleMusicStart) .listen(this::handleMusicStart)
.listen(this::handleVolumeChange) .listen(this::handleVolumeChange)
.listen(this::handleFxVolumeChange)
.listen(this::handleGetCurrentVolume) .listen(this::handleGetCurrentVolume)
.listen(this::handleGetCurrentFxVolume)
.listen(AudioEvents.ClickButton.class, _ -> { .listen(AudioEvents.ClickButton.class, _ -> {
try { try {
playSound("medium-button-click.wav", false); playSound("medium-button-click.wav", false);
@@ -68,13 +71,20 @@ public class SoundManager {
this.audioResources.put(audioAsset.getName(), audioAsset.getResource()); this.audioResources.put(audioAsset.getName(), audioAsset.getResource());
} }
private double limitVolume(double volume) {
if (volume > 1.0) return 1.0;
else return Math.max(volume, 0.0);
}
private void handleVolumeChange(AudioEvents.ChangeVolume event) { private void handleVolumeChange(AudioEvents.ChangeVolume event) {
double newVolume = event.newVolume() / 100; this.volume = limitVolume(event.newVolume() / 100);
if (newVolume > 1.0) this.volume = 1.0;
else this.volume = Math.max(newVolume, 0.0);
for (MediaPlayer mediaPlayer : this.activeMusic) { for (MediaPlayer mediaPlayer : this.activeMusic) {
mediaPlayer.setVolume(this.volume); mediaPlayer.setVolume(this.volume);
} }
}
private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) {
this.fxVolume = limitVolume(event.newVolume() / 100);
for (Clip clip : this.activeSoundEffects.values()){ for (Clip clip : this.activeSoundEffects.values()){
updateClipVolume(clip); updateClipVolume(clip);
} }
@@ -85,14 +95,19 @@ public class SoundManager {
FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float min = volumeControl.getMinimum(); float min = volumeControl.getMinimum();
float max = volumeControl.getMaximum(); float max = volumeControl.getMaximum();
float dB = (float) (Math.log10(Math.max(volume, 0.0001)) * 20.0); // convert linear to dB float dB = (float) (Math.log10(Math.max(fxVolume, 0.0001)) * 20.0); // convert linear to dB
dB = Math.max(min, Math.min(max, dB)); dB = Math.max(min, Math.min(max, dB));
volumeControl.setValue(dB); volumeControl.setValue(dB);
} }
} }
private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) {
new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeReponse(volume * 100, event.snowflakeId())) new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeResponse(volume * 100, event.snowflakeId()))
.asyncPostEvent();
}
private void handleGetCurrentFxVolume(AudioEvents.GetCurrentFxVolume event) {
new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId()))
.asyncPostEvent(); .asyncPostEvent();
} }

View File

@@ -15,6 +15,7 @@ public class AudioEvents extends EventsBase {
public record StartBackgroundMusic() implements EventWithoutSnowflake {} public record StartBackgroundMusic() implements EventWithoutSnowflake {}
public record ChangeVolume(double newVolume) implements EventWithoutSnowflake {} public record ChangeVolume(double newVolume) implements EventWithoutSnowflake {}
public record ChangeFxVolume(double newVolume) implements EventWithoutSnowflake {}
public record GetCurrentVolume(long snowflakeId) implements EventWithSnowflake { public record GetCurrentVolume(long snowflakeId) implements EventWithSnowflake {
@Override @Override
public Map<String, Object> result() { public Map<String, Object> result() {
@@ -26,7 +27,7 @@ public class AudioEvents extends EventsBase {
return snowflakeId; return snowflakeId;
} }
} }
public record GetCurrentVolumeReponse(double currentVolume, long snowflakeId) implements EventWithSnowflake { public record GetCurrentVolumeResponse(double currentVolume, long snowflakeId) implements EventWithSnowflake {
@Override @Override
public Map<String, Object> result() { public Map<String, Object> result() {
return Map.of(); return Map.of();
@@ -37,5 +38,30 @@ public class AudioEvents extends EventsBase {
return snowflakeId; return snowflakeId;
} }
} }
public record GetCurrentFxVolume(long snowflakeId) implements EventWithSnowflake {
@Override
public Map<String, Object> result() {
return Map.of();
}
@Override
public long eventSnowflake() {
return this.snowflakeId;
}
}
public record GetCurrentFxVolumeResponse(double currentVolume, long snowflakeId) implements EventWithSnowflake {
@Override
public Map<String, Object> result() {
return Map.of();
}
@Override
public long eventSnowflake() {
return this.snowflakeId;
}
}
public record ClickButton() implements EventWithoutSnowflake {} public record ClickButton() implements EventWithoutSnowflake {}
} }

View File

@@ -6,4 +6,5 @@ public class Settings {
public String theme = "dark"; public String theme = "dark";
public String layoutSize = "medium"; public String layoutSize = "medium";
public int volume = 15; public int volume = 15;
public int fxVolume = 20;
} }