-
Notifications
You must be signed in to change notification settings - Fork 0
Adjust the sound volume while playing #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
/codehelper hello |
private static SoundController instance; | ||
private MediaPlayer inGameSound; | ||
private BorderPane root; | ||
private static double volume = 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Consider initializing the inGameSound
field in the constructor rather than having it as null initially. This would prevent potential null pointer exceptions if methods like stopInGameSound()
are called before playInGameSound()
.
{ | ||
inGameSound.stop(); | ||
} | ||
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Consider adding a check for null before accessing the resource to prevent potential NullPointerException
if the resource is not found:
if (getClass().getResource(musicResource) == null) {
System.err.println("Resource not found: " + musicResource);
return;
}
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | ||
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | ||
if(sfxVolume == 0.00) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best Practice: Consider using a logger instead of System.out.println()
for better control over logging output.
private BorderPane root; | ||
private static double volume = 1.0; | ||
private static double prevVolume = 1.0; | ||
private static double sfxVolume = 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: The prevVolume
and prevSfxVolume
fields are static but could be instance variables since they're specific to each instance of SoundController
. Since this is a singleton, it might not cause issues, but it's better practice to make them instance variables.
sfxPlayer.play(); | ||
} | ||
public double adjustInGameSFX(Slider sfxVolumeSlider, Label sfxVolumeLabel, Image sfxMute, Image sfxAudioOn, ImageView sfxImageViewPlaying) { | ||
sfxVolumeSlider.setValue(sfxVolume); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Consider adding a null check for the sfxImageViewPlaying
parameter before accessing it to prevent potential NullPointerException
.
sfxPlayer.play(); | ||
} | ||
public double adjustInGameSFX(Slider sfxVolumeSlider, Label sfxVolumeLabel, Image sfxMute, Image sfxAudioOn, ImageView sfxImageViewPlaying) { | ||
sfxVolumeSlider.setValue(sfxVolume); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Design Improvement: The adjustInGameSFX
and adjustVolume
methods are quite long and do multiple things. Consider breaking them down into smaller, more focused methods for better maintainability.
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { | ||
Platform.runLater(() -> { | ||
|
||
volume = newValue.doubleValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Consider adding a null check for the inGameSound
before setting its volume to prevent potential NullPointerException
.
import javafx.scene.media.MediaPlayer; | ||
|
||
public class SoundController { | ||
private static SoundController instance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Consider adding JavaDoc to the SoundController
class and its public methods to better document their purpose and usage.
@@ -20,7 +22,7 @@ public class DinosaurController { | |||
private Entity score; | |||
private Entity life; | |||
private int lives = 3; | |||
|
|||
private MediaPlayer inGameSound; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: The inGameSound
field is now declared in both DinosaurController
and SoundController
. Since SoundController
manages the sound, consider removing the duplicate field from DinosaurController
.
public Image getViewImage() { | ||
return viewImage; | ||
} | ||
public void playSoundEffect(String soundResource) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Consider adding proper error handling when playing sound effects. If the sound file is missing, the current implementation might throw an exception.
public PauseMenu() { | ||
super(MenuType.GAME_MENU); | ||
DinosaurApp.initLanguages(); | ||
|
||
DinosaurApp.initLanguages(); | ||
|
||
PauseButton btnBack = new PauseButton(getLocalizationService().getLocalizedString("Pause.1"),() -> fireResume()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Style: The comment //need2ComeBack
seems like a TODO item. Consider using a proper TODO comment format like // TODO: [description]
or removing it if no longer needed.
//These are for tracking how many times the pauseMenu has been opened. Helps in getting the mute/unmute image from SoundController | ||
//For first time, this helps loading the unmuted icon and if count increases more than 1, it changes the icon depending on the controller | ||
//At this point of time, I really don't have other proper method, It works so why not, But if you know any other solution please let me know and contribute | ||
private int count = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Design Concern: The comment about tracking how many times the pause menu has been opened suggests a workaround solution. Consider refactoring this approach to a more robust design that doesn't rely on counting menu opens.
|
||
ControlButton btnControls = new ControlButton(getLocalizationService().getLocalizedString("Pause.3")); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource Management: Consider using try-with-resources for handling input streams to ensure they are properly closed after use.
|
||
//These are for tracking how many times the pauseMenu has been opened. Helps in getting the mute/unmute image from SoundController | ||
//For first time, this helps loading the unmuted icon and if count increases more than 1, it changes the icon depending on the controller | ||
//At this point of time, I really don't have other proper method, It works so why not, But if you know any other solution please let me know and contribute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: The count
and sfxCount
variables are used to track menu opens, but this approach seems fragile. Consider using a more direct approach to check the current state from SoundController
instead.
public static final String SHOOT_SOUND = "shoot.wav"; | ||
* SOUNDS | ||
*/ | ||
public static final String ENEMYSHOOT_SOUND = "/assets/sounds/enemyShoot.wav"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency: The sound path constants in GameConstants
have been updated to include the /assets
prefix, which is good for consistency, but ensure all code that uses these constants has been updated accordingly.
/refacto-test |
Refacto is reviewing this PR. Please wait for the review comments to be posted. |
/refacto-test |
PR already reviewed at the latest commit: 4befef9. |
/refacto-test |
Refacto is reviewing this PR. Please wait for the review comments to be posted. |
/refacto-test |
Refacto is reviewing this PR. Please wait for the review comments to be posted. |
Code Review: Sound Controller Implementation👍 Well Done
📌 Files Processed
📝 Additional Comments
|
// Use the controlled volume | ||
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | ||
MediaPlayer sfxPlayer = new MediaPlayer(media); | ||
sfxPlayer.setVolume(sfxVolume); | ||
sfxPlayer.play(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resource Leak Risk in Sound Effects
MediaPlayer instances are created without disposal, causing resource leaks. Each sound effect creates a new MediaPlayer that's never released, potentially exhausting system resources during gameplay.
// Use the controlled volume | |
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | |
MediaPlayer sfxPlayer = new MediaPlayer(media); | |
sfxPlayer.setVolume(sfxVolume); | |
sfxPlayer.play(); | |
} | |
public void playSoundEffect(String soundResource) { | |
// Use the controlled volume | |
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | |
MediaPlayer sfxPlayer = new MediaPlayer(media); | |
sfxPlayer.setVolume(sfxVolume); | |
sfxPlayer.setOnEndOfMedia(() -> { | |
sfxPlayer.dispose(); | |
}); | |
sfxPlayer.play(); | |
} |
Standards
- ISO-IEC-25010-Reliability-Maturity
- SRE-Resource-Management
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | ||
inGameSound = new MediaPlayer(media); | ||
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | ||
inGameSound.setVolume(volume); | ||
inGameSound.play(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Error Handling for Media Loading
No exception handling for resource loading failures. If audio file is missing or corrupted, NullPointerException will occur, potentially crashing the application.
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | |
inGameSound = new MediaPlayer(media); | |
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | |
inGameSound.setVolume(volume); | |
inGameSound.play(); | |
try { | |
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | |
inGameSound = new MediaPlayer(media); | |
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | |
inGameSound.setVolume(volume); | |
inGameSound.play(); | |
} catch (Exception e) { | |
System.err.println("Failed to load or play sound: " + musicResource); | |
e.printStackTrace(); | |
} |
Standards
- ISO-IEC-25010-Reliability-Fault-Tolerance
- SRE-Error-Handling
Platform.runLater(() -> { | ||
|
||
volume = newValue.doubleValue(); | ||
inGameSound.setVolume(volume); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential NullPointerException Risk
The adjustVolume method accesses inGameSound without null check. If called before playInGameSound initializes inGameSound, this will cause NullPointerException, breaking volume adjustment functionality.
inGameSound.setVolume(volume); | |
volume = newValue.doubleValue(); | |
if (inGameSound != null) { | |
inGameSound.setVolume(volume); | |
} | |
volumeLabel.setText(String.format("%.0f%%", volume * 100)); |
Standards
- Logic-Verification-Null-Safety
- Algorithm-Correctness-Defensive-Programming
Platform.runLater(() -> { | ||
sfxVolume = newValue.doubleValue(); | ||
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | ||
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | ||
if(sfxVolume == 0.00) | ||
{ | ||
sfxImageViewPlaying.setImage(sfxMute); | ||
viewSfxImage = sfxMute; | ||
} | ||
else | ||
{ | ||
sfxImageViewPlaying.setImage(sfxAudioOn); | ||
viewSfxImage = sfxAudioOn; | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI Thread Blocking
Using Platform.runLater inside a listener that's already on the JavaFX thread creates unnecessary thread scheduling overhead. This pattern can cause UI stuttering under high frequency slider changes.
Platform.runLater(() -> { | |
sfxVolume = newValue.doubleValue(); | |
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | |
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | |
if(sfxVolume == 0.00) | |
{ | |
sfxImageViewPlaying.setImage(sfxMute); | |
viewSfxImage = sfxMute; | |
} | |
else | |
{ | |
sfxImageViewPlaying.setImage(sfxAudioOn); | |
viewSfxImage = sfxAudioOn; | |
} | |
}); | |
sfxVolume = newValue.doubleValue(); | |
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | |
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | |
if(sfxVolume == 0.00) { | |
sfxImageViewPlaying.setImage(sfxMute); | |
viewSfxImage = sfxMute; | |
} else { | |
sfxImageViewPlaying.setImage(sfxAudioOn); | |
viewSfxImage = sfxAudioOn; | |
} |
Standards
- ISO-IEC-25010-Performance-Time-Behaviour
- JavaFX-Thread-Model-Best-Practices
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | ||
inGameSound = new MediaPlayer(media); | ||
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | ||
inGameSound.setVolume(volume); | ||
inGameSound.play(); | ||
} | ||
|
||
public void stopInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.stop(); | ||
} | ||
} | ||
|
||
public void muteInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.setMute(true); | ||
} | ||
} | ||
|
||
public void unmuteInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.setMute(false); | ||
} | ||
} | ||
|
||
public boolean isMuted() { | ||
return inGameSound != null && inGameSound.isMute(); | ||
} | ||
public double getVolume() { | ||
return volume; | ||
} | ||
public double getSfxVolume() { | ||
return sfxVolume; | ||
} | ||
public Image getViewSfxImage() { | ||
return viewSfxImage; | ||
} | ||
public Image getViewImage() { | ||
return viewImage; | ||
} | ||
public void playSoundEffect(String soundResource) { | ||
// Use the controlled volume | ||
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null Resource Check
Missing null check before calling toExternalForm() on resource. If resource not found, NullPointerException occurs. Attacker could exploit by manipulating resource paths.
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | |
inGameSound = new MediaPlayer(media); | |
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | |
inGameSound.setVolume(volume); | |
inGameSound.play(); | |
} | |
public void stopInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.stop(); | |
} | |
} | |
public void muteInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.setMute(true); | |
} | |
} | |
public void unmuteInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.setMute(false); | |
} | |
} | |
public boolean isMuted() { | |
return inGameSound != null && inGameSound.isMute(); | |
} | |
public double getVolume() { | |
return volume; | |
} | |
public double getSfxVolume() { | |
return sfxVolume; | |
} | |
public Image getViewSfxImage() { | |
return viewSfxImage; | |
} | |
public Image getViewImage() { | |
return viewImage; | |
} | |
public void playSoundEffect(String soundResource) { | |
// Use the controlled volume | |
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | |
java.net.URL resourceUrl = getClass().getResource(musicResource); | |
if (resourceUrl == null) { | |
System.err.println("Resource not found: " + musicResource); | |
return; | |
} | |
Media media = new Media(resourceUrl.toExternalForm()); |
Standards
- CWE-476
- OWASP-A04
public static SoundController getInstance() { | ||
if (instance == null) { | ||
instance = new SoundController(); | ||
} | ||
return instance; | ||
} | ||
|
||
public void playInGameSound(String musicResource, double volumeValue) { | ||
if(inGameSound != null) | ||
{ | ||
inGameSound.stop(); | ||
} | ||
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | ||
inGameSound = new MediaPlayer(media); | ||
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | ||
inGameSound.setVolume(volume); | ||
inGameSound.play(); | ||
} | ||
|
||
public void stopInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.stop(); | ||
} | ||
} | ||
|
||
public void muteInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.setMute(true); | ||
} | ||
} | ||
|
||
public void unmuteInGameSound() { | ||
if (inGameSound != null) { | ||
inGameSound.setMute(false); | ||
} | ||
} | ||
|
||
public boolean isMuted() { | ||
return inGameSound != null && inGameSound.isMute(); | ||
} | ||
public double getVolume() { | ||
return volume; | ||
} | ||
public double getSfxVolume() { | ||
return sfxVolume; | ||
} | ||
public Image getViewSfxImage() { | ||
return viewSfxImage; | ||
} | ||
public Image getViewImage() { | ||
return viewImage; | ||
} | ||
public void playSoundEffect(String soundResource) { | ||
// Use the controlled volume | ||
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | ||
MediaPlayer sfxPlayer = new MediaPlayer(media); | ||
sfxPlayer.setVolume(sfxVolume); | ||
sfxPlayer.play(); | ||
} | ||
public double adjustInGameSFX(Slider sfxVolumeSlider, Label sfxVolumeLabel, Image sfxMute, Image sfxAudioOn, ImageView sfxImageViewPlaying) { | ||
sfxVolumeSlider.setValue(sfxVolume); | ||
sfxVolumeSlider.valueProperty().addListener(new ChangeListener<Number>() { | ||
@Override | ||
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { | ||
Platform.runLater(() -> { | ||
sfxVolume = newValue.doubleValue(); | ||
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | ||
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | ||
if(sfxVolume == 0.00) | ||
{ | ||
sfxImageViewPlaying.setImage(sfxMute); | ||
viewSfxImage = sfxMute; | ||
} | ||
else | ||
{ | ||
sfxImageViewPlaying.setImage(sfxAudioOn); | ||
viewSfxImage = sfxAudioOn; | ||
} | ||
}); | ||
} | ||
|
||
}); | ||
|
||
sfxImageViewPlaying.setOnMouseClicked(mouseEvent -> { | ||
if (sfxVolume == 0.00){ | ||
sfxImageViewPlaying.setImage(sfxAudioOn); | ||
sfxVolume = prevSfxVolume; | ||
sfxVolumeSlider.setValue(sfxVolume); | ||
viewSfxImage = sfxAudioOn; | ||
} else { | ||
sfxImageViewPlaying.setImage(sfxMute); | ||
prevSfxVolume = sfxVolume; | ||
sfxVolume = 0.00; | ||
sfxVolumeSlider.setValue(sfxVolume); | ||
viewSfxImage = sfxMute; | ||
} | ||
}); | ||
return sfxVolume; | ||
} | ||
public double adjustVolume(Slider volumeSlider, Label volumeLabel, Image mute, Image audioOn, ImageView imageViewPlaying) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
God Class Issue
SoundController violates SRP by handling sound playback, UI interaction, and volume control. This creates tight coupling between UI and audio logic, making changes difficult and testing nearly impossible.
public class SoundController { | |
private static SoundController instance; | |
private MediaPlayer inGameSound; | |
private BorderPane root; | |
private static double volume = 1.0; | |
private static double prevVolume = 1.0; | |
private static double sfxVolume = 1.0; | |
private static double prevSfxVolume = 1.0; | |
private static Image viewImage; | |
private static Image viewSfxImage; | |
private SoundController() {} | |
public static SoundController getInstance() { | |
if (instance == null) { | |
instance = new SoundController(); | |
} | |
return instance; | |
} | |
public void playInGameSound(String musicResource, double volumeValue) { | |
if(inGameSound != null) | |
{ | |
inGameSound.stop(); | |
} | |
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | |
inGameSound = new MediaPlayer(media); | |
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | |
inGameSound.setVolume(volume); | |
inGameSound.play(); | |
} | |
public void stopInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.stop(); | |
} | |
} | |
public void muteInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.setMute(true); | |
} | |
} | |
public void unmuteInGameSound() { | |
if (inGameSound != null) { | |
inGameSound.setMute(false); | |
} | |
} | |
public boolean isMuted() { | |
return inGameSound != null && inGameSound.isMute(); | |
} | |
public double getVolume() { | |
return volume; | |
} | |
public double getSfxVolume() { | |
return sfxVolume; | |
} | |
public Image getViewSfxImage() { | |
return viewSfxImage; | |
} | |
public Image getViewImage() { | |
return viewImage; | |
} | |
public void playSoundEffect(String soundResource) { | |
// Use the controlled volume | |
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | |
MediaPlayer sfxPlayer = new MediaPlayer(media); | |
sfxPlayer.setVolume(sfxVolume); | |
sfxPlayer.play(); | |
} | |
public double adjustInGameSFX(Slider sfxVolumeSlider, Label sfxVolumeLabel, Image sfxMute, Image sfxAudioOn, ImageView sfxImageViewPlaying) { | |
sfxVolumeSlider.setValue(sfxVolume); | |
sfxVolumeSlider.valueProperty().addListener(new ChangeListener<Number>() { | |
@Override | |
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { | |
Platform.runLater(() -> { | |
sfxVolume = newValue.doubleValue(); | |
sfxVolumeLabel.setText(String.format("%.0f%%", sfxVolume * 100)); | |
System.out.println("VFX Volume label updated to: " + sfxVolumeLabel.getText()); | |
if(sfxVolume == 0.00) | |
{ | |
sfxImageViewPlaying.setImage(sfxMute); | |
viewSfxImage = sfxMute; | |
} | |
else | |
{ | |
sfxImageViewPlaying.setImage(sfxAudioOn); | |
viewSfxImage = sfxAudioOn; | |
} | |
}); | |
} | |
}); | |
sfxImageViewPlaying.setOnMouseClicked(mouseEvent -> { | |
if (sfxVolume == 0.00){ | |
sfxImageViewPlaying.setImage(sfxAudioOn); | |
sfxVolume = prevSfxVolume; | |
sfxVolumeSlider.setValue(sfxVolume); | |
viewSfxImage = sfxAudioOn; | |
} else { | |
sfxImageViewPlaying.setImage(sfxMute); | |
prevSfxVolume = sfxVolume; | |
sfxVolume = 0.00; | |
sfxVolumeSlider.setValue(sfxVolume); | |
viewSfxImage = sfxMute; | |
} | |
}); | |
return sfxVolume; | |
} | |
public double adjustVolume(Slider volumeSlider, Label volumeLabel, Image mute, Image audioOn, ImageView imageViewPlaying) { | |
// SoundController.java - Core audio functionality | |
public class SoundController { | |
private static SoundController instance; | |
private MediaPlayer inGameSound; | |
private static double volume = 1.0; | |
private static double sfxVolume = 1.0; | |
private SoundController() {} | |
public static SoundController getInstance() { | |
if (instance == null) { | |
instance = new SoundController(); | |
} | |
return instance; | |
} | |
public void playInGameSound(String musicResource, double volumeValue) { | |
if(inGameSound != null) { | |
inGameSound.stop(); | |
} | |
Media media = new Media(getClass().getResource(musicResource).toExternalForm()); | |
inGameSound = new MediaPlayer(media); | |
inGameSound.setCycleCount(MediaPlayer.INDEFINITE); | |
inGameSound.setVolume(volume); | |
inGameSound.play(); | |
} | |
public void playSoundEffect(String soundResource) { | |
Media media = new Media(getClass().getResource(soundResource).toExternalForm()); | |
MediaPlayer sfxPlayer = new MediaPlayer(media); | |
sfxPlayer.setVolume(sfxVolume); | |
sfxPlayer.play(); | |
} | |
// Volume getters and setters | |
public double getVolume() { return volume; } | |
public void setVolume(double value) { volume = value; if(inGameSound != null) inGameSound.setVolume(volume); } | |
public double getSfxVolume() { return sfxVolume; } | |
public void setSfxVolume(double value) { sfxVolume = value; } | |
} |
Standards
- SOLID-SRP
- Clean-Code-Class-Organization
- Refactoring-Extract-Class
👉 Checklist
✍ Description of the Pull Request
🔗 Issue link