diff --git a/core/src/main/java/io/github/com/quillraven/audio/AudioService.java b/core/src/main/java/io/github/com/quillraven/audio/AudioService.java index 6dda9e9..294ae63 100644 --- a/core/src/main/java/io/github/com/quillraven/audio/AudioService.java +++ b/core/src/main/java/io/github/com/quillraven/audio/AudioService.java @@ -2,6 +2,7 @@ package io.github.com.quillraven.audio; import com.badlogic.gdx.audio.Music; import com.badlogic.gdx.maps.tiled.TiledMap; +import com.badlogic.gdx.math.MathUtils; import io.github.com.quillraven.asset.AssetService; import io.github.com.quillraven.asset.MusicAsset; @@ -10,11 +11,34 @@ public class AudioService { private final AssetService assetService; private Music currentMusic; private MusicAsset currentMusicAsset; + private float musicVolume; + private float soundVolume; public AudioService(AssetService assetService) { this.assetService = assetService; this.currentMusic = null; this.currentMusicAsset = null; + this.musicVolume = 0.5f; + this.soundVolume = 0.33f; + } + + public void setMusicVolume(float volume) { + this.musicVolume = MathUtils.clamp(volume, 0f, 1f); + if (this.currentMusic != null) { + this.currentMusic.setVolume(volume); + } + } + + public float getMusicVolume() { + return musicVolume; + } + + public void setSoundVolume(float soundVolume) { + this.soundVolume = MathUtils.clamp(soundVolume, 0f, 1f); + } + + public float getSoundVolume() { + return soundVolume; } public void playMusic(MusicAsset musicAsset) { diff --git a/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java b/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java index 2a745bc..6f94cc2 100644 --- a/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java +++ b/core/src/main/java/io/github/com/quillraven/screen/GameScreen.java @@ -47,7 +47,7 @@ public class GameScreen extends ScreenAdapter { this.physicWorld = new World(Vector2.Zero, true); this.physicWorld.setAutoClearForces(false); this.engine = new Engine(); - this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld); + this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld, this.game.getAssetService()); ImmutableArray controllerEntities = this.engine.getEntitiesFor(Family.all(Controller.class).get()); this.keyboardController = new KeyboardController(GameControllerState.class, controllerEntities); diff --git a/core/src/main/java/io/github/com/quillraven/screen/MenuScreen.java b/core/src/main/java/io/github/com/quillraven/screen/MenuScreen.java index d1126a6..640a6a6 100644 --- a/core/src/main/java/io/github/com/quillraven/screen/MenuScreen.java +++ b/core/src/main/java/io/github/com/quillraven/screen/MenuScreen.java @@ -1,22 +1,15 @@ package io.github.com.quillraven.screen; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputMultiplexer; import com.badlogic.gdx.ScreenAdapter; -import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; -import com.badlogic.gdx.scenes.scene2d.ui.Image; -import com.badlogic.gdx.scenes.scene2d.ui.Label; -import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar; import com.badlogic.gdx.scenes.scene2d.ui.Skin; -import com.badlogic.gdx.scenes.scene2d.ui.Table; -import com.badlogic.gdx.scenes.scene2d.ui.TextButton; -import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; import io.github.com.quillraven.GdxGame; import io.github.com.quillraven.asset.SkinAsset; +import io.github.com.quillraven.ui.model.MenuViewModel; +import io.github.com.quillraven.ui.view.MenuView; public class MenuScreen extends ScreenAdapter { @@ -44,7 +37,7 @@ public class MenuScreen extends ScreenAdapter { this.inputMultiplexer.clear(); this.inputMultiplexer.addProcessor(stage); - menuUI(); + this.stage.addActor(new MenuView(stage, skin, new MenuViewModel(game))); } @Override @@ -52,72 +45,6 @@ public class MenuScreen extends ScreenAdapter { this.stage.clear(); } - private void menuUI() { - Table table = new Table(); - table.setFillParent(true); - - Image image = new Image(skin, "banner"); - table.add(image); - - table.row(); - Table table1 = new Table(); - table1.setBackground(skin.getDrawable("frame")); - table1.padLeft(40.0f); - table1.padRight(40.0f); - table1.padTop(25.0f); - table1.padBottom(20.0f); - - TextButton textButton = new TextButton("Start Game", skin); - textButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(GameScreen.class); - } - }); - table1.add(textButton); - - table1.row(); - Table table2 = new Table(); - - Label label = new Label("Music Volume", skin); - label.setColor(skin.getColor("sand")); - table2.add(label); - - table2.row(); - ProgressBar progressBar = new ProgressBar(0.0f, 100.0f, 1.0f, false, skin); - table2.add(progressBar); - table1.add(table2).padTop(10.0f); - - table1.row(); - table2 = new Table(); - - label = new Label("Sound Volume", skin); - label.setColor(skin.getColor("sand")); - table2.add(label); - - table2.row(); - progressBar = new ProgressBar(0.0f, 100.0f, 1.0f, false, skin); - table2.add(progressBar); - table1.add(table2).padTop(10.0f); - - table1.row(); - textButton = new TextButton("Quit Game", skin); - textButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - Gdx.app.exit(); - } - }); - table1.add(textButton).padTop(10.0f); - table.add(table1).align(Align.top).expandY().padTop(20f); - - table.row(); - label = new Label("by Quillraven 2025", skin, "small"); - label.setColor(skin.getColor("white")); - table.add(label).padRight(5.0f).padBottom(5f).expand().align(Align.bottomRight); - stage.addActor(table); - } - @Override public void render(float delta) { stage.act(delta); diff --git a/core/src/main/java/io/github/com/quillraven/ui/model/MenuViewModel.java b/core/src/main/java/io/github/com/quillraven/ui/model/MenuViewModel.java new file mode 100644 index 0000000..ba06b89 --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/ui/model/MenuViewModel.java @@ -0,0 +1,38 @@ +package io.github.com.quillraven.ui.model; + +import com.badlogic.gdx.Gdx; +import io.github.com.quillraven.GdxGame; +import io.github.com.quillraven.audio.AudioService; +import io.github.com.quillraven.screen.GameScreen; + +public class MenuViewModel extends ViewModel { + public static final String MUSIC_VOLUME_PROPERTY = "musicVolume"; + + private final AudioService audioService; + + public MenuViewModel(GdxGame game) { + super(game); + this.audioService = game.getAudioService(); + } + + public float getMusicVolume() { + return audioService.getMusicVolume(); + } + + public void setMusicVolume(float volume) { + this.propertyChangeSupport.firePropertyChange(MUSIC_VOLUME_PROPERTY, getMusicVolume(), volume); + this.audioService.setMusicVolume(volume); + } + + public float getSoundVolume() { + return audioService.getSoundVolume(); + } + + public void startGame() { + game.setScreen(GameScreen.class); + } + + public void quitGame() { + Gdx.app.exit(); + } +} diff --git a/core/src/main/java/io/github/com/quillraven/ui/model/ViewModel.java b/core/src/main/java/io/github/com/quillraven/ui/model/ViewModel.java new file mode 100644 index 0000000..b75c760 --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/ui/model/ViewModel.java @@ -0,0 +1,20 @@ +package io.github.com.quillraven.ui.model; + +import io.github.com.quillraven.GdxGame; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public abstract class ViewModel { + protected final GdxGame game; + protected final PropertyChangeSupport propertyChangeSupport; + + public ViewModel(GdxGame game) { + this.game = game; + this.propertyChangeSupport = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener); + } +} diff --git a/core/src/main/java/io/github/com/quillraven/ui/view/MenuView.java b/core/src/main/java/io/github/com/quillraven/ui/view/MenuView.java new file mode 100644 index 0000000..dd0ab92 --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/ui/view/MenuView.java @@ -0,0 +1,70 @@ +package io.github.com.quillraven.ui.view; + +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar; +import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.utils.Align; +import io.github.com.quillraven.ui.model.MenuViewModel; + +public class MenuView extends View { + + public MenuView(Stage stage, Skin skin, MenuViewModel viewModel) { + super(stage, skin, viewModel); + } + + @Override + protected void setupUI() { + setFillParent(true); + + Image image = new Image(skin, "banner"); + add(image).row(); + + setupMenuContent(); + + Label label = new Label("by Quillraven 2025", skin, "small"); + label.setColor(skin.getColor("white")); + add(label).padRight(5.0f).padBottom(5f).expand().align(Align.bottomRight); + } + + private void setupMenuContent() { + Table contentTable = new Table(); + contentTable.setBackground(skin.getDrawable("frame")); + contentTable.padLeft(40.0f); + contentTable.padRight(40.0f); + contentTable.padTop(25.0f); + contentTable.padBottom(20.0f); + + TextButton textButton = new TextButton("Start Game", skin); + onClick(textButton, ((event, x, y) -> viewModel.startGame())); + contentTable.add(textButton).row(); + + ProgressBar musicBar = setupVolumeBar(contentTable, "Music Volume", viewModel.getMusicVolume()); + viewModel.addPropertyChangeListener(MenuViewModel.MUSIC_VOLUME_PROPERTY, (event) -> + musicBar.setValue((Float) event.getNewValue()) + ); + setupVolumeBar(contentTable, "Sound Volume", viewModel.getSoundVolume()); + + textButton = new TextButton("Quit Game", skin); + onClick(textButton, ((event, x, y) -> viewModel.quitGame())); + contentTable.add(textButton).padTop(10.0f); + + add(contentTable).align(Align.top).expandY().padTop(20f).row(); + } + + private ProgressBar setupVolumeBar(Table contentTable, String title, float initialValue) { + Table table = new Table(); + Label label = new Label(title, skin); + label.setColor(skin.getColor("sand")); + table.add(label).row(); + + ProgressBar progressBar = new ProgressBar(0.0f, 1f, 0.05f, false, skin); + progressBar.setValue(initialValue); + table.add(progressBar).fill(); + contentTable.add(table).padTop(10.0f).row(); + return progressBar; + } +} diff --git a/core/src/main/java/io/github/com/quillraven/ui/view/View.java b/core/src/main/java/io/github/com/quillraven/ui/view/View.java new file mode 100644 index 0000000..d753319 --- /dev/null +++ b/core/src/main/java/io/github/com/quillraven/ui/view/View.java @@ -0,0 +1,40 @@ +package io.github.com.quillraven.ui.view; + +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import io.github.com.quillraven.ui.model.ViewModel; + +public abstract class View extends Table { + + protected final Stage stage; + protected final Skin skin; + protected final T viewModel; + + public View(Stage stage, Skin skin, T viewModel) { + super(skin); + this.stage = stage; + this.skin = skin; + this.viewModel = viewModel; + setupUI(); + } + + protected abstract void setupUI(); + + public static void onClick(Actor actor, OnClickConsumer consumer) { + actor.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + consumer.onClick(event, x, y); + } + }); + } + + @FunctionalInterface + public interface OnClickConsumer { + void onClick(InputEvent event, float x, float y); + } +}