diff --git a/app/src/main/java/org/toop/app/menu/CreditsMenu.java b/app/src/main/java/org/toop/app/menu/CreditsMenu.java index 35f34be..31c093a 100644 --- a/app/src/main/java/org/toop/app/menu/CreditsMenu.java +++ b/app/src/main/java/org/toop/app/menu/CreditsMenu.java @@ -1,32 +1,100 @@ -// package org.toop.app.menu; -// -// import javafx.application.Platform; -// import org.toop.framework.asset.ResourceManager; -// import org.toop.framework.asset.resources.LocalizationAsset; -// import org.toop.framework.eventbus.EventFlow; -// import org.toop.local.AppContext; -// -// import java.util.Locale; -// -// public final class CreditsMenu extends Menu { -// private Locale currentLocale = AppContext.getLocale(); -// private LocalizationAsset loc = ResourceManager.get("localization_en_us.properties"); -// public CreditsMenu() { -// try { -// new EventFlow() -// .listen(this::handleChangeLanguage); -// -// }catch (Exception e){ -// System.out.println("Something went wrong while trying to change the language."); -// throw e; -// } -// -// } -// private void handleChangeLanguage(LocalizationEvents.LanguageHasChanged event) { -// Platform.runLater(() -> { -// currentLocale = AppContext.getLocale(); -// //credits.setText(loc.getString("credits",currentLocale)); -// }); -// -// } -// } \ No newline at end of file +package org.toop.app.menu; + +import javafx.animation.Interpolator; +import javafx.animation.PauseTransition; +import javafx.animation.TranslateTransition; +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.util.Duration; +import org.toop.app.App; +import org.toop.framework.asset.ResourceManager; +import org.toop.framework.asset.resources.LocalizationAsset; +import org.toop.framework.eventbus.EventFlow; +import org.toop.local.AppContext; +import org.toop.local.LocalizationEvents; + +import java.util.Locale; + +public final class CreditsMenu extends Menu { ; + private Locale currentLocale = AppContext.getLocale(); + private LocalizationAsset loc = ResourceManager.get("localization_en_us.properties"); + + String[] credits = { + "Scrum Master: Stef", + "Product Owner: Omar", + "Merge Commander: Bas", + "Localization: Ticho", + "AI: Michiel", + "Developers: Michiel, Bas, Stef, Omar, Ticho", + "Moral Support: Wesley (voor 1 week)", + "OpenGL: Omar" + }; + + double scrollDuration = 20.0; + double lineHeight = 40.0; + + public CreditsMenu() { + VBox creditsBox = new VBox(lineHeight / 2); + for (int i = credits.length - 1; i >= 0; i--) { + creditsBox.getChildren().add(createText(credits[i])); + creditsBox.setAlignment(Pos.CENTER); + } + + Button exit = new Button("<"); + exit.setStyle( + "-fx-background-color: transparent;" + + "-fx-text-fill: white;" + + "-fx-font-size: 72px;" + + "-fx-padding: 10 20 10 20;" + ); + exit.setOnAction(e -> App.pop()); + + final Region background = createBackground(); + StackPane.setAlignment(exit, Pos.TOP_LEFT); + pane = new StackPane(background, creditsBox, exit); + + Platform.runLater(() -> playCredits(creditsBox, 800)); + + try { + new EventFlow() + .listen(this::handleChangeLanguage); + + }catch (Exception e){ + System.out.println("Something went wrong while trying to change the language."); + throw e; + } + } + + public void playCredits(VBox creditsBox, double sceneLength) { + double height = (credits.length * lineHeight); + double startY = -sceneLength; + double endY = height; + + creditsBox.setTranslateY(startY); + + TranslateTransition scrollCredits = new TranslateTransition(); + scrollCredits.setNode(creditsBox); + scrollCredits.setFromY(startY); + scrollCredits.setToY(endY / 2 - 200); + scrollCredits.setDuration(Duration.seconds(scrollDuration)); + scrollCredits.setInterpolator(Interpolator.LINEAR); + + scrollCredits.setOnFinished(e -> { + PauseTransition pauseCredits = new PauseTransition(Duration.seconds(5)); + pauseCredits.setOnFinished(a -> playCredits(creditsBox, sceneLength)); + pauseCredits.play(); + }); + + scrollCredits.play(); + } + private void handleChangeLanguage(LocalizationEvents.LanguageHasChanged event) { + Platform.runLater(() -> { + currentLocale = AppContext.getLocale(); + //credits.setText(loc.getString("credits",currentLocale)); + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/toop/app/menu/MainMenu.java b/app/src/main/java/org/toop/app/menu/MainMenu.java index e09fb91..2765083 100644 --- a/app/src/main/java/org/toop/app/menu/MainMenu.java +++ b/app/src/main/java/org/toop/app/menu/MainMenu.java @@ -1,65 +1,69 @@ -// package org.toop.app.menu; -// -// import javafx.application.Platform; -// import org.toop.app.App; -// import org.toop.app.GameType; -// -// import javafx.geometry.Pos; -// import javafx.scene.control.Button; -// import javafx.scene.layout.*; -// import org.toop.framework.asset.ResourceManager; -// import org.toop.framework.asset.resources.LocalizationAsset; -// import org.toop.framework.eventbus.EventFlow; -// import org.toop.local.AppContext; -// -// import java.util.Locale; -// -// public final class MainMenu extends Menu { -// private Locale currentLocale = AppContext.getLocale(); -// private final LocalizationAsset loc = ResourceManager.get("localization"); -// private final Button tictactoe,reversi,credits,options,quit; -// public MainMenu() { -// final Region background = createBackground(); -// -// tictactoe = createButton(loc.getString("mainMenuSelectTicTacToe",currentLocale), () -> { App.activate(new GameSelectMenu(GameType.TICTACTOE)); }); -// reversi = createButton(loc.getString("mainMenuSelectReversi",currentLocale), () -> { App.activate(new GameSelectMenu(GameType.REVERSI)); }); -// -// final VBox gamesBox = new VBox(10, tictactoe, reversi); -// gamesBox.setAlignment(Pos.TOP_LEFT); -// gamesBox.setPickOnBounds(false); -// gamesBox.setTranslateY(50); -// gamesBox.setTranslateX(25); -// -// credits = createButton(loc.getString("mainMenuSelectCredits",currentLocale), () -> { App.push(new CreditsMenu()); }); -// options = createButton(loc.getString("mainMenuSelectOptions",currentLocale), () -> { App.push(new OptionsMenu()); }); -// quit = createButton(loc.getString("mainMenuSelectQuit",currentLocale), () -> { App.quitPopup(); }); -// -// final VBox controlBox = new VBox(10, credits, options, quit); -// controlBox.setAlignment(Pos.BOTTOM_LEFT); -// controlBox.setPickOnBounds(false); -// controlBox.setTranslateY(-50); -// controlBox.setTranslateX(25); -// -// pane = new StackPane(background, gamesBox, controlBox); -// try { -// new EventFlow() -// .listen(this::handleChangeLanguage); -// -// }catch (Exception e){ -// System.out.println("Something went wrong while trying to change the language."); -// throw e; -// } -// -// } -// private void handleChangeLanguage(LocalizationEvents.LanguageHasChanged event) { -// Platform.runLater(() -> { -// currentLocale = AppContext.getLocale(); -// tictactoe.setText(loc.getString("mainMenuSelectTicTacToe",currentLocale)); -// reversi.setText(loc.getString("mainMenuSelectReversi",currentLocale)); -// credits.setText(loc.getString("mainMenuSelectCredits",currentLocale)); -// options.setText(loc.getString("mainMenuSelectOptions",currentLocale)); -// quit.setText(loc.getString("mainMenuSelectQuit",currentLocale)); -// }); -// -// } -// } \ No newline at end of file +package org.toop.app.menu; + +import javafx.application.Platform; +import org.toop.app.App; +import org.toop.app.GameType; + +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.layout.*; +import org.toop.framework.asset.ResourceManager; +import org.toop.framework.asset.resources.LocalizationAsset; +import org.toop.framework.eventbus.EventFlow; +import org.toop.game.tictactoe.TicTacToe; +import org.toop.local.AppContext; +import org.toop.local.LocalizationEvents; + +import java.util.Locale; + +public final class MainMenu extends Menu { + private Locale currentLocale = AppContext.getLocale(); + private final LocalizationAsset loc = ResourceManager.get("localization"); + private final Button tictactoe,reversi,credits,options,quit; + public MainMenu() { + final Region background = createBackground(); + + tictactoe = createButton( + loc.getString("mainMenuSelectTicTacToe",currentLocale), () -> { App.activate(new GameSelectMenu(GameType.TICTACTOE)); }); + reversi = createButton( + loc.getString("mainMenuSelectReversi",currentLocale), () -> { App.activate(new GameSelectMenu(GameType.REVERSI)); }); + + final VBox gamesBox = new VBox(10, tictactoe, reversi); + gamesBox.setAlignment(Pos.TOP_LEFT); + gamesBox.setPickOnBounds(false); + gamesBox.setTranslateY(50); + gamesBox.setTranslateX(25); + + credits = createButton(loc.getString("mainMenuSelectCredits",currentLocale), () -> { App.push(new CreditsMenu()); }); + options = createButton(loc.getString("mainMenuSelectOptions",currentLocale), () -> { App.push(new OptionsMenu()); }); + quit = createButton(loc.getString("mainMenuSelectQuit",currentLocale), () -> { App.quitPopup(); }); + + final VBox controlBox = new VBox(10, credits, options, quit); + controlBox.setAlignment(Pos.BOTTOM_LEFT); + controlBox.setPickOnBounds(false); + controlBox.setTranslateY(-50); + controlBox.setTranslateX(25); + + pane = new StackPane(background, gamesBox, controlBox); + try { + new EventFlow() + .listen(this::handleChangeLanguage); + + }catch (Exception e){ + System.out.println("Something went wrong while trying to change the language."); + throw e; + } + + } + private void handleChangeLanguage(LocalizationEvents.LanguageHasChanged event) { + Platform.runLater(() -> { + currentLocale = AppContext.getLocale(); + tictactoe.setText(loc.getString("mainMenuSelectTicTacToe",currentLocale)); + reversi.setText(loc.getString("mainMenuSelectReversi",currentLocale)); + credits.setText(loc.getString("mainMenuSelectCredits",currentLocale)); + options.setText(loc.getString("mainMenuSelectOptions",currentLocale)); + quit.setText(loc.getString("mainMenuSelectQuit",currentLocale)); + }); + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/toop/app/menu/Menu.java b/app/src/main/java/org/toop/app/menu/Menu.java index 9e9ac29..6863d8e 100644 --- a/app/src/main/java/org/toop/app/menu/Menu.java +++ b/app/src/main/java/org/toop/app/menu/Menu.java @@ -4,6 +4,8 @@ import javafx.scene.control.Button; import javafx.scene.layout.Pane; import javafx.scene.layout.Region; import javafx.scene.text.Text; +import org.toop.framework.audio.events.AudioEvents; +import org.toop.framework.eventbus.EventFlow; public abstract class Menu { protected Pane pane; @@ -34,7 +36,10 @@ public abstract class Menu { public Button createButton(String css, String x, Runnable runnable) { final Button button = new Button(x); - button.setOnAction(_ -> runnable.run()); + button.setOnAction(_ -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + runnable.run(); + }); button.getStyleClass().add(css); return button; diff --git a/app/src/main/java/org/toop/app/menu/OptionsMenu.java b/app/src/main/java/org/toop/app/menu/OptionsMenu.java index ffa7ac5..7a67422 100644 --- a/app/src/main/java/org/toop/app/menu/OptionsMenu.java +++ b/app/src/main/java/org/toop/app/menu/OptionsMenu.java @@ -1,142 +1,174 @@ -// package org.toop.app.menu; -// -// import javafx.geometry.Pos; -// import javafx.scene.control.*; -// import javafx.scene.control.Button; -// import javafx.scene.control.Label; -// import javafx.scene.layout.Region; -// import javafx.scene.layout.StackPane; -// import javafx.scene.layout.VBox; -// import org.toop.app.App; -// import org.toop.framework.asset.ResourceManager; -// import org.toop.framework.asset.resources.LocalizationAsset; -// import org.toop.framework.audio.events.AudioEvents; -// import org.toop.framework.eventbus.EventFlow; -// import org.toop.local.AppContext; -// -// import java.awt.*; -// import java.util.Locale; -// -// public final class OptionsMenu extends Menu { -// private Locale currentLocale = AppContext.getLocale(); -// private LocalizationAsset loc = ResourceManager.get("localization"); -// private GraphicsDevice currentScreenDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0]; -// -// public OptionsMenu() { -// final Label selectLanguageLabel = new Label( -// loc.getString("optionsMenuLabelSelectLanguage", currentLocale) -// ); -// -// final Button exitOptionsButton = createButton("Exit Options", () -> { App.pop(); } ); -// -// final VBox optionsBox = new VBox(10, -// selectLanguageLabel, -// languageSelectorCreation(), -// screenDeviceSelectorCreation(), -// displayModeSelectorCreation(), -// selectFullscreenCreation(), -// volumeSelectorCreation(), -// exitOptionsButton); -// -// optionsBox.setAlignment(Pos.CENTER); -// optionsBox.setPickOnBounds(false); -// optionsBox.setTranslateY(50); -// optionsBox.setTranslateX(25); -// -// pane = new StackPane(optionsBox); -// -// } -// -// private ChoiceBox languageSelectorCreation() { -// final ChoiceBox selectLanguage = new ChoiceBox<>(); -// selectLanguage.setValue(currentLocale); -// -// for (Locale locFile : loc.getAvailableLocales()) { -// selectLanguage.getItems().add(locFile); -// } -// -// selectLanguage.setConverter(new javafx.util.StringConverter() { -// @Override -// public String toString(Locale locale) { -// return locale.getDisplayName(); -// } -// -// @Override -// public Locale fromString(String string) { -// return null; -// } -// }); -// -// selectLanguage.setOnAction(event -> { -// Locale selectedLocale = selectLanguage.getSelectionModel().getSelectedItem(); -// if (selectedLocale != null) { -// AppContext.setLocale(selectedLocale); -// App.pop(); -// App.push(new OptionsMenu()); -// } -// }); -// -// return selectLanguage; -// } -// -// private ChoiceBox screenDeviceSelectorCreation() { -// GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); -// GraphicsDevice[] devices = ge.getScreenDevices(); -// final ChoiceBox selectScreen = new ChoiceBox<>(); -// for (GraphicsDevice screen : devices) { -// selectScreen.getItems().add(screen); -// } -// -// selectScreen.setOnAction(event -> { -// int selectedIndex = selectScreen.getSelectionModel().getSelectedIndex(); -// Object selectedItem = selectScreen.getSelectionModel().getSelectedItem(); -// -// System.out.println("Selection made: [" + selectedIndex + "] " + selectedItem); -// System.out.println(" ChoiceBox.getValue(): " + selectScreen.getValue()); -// }); -// return selectScreen; -// } -// -// private ChoiceBox displayModeSelectorCreation() { -// final ChoiceBox selectWindowSize = new ChoiceBox<>(); -// for (DisplayMode displayMode : currentScreenDevice.getDisplayModes()) { -// selectWindowSize.getItems().add(displayMode); -// } -// return selectWindowSize; -// } -// -// private CheckBox selectFullscreenCreation() { -// final CheckBox setFullscreen = new CheckBox("Fullscreen"); -// setFullscreen.setSelected(App.isFullscreen()); -// setFullscreen.setOnAction(event -> { -// boolean isSelected = setFullscreen.isSelected(); -// App.setFullscreen(isSelected); -// }); -// return setFullscreen; -// } -// -// private Slider volumeSelectorCreation() { -// Slider volumeSlider = new Slider(0, 100, 50); -// new EventFlow() -// .addPostEvent(AudioEvents.GetCurrentVolume.class) -// .onResponse(AudioEvents.GetCurrentVolumeReponse.class, event -> { -// volumeSlider.setValue(event.currentVolume() * 100); -// }).asyncPostEvent(); -// volumeSlider.setShowTickLabels(true); -// volumeSlider.setShowTickMarks(true); -// volumeSlider.setMajorTickUnit(25); -// volumeSlider.setMinorTickCount(4); -// volumeSlider.setBlockIncrement(5); -// volumeSlider.setMaxWidth(225); -// -// Label valueLabel = new Label(String.valueOf((int) volumeSlider.getValue())); -// -// volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> { -// valueLabel.setText(String.valueOf(newVal.intValue())); -// new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newVal.doubleValue()/100.0)) -// .asyncPostEvent(); -// }); -// return volumeSlider; -// } -// -// } \ No newline at end of file +package org.toop.app.menu; + +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import org.toop.app.App; +import org.toop.framework.asset.ResourceManager; +import org.toop.framework.asset.resources.LocalizationAsset; +import org.toop.framework.audio.events.AudioEvents; +import org.toop.framework.eventbus.EventFlow; +import org.toop.local.AppContext; + +import java.awt.*; +import java.util.Locale; + +public final class OptionsMenu extends Menu { + private Locale currentLocale = AppContext.getLocale(); + private LocalizationAsset loc = ResourceManager.get("localization"); + private GraphicsDevice currentScreenDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0]; + + public OptionsMenu() { + final Label selectLanguageLabel = new Label( + loc.getString("optionsMenuLabelSelectLanguage", currentLocale) + ); + + final Button exitOptionsButton = createButton("Exit Options", () -> { App.pop(); } ); + + final VBox optionsBox = new VBox(10, + selectLanguageLabel, + languageSelectorCreation(), + screenDeviceSelectorCreation(), + displayModeSelectorCreation(), + selectFullscreenCreation(), + volumeSelectorCreation(), + exitOptionsButton); + + optionsBox.setAlignment(Pos.CENTER); + optionsBox.setPickOnBounds(false); + optionsBox.setTranslateY(50); + optionsBox.setTranslateX(25); + + pane = new StackPane(optionsBox); + + } + + private ChoiceBox languageSelectorCreation() { + final ChoiceBox selectLanguage = new ChoiceBox<>(); + selectLanguage.setValue(currentLocale); + + for (Locale locFile : loc.getAvailableLocales()) { + selectLanguage.getItems().add(locFile); + } + + selectLanguage.setConverter(new javafx.util.StringConverter<>() { + @Override + public String toString(Locale locale) { + return locale.getDisplayName(); + } + + @Override + public Locale fromString(String string) { + return null; + } + }); + + selectLanguage.setOnShowing(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + }); + + selectLanguage.setOnAction(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + Locale selectedLocale = selectLanguage.getSelectionModel().getSelectedItem(); + if (selectedLocale != null) { + AppContext.setLocale(selectedLocale); + App.pop(); + App.push(new OptionsMenu()); + } + }); + + return selectLanguage; + } + + private ChoiceBox screenDeviceSelectorCreation() { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = ge.getScreenDevices(); + final ChoiceBox selectScreen = new ChoiceBox<>(); + for (GraphicsDevice screen : devices) { + selectScreen.getItems().add(screen); + } + + selectScreen.setOnShowing(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + }); + + selectScreen.setOnAction(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + int selectedIndex = selectScreen.getSelectionModel().getSelectedIndex(); + Object selectedItem = selectScreen.getSelectionModel().getSelectedItem(); + + System.out.println("Selection made: [" + selectedIndex + "] " + selectedItem); + System.out.println(" ChoiceBox.getValue(): " + selectScreen.getValue()); + }); + return selectScreen; + } + + private ChoiceBox displayModeSelectorCreation() { + final ChoiceBox selectWindowSize = new ChoiceBox<>(); + for (DisplayMode displayMode : currentScreenDevice.getDisplayModes()) { + selectWindowSize.getItems().add(displayMode); + } + selectWindowSize.setOnShowing(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + }); + selectWindowSize.setOnAction(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + int selectedIndex = selectWindowSize.getSelectionModel().getSelectedIndex(); + Object selectedItem = selectWindowSize.getSelectionModel().getSelectedItem(); + + System.out.println("Selection made: [" + selectedIndex + "] " + selectedItem); + System.out.println(" ChoiceBox.getValue(): " + selectWindowSize.getValue()); + }); + return selectWindowSize; + } + + private CheckBox selectFullscreenCreation() { + final CheckBox setFullscreen = new CheckBox("Fullscreen"); + setFullscreen.setSelected(App.isFullscreen()); + setFullscreen.setOnAction(event -> { + new EventFlow().addPostEvent(new AudioEvents.clickButton()).asyncPostEvent(); + boolean isSelected = setFullscreen.isSelected(); + App.setFullscreen(isSelected); + }); + return setFullscreen; + } + + private Slider volumeSelectorCreation() { + Slider volumeSlider = new Slider(0, 100, 50); + new EventFlow() + .addPostEvent(AudioEvents.GetCurrentVolume.class) + .onResponse(AudioEvents.GetCurrentVolumeReponse.class, event -> { + volumeSlider.setValue(event.currentVolume() * 100); + }, true).asyncPostEvent(); + volumeSlider.setShowTickLabels(true); + volumeSlider.setShowTickMarks(true); + volumeSlider.setMajorTickUnit(25); + volumeSlider.setMinorTickCount(4); + volumeSlider.setBlockIncrement(5); + volumeSlider.setMaxWidth(225); + + Label valueLabel = new Label(String.valueOf((int) volumeSlider.getValue())); + + final long[] lastPlayed = {0}; + final long cooldown = 50; + volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> { + long now = System.currentTimeMillis(); + + if (now - lastPlayed[0] >= cooldown) { + lastPlayed[0] = now; +// new EventFlow().addPostEvent(new AudioEvents.clickButton()) +// .asyncPostEvent(); // TODO: creates double sound bug, WHYYY???? + } + valueLabel.setText(String.valueOf(newVal.intValue())); + new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newVal.doubleValue()/100.0)) + .asyncPostEvent(); + }); + + return volumeSlider; + } + +} \ No newline at end of file diff --git a/app/src/main/resources/assets/audio/fx/harsh-button-click.wav b/app/src/main/resources/assets/audio/fx/harsh-button-click.wav new file mode 100644 index 0000000..1ad2158 Binary files /dev/null and b/app/src/main/resources/assets/audio/fx/harsh-button-click.wav differ diff --git a/app/src/main/resources/assets/audio/fx/medium-button-click.wav b/app/src/main/resources/assets/audio/fx/medium-button-click.wav new file mode 100644 index 0000000..acd2ee3 Binary files /dev/null and b/app/src/main/resources/assets/audio/fx/medium-button-click.wav differ diff --git a/app/src/main/resources/assets/audio/fx/soft-button-click.wav b/app/src/main/resources/assets/audio/fx/soft-button-click.wav new file mode 100644 index 0000000..f795c3c Binary files /dev/null and b/app/src/main/resources/assets/audio/fx/soft-button-click.wav differ diff --git a/app/src/main/resources/assets/style/credits.css b/app/src/main/resources/assets/style/credits.css new file mode 100644 index 0000000..be920fe --- /dev/null +++ b/app/src/main/resources/assets/style/credits.css @@ -0,0 +1,18 @@ +.credit-text { + -fx-fill: #ffffff; + -fx-font-size: 24px; + -fx-font-family: "Arial"; + -fx-font-weight: bold; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.7), 4, 0, 2, 2); +} + +.button.exit-button { + -fx-background-color: #3498db; + -fx-text-fill: white; + -fx-font-size: 72px; + -fx-padding: 10 20 10 20; + -fx-background-radius: 5; +} +.button.exit-button:hover { + -fx-background-color: #2980b9; +} diff --git a/framework/src/main/java/org/toop/framework/asset/ResourceManager.java b/framework/src/main/java/org/toop/framework/asset/ResourceManager.java index 982caeb..8324b25 100644 --- a/framework/src/main/java/org/toop/framework/asset/ResourceManager.java +++ b/framework/src/main/java/org/toop/framework/asset/ResourceManager.java @@ -1,5 +1,7 @@ package org.toop.framework.asset; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.toop.framework.asset.resources.*; import java.util.*; @@ -46,6 +48,7 @@ import java.util.concurrent.ConcurrentHashMap; * */ public class ResourceManager { + private static final Logger logger = LogManager.getLogger(ResourceManager.class); private static final ResourceManager INSTANCE = new ResourceManager(); private static final Map> assets = new ConcurrentHashMap<>(); diff --git a/framework/src/main/java/org/toop/framework/asset/resources/SoundEffectAsset.java b/framework/src/main/java/org/toop/framework/asset/resources/SoundEffectAsset.java index 1d0cedd..3ca6386 100644 --- a/framework/src/main/java/org/toop/framework/asset/resources/SoundEffectAsset.java +++ b/framework/src/main/java/org/toop/framework/asset/resources/SoundEffectAsset.java @@ -23,7 +23,10 @@ public class SoundEffectAsset extends BaseResource implements LoadableResource { Clip clip = AudioSystem.getClip(); // Insert a new audio stream into the clip - clip.open(this.getAudioStream()); + AudioInputStream inputStream = this.getAudioStream(); + AudioFormat baseFormat = inputStream.getFormat(); + if (baseFormat.getSampleSizeInBits() > 16) inputStream = downSampleAudio(inputStream, baseFormat); + clip.open(inputStream); // ^ Clip can only run 16 bit and lower, thus downsampling necessary. return clip; } @@ -32,6 +35,20 @@ public class SoundEffectAsset extends BaseResource implements LoadableResource { return AudioSystem.getAudioInputStream(this.file); } + private AudioInputStream downSampleAudio(AudioInputStream audioInputStream, AudioFormat baseFormat) { + AudioFormat decodedFormat = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + baseFormat.getSampleRate(), + 16, // force 16-bit + baseFormat.getChannels(), + baseFormat.getChannels() * 2, + baseFormat.getSampleRate(), + false // little-endian + ); + + return AudioSystem.getAudioInputStream(decodedFormat, audioInputStream); + } + @Override public void load() { try { diff --git a/framework/src/main/java/org/toop/framework/audio/SoundManager.java b/framework/src/main/java/org/toop/framework/audio/SoundManager.java index 2a0ec17..f7fad76 100644 --- a/framework/src/main/java/org/toop/framework/audio/SoundManager.java +++ b/framework/src/main/java/org/toop/framework/audio/SoundManager.java @@ -1,5 +1,7 @@ package org.toop.framework.audio; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.toop.framework.SnowflakeGenerator; import org.toop.framework.asset.ResourceManager; import org.toop.framework.asset.ResourceMeta; @@ -15,6 +17,7 @@ import java.util.*; import javax.sound.sampled.*; public class SoundManager { + private static final Logger logger = LogManager.getLogger(SoundManager.class); private final List activeMusic = new ArrayList<>(); private final Queue backgroundMusicQueue = new LinkedList<>(); private final Map activeSoundEffects = new HashMap<>(); @@ -38,16 +41,16 @@ public class SoundManager { .listen(this::handleMusicStart) .listen(this::handleVolumeChange) .listen(this::handleGetCurrentVolume) - .listen(AudioEvents.playOnClickButton.class, _ -> { + .listen(AudioEvents.clickButton.class, _ -> { try { - playSound("hitsound0.wav", false); + playSound("medium-button-click.wav", false); } catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) { - throw new RuntimeException(e); + logger.error(e); } }); } - private void handlePlaySound(AudioEvents.PlayAudio event) { + private void handlePlaySound(AudioEvents.PlayEffect event) { try { this.playSound(event.fileName(), event.loop()); } catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) { @@ -55,7 +58,7 @@ public class SoundManager { } } - private void handleStopSound(AudioEvents.StopAudio event) { + private void handleStopSound(AudioEvents.StopEffect event) { this.stopSound(event.clipId()); } @@ -71,7 +74,6 @@ public class SoundManager { for (MediaPlayer mediaPlayer : this.activeMusic) { mediaPlayer.setVolume(this.volume); } - IO.println("Volume: " + this.volume); } private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { @@ -125,13 +127,16 @@ public class SoundManager { mediaPlayer.setVolume(this.volume); mediaPlayer.play(); activeMusic.add(mediaPlayer); + logger.info("Playing background music: {}", ma.getFile().getName()); + logger.info("Background music next in line: {}", backgroundMusicQueue.peek().getFile().getName()); } private long playSound(String audioFileName, boolean loop) throws UnsupportedAudioFileException, LineUnavailableException, IOException { SoundEffectAsset asset = audioResources.get(audioFileName); // Return -1 which indicates resource wasn't available - if (asset == null){ + if (asset == null) { + logger.warn("Unable to load audio asset: {}", audioFileName); return -1; } @@ -146,6 +151,8 @@ public class SoundManager { clip.start(); } + logger.debug("Playing sound: {}", asset.getFile().getName()); + // Generate id for clip long clipId = idGenerator.nextId(); diff --git a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java index 08fb67b..5aceb8c 100644 --- a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java +++ b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java @@ -1,6 +1,5 @@ package org.toop.framework.audio.events; -import org.toop.framework.asset.resources.MusicAsset; import org.toop.framework.eventbus.events.EventWithSnowflake; import org.toop.framework.eventbus.events.EventWithoutSnowflake; import org.toop.framework.eventbus.events.EventsBase; @@ -9,10 +8,10 @@ import java.util.Map; public class AudioEvents extends EventsBase { /** Starts playing a sound. */ - public record PlayAudio(String fileName, boolean loop) + public record PlayEffect(String fileName, boolean loop) implements EventWithoutSnowflake {} - public record StopAudio(long clipId) implements EventWithoutSnowflake {} + public record StopEffect(long clipId) implements EventWithoutSnowflake {} public record StartBackgroundMusic() implements EventWithoutSnowflake {} public record ChangeVolume(double newVolume) implements EventWithoutSnowflake {} @@ -38,5 +37,5 @@ public class AudioEvents extends EventsBase { return snowflakeId; } } - public record playOnClickButton() implements EventWithoutSnowflake {} + public record clickButton() implements EventWithoutSnowflake {} }