Add a music volume slider (#135)

This commit is contained in:
Stef
2025-10-07 11:47:57 +02:00
committed by GitHub
parent 58269e917a
commit 3af182b986
7 changed files with 80 additions and 6 deletions

View File

@@ -41,6 +41,9 @@ public final class OptionsPopup extends Popup {
final var fxVolumeHeader = NodeBuilder.header(AppContext.getString("effectsVolume")); final var fxVolumeHeader = NodeBuilder.header(AppContext.getString("effectsVolume"));
final var fxVolumeSeparator = NodeBuilder.separator(); final var fxVolumeSeparator = NodeBuilder.separator();
final var musicVolumeHeader = NodeBuilder.header(AppContext.getString("musicVolume"));
final var musicVolumeSeparator = 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();
@@ -51,6 +54,7 @@ public final class OptionsPopup extends Popup {
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(fxVolumeHeader, fxVolumeSlider(), fxVolumeSeparator);
optionsContainer.addNodes(musicVolumeHeader, musicVolumeSlider(), musicVolumeSeparator);
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());
@@ -115,6 +119,13 @@ public final class OptionsPopup extends Popup {
}); });
} }
private Slider musicVolumeSlider() {
return NodeBuilder.slider(100, settings.getMusicVolume(), (volume) -> {
settings.setMusicVolume(volume);
new EventFlow().addPostEvent(new AudioEvents.ChangeMusicVolume(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) -> {

View File

@@ -1,5 +1,6 @@
package org.toop.local; package org.toop.local;
import jdk.jfr.Event;
import org.toop.app.App; import org.toop.app.App;
import org.toop.framework.asset.resources.SettingsAsset; import org.toop.framework.asset.resources.SettingsAsset;
import org.toop.framework.audio.events.AudioEvents; import org.toop.framework.audio.events.AudioEvents;
@@ -23,6 +24,8 @@ public class AppSettings {
AppContext.setLocale(Locale.of(settingsData.locale)); AppContext.setLocale(Locale.of(settingsData.locale));
App.setFullscreen(settingsData.fullScreen); App.setFullscreen(settingsData.fullScreen);
new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(settingsData.volume)).asyncPostEvent(); new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(settingsData.volume)).asyncPostEvent();
new EventFlow().addPostEvent(new AudioEvents.ChangeFxVolume(settingsData.fxVolume)).asyncPostEvent();
new EventFlow().addPostEvent(new AudioEvents.ChangeMusicVolume(settingsData.musicVolume)).asyncPostEvent();
App.setStyle(settingsAsset.getTheme(), settingsAsset.getLayoutSize()); App.setStyle(settingsAsset.getTheme(), settingsAsset.getLayoutSize());
} }

View File

@@ -17,6 +17,7 @@ deny=Deny
developers=Developers developers=Developers
drawText=The game ended in a draw drawText=The game ended in a draw
effectsVolume=Effects Volume effectsVolume=Effects Volume
musicVolume=Music Volume
fullscreen=Fullscreen fullscreen=Fullscreen
gameIsText=To a game of gameIsText=To a game of
goodGameText=Good game. Well played. goodGameText=Good game. Well played.
@@ -47,7 +48,7 @@ small=Small
start=Start start=Start
theme=Theme theme=Theme
tictactoe=Tic Tac Toe tictactoe=Tic Tac Toe
volume=Volume volume=Master Volume
windowed=Windowed windowed=Windowed
yes=Yes yes=Yes

View File

@@ -20,6 +20,10 @@ public class SettingsAsset extends JsonAsset<Settings> {
return getContent().fxVolume; return getContent().fxVolume;
} }
public int getMusicVolume() {
return getContent().musicVolume;
}
public Locale getLocale() { public Locale getLocale() {
return Locale.forLanguageTag(getContent().locale); return Locale.forLanguageTag(getContent().locale);
} }
@@ -46,6 +50,11 @@ public class SettingsAsset extends JsonAsset<Settings> {
save(); save();
} }
public void setMusicVolume(int musicVolume) {
getContent().musicVolume = musicVolume;
save();
}
public void setLocale(String locale) { public void setLocale(String locale) {
getContent().locale = locale; getContent().locale = locale;
save(); save();

View File

@@ -1,5 +1,6 @@
package org.toop.framework.audio; package org.toop.framework.audio;
import com.sun.scenario.Settings;
import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaPlayer;
import org.toop.framework.audio.events.AudioEvents; import org.toop.framework.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
@@ -12,6 +13,7 @@ public class AudioVolumeManager {
private double volume = 1.0; private double volume = 1.0;
private double fxVolume = 1.0; private double fxVolume = 1.0;
private double musicVolume = 1.0;
public AudioVolumeManager(SoundManager soundManager){ public AudioVolumeManager(SoundManager soundManager){
this.sM = soundManager; this.sM = soundManager;
@@ -19,12 +21,15 @@ public class AudioVolumeManager {
new EventFlow() new EventFlow()
.listen(this::handleVolumeChange) .listen(this::handleVolumeChange)
.listen(this::handleFxVolumeChange) .listen(this::handleFxVolumeChange)
.listen(this::handleMusicVolumeChange)
.listen(this::handleGetCurrentVolume) .listen(this::handleGetCurrentVolume)
.listen(this::handleGetCurrentFxVolume); .listen(this::handleGetCurrentFxVolume)
.listen(this::handleGetCurrentMusicVolume);
} }
public void updateMusicVolume(MediaPlayer mediaPlayer){ public void updateMusicVolume(MediaPlayer mediaPlayer){
mediaPlayer.setVolume(this.volume); mediaPlayer.setVolume(this.musicVolume * this.volume);
} }
public void updateSoundEffectVolume(Clip clip){ public void updateSoundEffectVolume(Clip clip){
@@ -32,7 +37,7 @@ public class AudioVolumeManager {
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(fxVolume, 0.0001)) * 20.0); // convert linear to dB float dB = (float) (Math.log10(Math.max(this.fxVolume * this.volume, 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);
} }
@@ -55,6 +60,18 @@ public class AudioVolumeManager {
for (MediaPlayer mediaPlayer : sM.getActiveMusic()) { for (MediaPlayer mediaPlayer : sM.getActiveMusic()) {
this.updateMusicVolume(mediaPlayer); this.updateMusicVolume(mediaPlayer);
} }
for (Clip clip : sM.getActiveSoundEffects().values()){
updateSoundEffectVolume(clip);
}
}
private void handleMusicVolumeChange(AudioEvents.ChangeMusicVolume event){
this.musicVolume = limitVolume(event.newVolume() / 100);
System.out.println(this.musicVolume);
System.out.println(this.volume);
for (MediaPlayer mediaPlayer : sM.getActiveMusic()){
this.updateMusicVolume(mediaPlayer);
}
} }
private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) {
@@ -66,4 +83,9 @@ public class AudioVolumeManager {
new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId())) new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId()))
.asyncPostEvent(); .asyncPostEvent();
} }
private void handleGetCurrentMusicVolume(AudioEvents.GetCurrentMusicVolume event){
new EventFlow().addPostEvent(new AudioEvents.GetCurrentMusicVolumeResponse(musicVolume * 100, event.snowflakeId()))
.asyncPostEvent();
}
} }

View File

@@ -16,6 +16,8 @@ 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 ChangeFxVolume(double newVolume) implements EventWithoutSnowflake {}
public record ChangeMusicVolume(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() {
@@ -51,6 +53,18 @@ public class AudioEvents extends EventsBase {
} }
} }
public record GetCurrentMusicVolume(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 { public record GetCurrentFxVolumeResponse(double currentVolume, long snowflakeId) implements EventWithSnowflake {
@Override @Override
public Map<String, Object> result() { public Map<String, Object> result() {
@@ -63,5 +77,18 @@ public class AudioEvents extends EventsBase {
} }
} }
public record ClickButton() implements EventWithoutSnowflake {} public record GetCurrentMusicVolumeResponse(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 {}
} }

View File

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