Skip to content

Commit

Permalink
Merge pull request #117 from einaskoi/per/settings
Browse files Browse the repository at this point in the history
Per/settings
  • Loading branch information
einaskoi authored May 15, 2026
2 parents 5786dee + f3f9520 commit 3ad0a9e
Show file tree
Hide file tree
Showing 52 changed files with 2,278 additions and 1,375 deletions.
11 changes: 11 additions & 0 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Audio/Audio.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package edu.ntnu.idi.idatt2003.gruppe42.Audio;

/**
* Represents a Audio enum.
*/
public enum Audio {

// Sound effects
Expand All @@ -19,10 +22,18 @@ public enum Audio {
this.isSFX = isSFX;
}

/**
* Returns the path.
*
* @return the value
*/
public String getPath() {
return path;
}

/**
* Issfx method.
*/
public boolean isSFX() {
return isSFX;
}
Expand Down
125 changes: 108 additions & 17 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Audio/AudioManager.java
Original file line number Diff line number Diff line change
@@ -1,65 +1,156 @@
package edu.ntnu.idi.idatt2003.gruppe42.Audio;

import javax.sound.sampled.*;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;

/**
* Represents a AudioManager class.
*/
public final class AudioManager {

public class AudioManager {
private static final AudioManager INSTANCE = new AudioManager();

private static final AudioManager instance = new AudioManager();
private final Map<Audio, byte[]> sfxCache = new EnumMap<>(Audio.class);
private MediaPlayer bgPlayer;

private final DoubleProperty masterVolume = new SimpleDoubleProperty(0.8);
private final DoubleProperty sfxVolume = new SimpleDoubleProperty(0.8);

private AudioManager() {
for (Audio audio : Audio.values()) {
if (audio.isSFX()) {
try (var stream = getClass().getResourceAsStream(audio.getPath())) {
sfxCache.put(audio, stream.readAllBytes());
if (stream != null) {
sfxCache.put(audio, stream.readAllBytes());
}
} catch (IOException e) {
e.printStackTrace();
System.err.println("[Audio] Failed to cache " + audio + ": " + e.getMessage());
}
}
}

// Keep background music volume in sync with master × 0.5 (bg is quieter)
masterVolume.addListener((obs, ov, nv) -> {
if (bgPlayer != null) {
bgPlayer.setVolume(nv.doubleValue() * 0.5);
}
});
}

public static AudioManager getInstance() { return instance; }
public static AudioManager get() { return INSTANCE; }


public void playSFX(Audio audio) {
/**
* Playsfx method.
*/
public void playSFX(final Audio audio) {
byte[] data = sfxCache.get(audio);
if (data == null) return;

double volume = masterVolume.get() * sfxVolume.get();

new Thread(() -> {
try {
var stream = AudioSystem.getAudioInputStream(
new java.io.ByteArrayInputStream(data));
Clip clip = AudioSystem.getClip();
var bais = new java.io.ByteArrayInputStream(data);
var stream = AudioSystem.getAudioInputStream(bais);
Clip clip = AudioSystem.getClip();
clip.open(stream);

// Apply volume via MASTER_GAIN
if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
FloatControl gain = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float db = volumeToDb(volume);
gain.setValue(Math.max(gain.getMinimum(), Math.min(gain.getMaximum(), db)));
}

clip.addLineListener(e -> {
if (e.getType() == LineEvent.Type.STOP) clip.close();
});
clip.start();

} catch (Exception e) {
e.printStackTrace();
System.err.println("[Audio] SFX playback failed: " + e.getMessage());
}
}).start();
}, "sfx-thread").start();
}

public void playBgMusic(Audio audio) {

/**
* Playbgmusic method.
*/
public void playBgMusic(final Audio audio) {
stopBgMusic();
var url = getClass().getResource(audio.getPath()).toExternalForm();
String url = getClass().getResource(audio.getPath()).toExternalForm();
bgPlayer = new MediaPlayer(new Media(url));
bgPlayer.setVolume(0.5);
bgPlayer.setVolume(masterVolume.get() * 0.5);
bgPlayer.setCycleCount(MediaPlayer.INDEFINITE);
bgPlayer.play();
}

/**
* Stopbgmusic method.
*/
public void stopBgMusic() {
if (bgPlayer != null) {
bgPlayer.stop();
bgPlayer.dispose();
bgPlayer = null;
}
}


/**
* Mastervolumeproperty method.
*/
public DoubleProperty masterVolumeProperty() { return masterVolume; }
/**
* Sfxvolumeproperty method.
*/
public DoubleProperty sfxVolumeProperty() { return sfxVolume; }

/**
* Returns the mastervolume.
*
* @return the value
*/
public double getMasterVolume() { return masterVolume.get(); }
/**
* Returns the sfxvolume.
*
* @return the value
*/
public double getSfxVolume() { return sfxVolume.get(); }

/**
* Sets the mastervolume.
*
* @param value the new value
*/
public void setMasterVolume(final double v) { masterVolume.set(clamp(v)); }
/**
* Sets the sfxvolume.
*
* @param value the new value
*/
public void setSfxVolume(final double v) { sfxVolume.set(clamp(v)); }


/** Converts a 0.0–1.0 linear volume to decibels for FloatControl. */
private static float volumeToDb(final double volume) {
if (volume <= 0.0) return -80.0f;
return (float) (20.0 * Math.log10(volume));
}

private static double clamp(final double v) {
return Math.max(0.0, Math.min(1.0, v));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@

import edu.ntnu.idi.idatt2003.gruppe42.View.Apps.AppStoreApp;

/**
* Controller for the App Store.
*/
/** Controller for the App Store. */
public class AppStoreController implements AppController {
/**
* Constructs a new AppStoreController.
*
* @param appStoreApp the app store view
*/
/** Constructs the controller. */
public AppStoreController(final AppStoreApp appStoreApp) {
}

/** Processes next tick. */
@Override
public void nextTick() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,14 @@
import edu.ntnu.idi.idatt2003.gruppe42.View.Apps.BankApp;
import javafx.application.Platform;

/**
* Controller for the {@link BankApp}.
* Handles updating the player's financial status and portfolio view.
*/
/** Controller for Bank app. */
public record BankAppController(BankApp bankApp, Player player) implements AppController {
/**
* Constructs a new BankAppController.
*
* @param bankApp the bank app view
* @param player the player model
*/
/** Constructs the controller. */
public BankAppController {
nextTick();
}

/** Processes next tick. */
@Override
public void nextTick() {
Platform.runLater(() -> {
Expand Down
Loading

0 comments on commit 3ad0a9e

Please sign in to comment.