add main menu keyboard controls
This commit is contained in:
@@ -4,5 +4,6 @@ public enum Command {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
DOWN,
|
||||
UP
|
||||
UP,
|
||||
SELECT
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@ package io.github.com.quillraven.input;
|
||||
public interface ControllerState {
|
||||
void keyDown(Command command);
|
||||
|
||||
void keyUp(Command command);
|
||||
default void keyUp(Command command) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package io.github.com.quillraven.input;
|
||||
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.utils.ImmutableArray;
|
||||
import io.github.com.quillraven.component.Controller;
|
||||
import io.github.com.quillraven.component.Move;
|
||||
|
||||
public class GameControllerState implements ControllerState {
|
||||
|
||||
private final ImmutableArray<Entity> controllerEntities;
|
||||
|
||||
public GameControllerState(ImmutableArray<Entity> controllerEntities) {
|
||||
this.controllerEntities = controllerEntities;
|
||||
public GameControllerState(Engine engine) {
|
||||
this.controllerEntities = engine.getEntitiesFor(Family.all(Controller.class).get());
|
||||
}
|
||||
|
||||
private void moveEntities(float dx, float dy) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.github.com.quillraven.input;
|
||||
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.utils.ImmutableArray;
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.InputAdapter;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -14,20 +14,28 @@ public class KeyboardController extends InputAdapter {
|
||||
Map.entry(Input.Keys.W, Command.UP),
|
||||
Map.entry(Input.Keys.S, Command.DOWN),
|
||||
Map.entry(Input.Keys.A, Command.LEFT),
|
||||
Map.entry(Input.Keys.D, Command.RIGHT)
|
||||
Map.entry(Input.Keys.D, Command.RIGHT),
|
||||
Map.entry(Input.Keys.SPACE, Command.SELECT)
|
||||
);
|
||||
|
||||
private final boolean[] commandState;
|
||||
private final Map<Class<? extends ControllerState>, ControllerState> stateCache;
|
||||
private ControllerState activeState;
|
||||
|
||||
public KeyboardController(Class<? extends ControllerState> initialState, ImmutableArray<Entity> controllerEntities) {
|
||||
public KeyboardController(Class<? extends ControllerState> initialState,
|
||||
Engine engine,
|
||||
Stage stage) {
|
||||
this.commandState = new boolean[Command.values().length];
|
||||
this.stateCache = new HashMap<>();
|
||||
this.activeState = null;
|
||||
|
||||
this.stateCache.put(IdleControllerState.class, new IdleControllerState());
|
||||
this.stateCache.put(GameControllerState.class, new GameControllerState(controllerEntities));
|
||||
if (engine != null) {
|
||||
this.stateCache.put(GameControllerState.class, new GameControllerState(engine));
|
||||
}
|
||||
if (stage != null) {
|
||||
this.stateCache.put(UiControllerState.class, new UiControllerState(stage));
|
||||
}
|
||||
setActiveState(initialState);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.github.com.quillraven.input;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
|
||||
public class UiControllerState implements ControllerState {
|
||||
|
||||
private final Stage stage;
|
||||
|
||||
public UiControllerState(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown(Command command) {
|
||||
this.stage.getRoot().fire(new UiEvent(command));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.github.com.quillraven.input;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.Event;
|
||||
|
||||
public class UiEvent extends Event {
|
||||
private final Command command;
|
||||
|
||||
public UiEvent(Command command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
package io.github.com.quillraven.screen;
|
||||
|
||||
import com.badlogic.ashley.core.Engine;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.EntitySystem;
|
||||
import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.utils.ImmutableArray;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
@@ -15,7 +12,6 @@ import com.badlogic.gdx.utils.Disposable;
|
||||
import io.github.com.quillraven.GdxGame;
|
||||
import io.github.com.quillraven.asset.MapAsset;
|
||||
import io.github.com.quillraven.audio.AudioService;
|
||||
import io.github.com.quillraven.component.Controller;
|
||||
import io.github.com.quillraven.input.GameControllerState;
|
||||
import io.github.com.quillraven.input.KeyboardController;
|
||||
import io.github.com.quillraven.system.AnimationSystem;
|
||||
@@ -48,8 +44,7 @@ public class GameScreen extends ScreenAdapter {
|
||||
this.physicWorld.setAutoClearForces(false);
|
||||
this.engine = new Engine();
|
||||
this.tiledAshleySpawner = new TiledAshleySpawner(this.engine, this.physicWorld, this.game.getAssetService());
|
||||
ImmutableArray<Entity> controllerEntities = this.engine.getEntitiesFor(Family.all(Controller.class).get());
|
||||
this.keyboardController = new KeyboardController(GameControllerState.class, controllerEntities);
|
||||
this.keyboardController = new KeyboardController(GameControllerState.class, engine, null);
|
||||
|
||||
// add ECS systems
|
||||
this.engine.addSystem(new PhysicMoveSystem());
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import io.github.com.quillraven.GdxGame;
|
||||
import io.github.com.quillraven.asset.MusicAsset;
|
||||
import io.github.com.quillraven.asset.SkinAsset;
|
||||
import io.github.com.quillraven.input.KeyboardController;
|
||||
import io.github.com.quillraven.input.UiControllerState;
|
||||
import io.github.com.quillraven.ui.model.MenuViewModel;
|
||||
import io.github.com.quillraven.ui.view.MenuView;
|
||||
|
||||
@@ -19,12 +21,14 @@ public class MenuScreen extends ScreenAdapter {
|
||||
private final Skin skin;
|
||||
private final Viewport uiViewport;
|
||||
private final InputMultiplexer inputMultiplexer;
|
||||
private final KeyboardController keyboardController;
|
||||
|
||||
public MenuScreen(GdxGame game) {
|
||||
this.game = game;
|
||||
this.uiViewport = new FitViewport(800f, 450f);
|
||||
this.stage = new Stage(uiViewport, game.getBatch());
|
||||
this.skin = game.getAssetService().get(SkinAsset.DEFAULT);
|
||||
this.keyboardController = new KeyboardController(UiControllerState.class, null, stage);
|
||||
this.inputMultiplexer = game.getInputMultiplexer();
|
||||
}
|
||||
|
||||
@@ -37,6 +41,7 @@ public class MenuScreen extends ScreenAdapter {
|
||||
public void show() {
|
||||
this.inputMultiplexer.clear();
|
||||
this.inputMultiplexer.addProcessor(stage);
|
||||
this.inputMultiplexer.addProcessor(keyboardController);
|
||||
|
||||
this.stage.addActor(new MenuView(stage, skin, new MenuViewModel(game)));
|
||||
this.game.getAudioService().playMusic(MusicAsset.MENU);
|
||||
|
||||
@@ -12,23 +12,27 @@ import com.badlogic.gdx.scenes.scene2d.ui.Slider;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import io.github.com.quillraven.ui.model.MenuViewModel;
|
||||
|
||||
public class MenuView extends View<MenuViewModel> {
|
||||
private final Image selectionImg;
|
||||
private Group selectedItem;
|
||||
|
||||
public MenuView(Stage stage, Skin skin, MenuViewModel viewModel) {
|
||||
super(stage, skin, viewModel);
|
||||
|
||||
this.selectionImg = new Image(skin, "selection");
|
||||
this.selectionImg.setTouchable(Touchable.disabled);
|
||||
selectMenuItem(this.findActor("startGameBtn"));
|
||||
this.selectedItem = findActor(MenuOption.START_GAME.name());
|
||||
selectMenuItem(this.selectedItem);
|
||||
}
|
||||
|
||||
private void selectMenuItem(Group menuItem) {
|
||||
if (selectionImg.getParent() != null) {
|
||||
selectionImg.getParent().removeActor(selectionImg);
|
||||
}
|
||||
this.selectedItem = menuItem;
|
||||
|
||||
float extraSize = 7f;
|
||||
float halfExtraSize = extraSize * 0.5f;
|
||||
@@ -73,18 +77,21 @@ public class MenuView extends View<MenuViewModel> {
|
||||
contentTable.padBottom(20.0f);
|
||||
|
||||
TextButton textButton = new TextButton("Start Game", skin);
|
||||
textButton.setName("startGameBtn");
|
||||
textButton.setName(MenuOption.START_GAME.name());
|
||||
onClick(textButton, viewModel::startGame);
|
||||
onEnter(textButton, this::selectMenuItem);
|
||||
contentTable.add(textButton).row();
|
||||
|
||||
Slider musicSlider = setupVolumeSlider(contentTable, "Music Volume", viewModel.getMusicVolume());
|
||||
Slider musicSlider = setupVolumeSlider(contentTable, "Music Volume", MenuOption.MUSIC_VOLUME);
|
||||
musicSlider.setValue(viewModel.getMusicVolume());
|
||||
onChange(musicSlider, (slider) -> viewModel.setMusicVolume(slider.getValue()));
|
||||
|
||||
Slider soundSlider = setupVolumeSlider(contentTable, "Sound Volume", viewModel.getSoundVolume());
|
||||
Slider soundSlider = setupVolumeSlider(contentTable, "Sound Volume", MenuOption.SOUND_VOLUME);
|
||||
soundSlider.setValue(viewModel.getSoundVolume());
|
||||
onChange(soundSlider, (slider) -> viewModel.setSoundVolume(slider.getValue()));
|
||||
|
||||
textButton = new TextButton("Quit Game", skin);
|
||||
textButton.setName(MenuOption.QUIT_GAME.name());
|
||||
onClick(textButton, viewModel::quitGame);
|
||||
onEnter(textButton, this::selectMenuItem);
|
||||
contentTable.add(textButton).padTop(10.0f);
|
||||
@@ -92,18 +99,82 @@ public class MenuView extends View<MenuViewModel> {
|
||||
add(contentTable).align(Align.top).expandY().padTop(20f).row();
|
||||
}
|
||||
|
||||
private Slider setupVolumeSlider(Table contentTable, String title, float initialValue) {
|
||||
private Slider setupVolumeSlider(Table contentTable, String title, MenuOption menuOption) {
|
||||
Table table = new Table();
|
||||
table.setName(menuOption.name());
|
||||
Label label = new Label(title, skin);
|
||||
label.setColor(skin.getColor("sand"));
|
||||
table.add(label).row();
|
||||
|
||||
Slider slider = new Slider(0.0f, 1f, 0.05f, false, skin);
|
||||
slider.setValue(initialValue);
|
||||
table.add(slider);
|
||||
contentTable.add(table).padTop(10.0f).row();
|
||||
|
||||
onEnter(table, this::selectMenuItem);
|
||||
return slider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDown() {
|
||||
Group menuContentTable = this.selectedItem.getParent();
|
||||
int currentIdx = menuContentTable.getChildren().indexOf(this.selectedItem, true);
|
||||
if (currentIdx == -1) {
|
||||
throw new GdxRuntimeException("'selectedItem' is not a child of 'menuContentTable'");
|
||||
}
|
||||
|
||||
int numOptions = menuContentTable.getChildren().size;
|
||||
currentIdx = (currentIdx + 1) % numOptions;
|
||||
selectMenuItem((Group) menuContentTable.getChild(currentIdx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUp() {
|
||||
Group menuContentTable = this.selectedItem.getParent();
|
||||
int currentIdx = menuContentTable.getChildren().indexOf(this.selectedItem, true);
|
||||
if (currentIdx == -1) {
|
||||
throw new GdxRuntimeException("'selectedItem' is not a child of 'menuContentTable'");
|
||||
}
|
||||
|
||||
int numOptions = menuContentTable.getChildren().size;
|
||||
currentIdx = currentIdx == 0 ? numOptions - 1 : currentIdx - 1;
|
||||
selectMenuItem((Group) menuContentTable.getChild(currentIdx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRight() {
|
||||
MenuOption menuOption = MenuOption.valueOf(this.selectedItem.getName());
|
||||
switch (menuOption) {
|
||||
case MUSIC_VOLUME, SOUND_VOLUME -> {
|
||||
Slider slider = (Slider) this.selectedItem.getChild(1);
|
||||
slider.setValue(slider.getValue() + slider.getStepSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeft() {
|
||||
MenuOption menuOption = MenuOption.valueOf(this.selectedItem.getName());
|
||||
switch (menuOption) {
|
||||
case MUSIC_VOLUME, SOUND_VOLUME -> {
|
||||
Slider slider = (Slider) this.selectedItem.getChild(1);
|
||||
slider.setValue(slider.getValue() - slider.getStepSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelect() {
|
||||
MenuOption menuOption = MenuOption.valueOf(this.selectedItem.getName());
|
||||
switch (menuOption) {
|
||||
case START_GAME -> viewModel.startGame();
|
||||
case QUIT_GAME -> viewModel.quitGame();
|
||||
}
|
||||
}
|
||||
|
||||
private enum MenuOption {
|
||||
START_GAME,
|
||||
MUSIC_VOLUME,
|
||||
SOUND_VOLUME,
|
||||
QUIT_GAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.github.com.quillraven.ui.view;
|
||||
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||
import com.badlogic.gdx.scenes.scene2d.Event;
|
||||
import com.badlogic.gdx.scenes.scene2d.EventListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
@@ -8,9 +10,10 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import io.github.com.quillraven.input.UiEvent;
|
||||
import io.github.com.quillraven.ui.model.ViewModel;
|
||||
|
||||
public abstract class View<T extends ViewModel> extends Table {
|
||||
public abstract class View<T extends ViewModel> extends Table implements EventListener {
|
||||
|
||||
protected final Stage stage;
|
||||
protected final Skin skin;
|
||||
@@ -21,11 +24,43 @@ public abstract class View<T extends ViewModel> extends Table {
|
||||
this.stage = stage;
|
||||
this.skin = skin;
|
||||
this.viewModel = viewModel;
|
||||
this.stage.addListener(this);
|
||||
setupUI();
|
||||
}
|
||||
|
||||
protected abstract void setupUI();
|
||||
|
||||
public void onLeft() {
|
||||
}
|
||||
|
||||
public void onRight() {
|
||||
}
|
||||
|
||||
public void onUp() {
|
||||
}
|
||||
|
||||
public void onDown() {
|
||||
}
|
||||
|
||||
public void onSelect() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Event event) {
|
||||
if (event instanceof UiEvent uiEvent) {
|
||||
switch (uiEvent.getCommand()) {
|
||||
case LEFT -> onLeft();
|
||||
case RIGHT -> onRight();
|
||||
case UP -> onUp();
|
||||
case DOWN -> onDown();
|
||||
case SELECT -> onSelect();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void onClick(Actor actor, OnEventConsumer consumer) {
|
||||
actor.addListener(new ClickListener() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user