diff --git a/frontend/assets/menu-textures.atlas b/frontend/assets/menu-textures.atlas index 23a3c9761a3a5be2727d2350d4129568ff94eac6..046381c0b71c99f89d48c22fd37f0195871832d0 100644 --- a/frontend/assets/menu-textures.atlas +++ b/frontend/assets/menu-textures.atlas @@ -18,6 +18,13 @@ camo-background-portrait orig: 224, 500 offset: 0, 0 index: -1 +dark-back-arrow-button + rotate: false + xy: 644, 900 + size: 38, 38 + orig: 38, 38 + offset: 0, 0 + index: -1 dark-menu-header rotate: false xy: 228, 433 @@ -27,35 +34,42 @@ dark-menu-header index: -1 dark-rounded-button rotate: false - xy: 228, 397 + xy: 644, 940 size: 246, 34 orig: 246, 34 offset: 0, 0 index: -1 +dark-rounded-button-disabled + rotate: false + xy: 644, 976 + size: 275, 34 + orig: 275, 34 + offset: 0, 0 + index: -1 dark-rounded-button-down rotate: false - xy: 644, 927 + xy: 228, 348 size: 246, 34 orig: 246, 34 offset: 0, 0 index: -1 dark-stroked-input-field rotate: false - xy: 644, 963 + xy: 228, 384 size: 261, 47 orig: 261, 47 offset: 0, 0 index: -1 logo rotate: false - xy: 228, 355 + xy: 491, 391 size: 134, 40 orig: 134, 40 offset: 0, 0 index: -1 transparent-white-box rotate: false - xy: 907, 1009 + xy: 921, 1009 size: 1, 1 orig: 1, 1 offset: 0, 0 diff --git a/frontend/assets/menu-textures.json b/frontend/assets/menu-textures.json index ddbe9ce72cb5b7182dbce2ffdba695da6257277c..35087d42754f7b4c5434cb0c7567aa3f66b0c627 100644 --- a/frontend/assets/menu-textures.json +++ b/frontend/assets/menu-textures.json @@ -32,7 +32,13 @@ "font": "default", "fontColor": "white", "up": "dark-rounded-button", - "down": "dark-rounded-button-down" + "down": "dark-rounded-button-down", + "disabled": "dark-rounded-button-disabled" + } + }, + "com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle": { + "default": { + "up": "dark-back-arrow-button" } }, "com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle": { diff --git a/frontend/assets/menu-textures.png b/frontend/assets/menu-textures.png index c5ba22ba5b4830efdc5441dd056fd6dac89a2b3a..6b223eced211d505301197211b096bcdbc94a6c7 100644 Binary files a/frontend/assets/menu-textures.png and b/frontend/assets/menu-textures.png differ diff --git a/frontend/core/src/com/game/tankwars/controller/FindGameController.java b/frontend/core/src/com/game/tankwars/controller/FindGameController.java new file mode 100644 index 0000000000000000000000000000000000000000..4730e36abefc93d7700358d63f8bf5f9329b9a4d --- /dev/null +++ b/frontend/core/src/com/game/tankwars/controller/FindGameController.java @@ -0,0 +1,126 @@ +package com.game.tankwars.controller; + +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Button; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.ui.TextField; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.game.tankwars.ResourceManager; +import com.game.tankwars.TankWarsGame; +import com.game.tankwars.view.GameScreen; +import com.game.tankwars.view.MainMenuScreen; + +public class FindGameController { + + private final TankWarsGame tankWarsGame; + private final Stage stage; + private final TextField gamePinField; + private final TextButton joinLobbyButton, createLobbyButton; + private final Button backButton; + + /** + * Sets the event listeners of the buttons and the text field of the FindGameScreen, + * and allows for transitioning to MainMenuScreen and to GameScreen. + */ + public FindGameController(final TankWarsGame tankWarsGame, + TextField gamePinField, TextButton joinLobbyButton, + TextButton createLobbyButton, Button backButton, final Stage stage) { + this.tankWarsGame = tankWarsGame; + this.gamePinField = gamePinField; + this.joinLobbyButton = joinLobbyButton; + this.createLobbyButton = createLobbyButton; + this.backButton = backButton; + this.stage = stage; + + setEventListeners(); + } + + public void setEventListeners() { + + /* + * Transitions back to MainMenuScreen + */ + backButton.addListener(new InputListener() { + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + tankWarsGame.setScreen(new MainMenuScreen(tankWarsGame)); + return true; + } + }); + + /* + * Filters text field input: + * Max 4 characters long and only digits + */ + gamePinField.setTextFieldFilter(new TextField.TextFieldFilter() { + @Override + public boolean acceptChar(TextField textField, char c) { + return textField.getText().length() < 4 && Character.isDigit(c); + } + }); + + /* + * Enables the joinLobbyButton when the gamePinField contains 4 digits, + * and disables it otherwise + */ + gamePinField.addListener(new InputListener() { + @Override + public boolean keyTyped(InputEvent event, char character) { + super.keyTyped(event, character); + + if (event.getKeyCode() == 66) { + gamePinField.getOnscreenKeyboard().show(false); + stage.unfocus(gamePinField); + stage.getViewport().setScreenY(0); + stage.getViewport().apply(); + } + + joinLobbyButton.setDisabled(gamePinField.getText().length() != 4); + + return true; + } + }); + + /* + * Move camera down when text field is clicked + * to make the field appear above the keyboard. + */ + gamePinField.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + super.clicked(event, x, y); + stage.getViewport().setScreenY((int) (2 * stage.getHeight() / 3)); + stage.getViewport().apply(); + } + }); + + /* + * Disables input listener when the button is disabled. + * TODO: Join a lobby by sending a request to the backend + */ + joinLobbyButton.addListener(new InputListener() { + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + if (joinLobbyButton.isDisabled()) return true; + + System.out.println("Game pin: " + gamePinField.getText() + " - yet to be implemented"); + return true; + } + }); + + /* + * TODO: Create a lobby by sending request to backend - Transition to waiting screen? + */ + createLobbyButton.addListener(new InputListener() { + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + ResourceManager.getInstance().clear(); + tankWarsGame.setScreen(new GameScreen(tankWarsGame)); + return true; + } + }); + } + +} diff --git a/frontend/core/src/com/game/tankwars/controller/LoginController.java b/frontend/core/src/com/game/tankwars/controller/LoginController.java index c3c4d57121c90df1b155dc5d781bdcb0c36ea9c9..04847b93f16538f9822af88c36c00514e00fc460 100644 --- a/frontend/core/src/com/game/tankwars/controller/LoginController.java +++ b/frontend/core/src/com/game/tankwars/controller/LoginController.java @@ -21,8 +21,6 @@ import com.game.tankwars.view.MainMenuScreen; /** - * Todo: Login user on backend - * * Listens to the login button on the LoginScreen and logs in * the user with the username provided in the username text field. * Transitions to MainMenuScreen on login. diff --git a/frontend/core/src/com/game/tankwars/controller/MainMenuController.java b/frontend/core/src/com/game/tankwars/controller/MainMenuController.java index 38d14ea44e9a39069d7abf17d4ab51fd13562f1c..53177ca3ba93e28060b6da80f0e4c8cb3b6c8532 100644 --- a/frontend/core/src/com/game/tankwars/controller/MainMenuController.java +++ b/frontend/core/src/com/game/tankwars/controller/MainMenuController.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.game.tankwars.ResourceManager; import com.game.tankwars.TankWarsGame; +import com.game.tankwars.view.FindGameScreen; import com.game.tankwars.view.GameScreen; import com.game.tankwars.view.LeaderboardScreen; import com.game.tankwars.view.LoginScreen; @@ -32,15 +33,12 @@ public class MainMenuController { private void setEventListeners() { /* - * Transition to GameScreen - * Clear Resource Manager to dispose all menu-related textures - * TODO: Transition to FindGameScreen and then no longer clear ResourceManager + * Transition to FindGameScreen */ findGameButton.addListener(new InputListener() { @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { - ResourceManager.getInstance().clear(); - tankWarsGame.setScreen(new GameScreen(tankWarsGame)); + tankWarsGame.setScreen(new FindGameScreen(tankWarsGame)); return true; } }); diff --git a/frontend/core/src/com/game/tankwars/view/FindGameScreen.java b/frontend/core/src/com/game/tankwars/view/FindGameScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..3c4f4885e950c37fe2f3687069b30765da3052ce --- /dev/null +++ b/frontend/core/src/com/game/tankwars/view/FindGameScreen.java @@ -0,0 +1,136 @@ +package com.game.tankwars.view; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.scenes.scene2d.Group; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Button; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +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.ui.TextField; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.ScreenUtils; +import com.badlogic.gdx.utils.viewport.ExtendViewport; +import com.game.tankwars.ResourceManager; +import com.game.tankwars.TankWarsGame; +import com.game.tankwars.controller.FindGameController; + +/** + * Screen where the user can choose between creating a new game lobby + * and join an existing lobby by entering a game pin. + */ +public class FindGameScreen implements Screen { + + private final TankWarsGame tankWarsGame; + private Stage stage; + + public FindGameScreen(final TankWarsGame tankWarsGame) { + this.tankWarsGame = tankWarsGame; + } + + @Override + public void show() { + stage = new Stage(new ExtendViewport(tankWarsGame.getViewportWidth(), + tankWarsGame.getViewportHeight()), new SpriteBatch()); + Gdx.input.setInputProcessor(stage); + + Skin skin = ResourceManager.getInstance().loadAndGetMenuAssets(); + + Image backgroundPortrait = new Image(skin.getDrawable("camo-background-portrait")); + Drawable backgroundBlurred = skin.getDrawable("camo-background-portrait-blurred"); + Image logo = new Image(skin.getDrawable("logo")); + Drawable headerBox = skin.getDrawable("dark-menu-header"); + + Label findGameLabel = new Label("Find Game", skin.get("header", Label.LabelStyle.class)); + Label gamePinLabel = new Label("Game pin", skin.get("default", Label.LabelStyle.class)); + + TextField gamePinField = new TextField("", + skin.get("default", TextField.TextFieldStyle.class)); + gamePinField.setAlignment(Align.center); + + TextButton joinLobbyButton = new TextButton("Join lobby", + skin.get("default", TextButton.TextButtonStyle.class)); + joinLobbyButton.setDisabled(true); + TextButton createLobbyButton = new TextButton("Create lobby", + skin.get("default", TextButton.TextButtonStyle.class)); + Button backButton = new Button(skin.get("default", Button.ButtonStyle.class)); + + //--- Layout + float lw = 2 * stage.getWidth() / 6f; + float rw = stage.getWidth() - lw; + + Table rootTable = new Table(); + rootTable.setFillParent(true); + + Group leftGroup = new Group(); + leftGroup.setSize(lw, stage.getHeight()); + backgroundPortrait.setSize(lw, backgroundPortrait.getHeight() / backgroundPortrait.getWidth() * lw); + backgroundPortrait.setPosition(0, stage.getHeight() / 2f - backgroundPortrait.getHeight() / 2f); + leftGroup.addActor(backgroundPortrait); + backButton.setPosition(14, stage.getHeight() - backButton.getHeight() - 14); + leftGroup.addActor(backButton); + + Table rightTable = new Table(); + rightTable.background(backgroundBlurred); + + Table headerTable = new Table(); + headerTable.background(headerBox); + headerTable.add(logo).expandX().width(3 * rw / 7f). + height(logo.getHeight() / logo.getWidth() * 3 * rw / 7f); + headerTable.add(findGameLabel).expandX(); + + rightTable.add(headerTable).fillX().height(stage.getHeight() / 4f); + rightTable.row().expand(1, 0); + rightTable.add(gamePinLabel).width(2 * rw / 3f).bottom().padLeft(10); + rightTable.row().expand(1, 2); + rightTable.add(gamePinField).width(2 * rw / 3f).height(42).top(); + rightTable.row().expand(1, 1); + rightTable.add(joinLobbyButton).width(2 * rw / 3f).height(28); + rightTable.row().expand(1, 4); + rightTable.add(createLobbyButton).width(2 * rw / 3f).height(28); + + rootTable.add(leftGroup).width(lw).height(stage.getHeight()); + rootTable.add(rightTable).expandX().height(stage.getHeight()); + stage.addActor(rootTable); + + new FindGameController(tankWarsGame, gamePinField, joinLobbyButton, createLobbyButton, backButton, stage); + } + + @Override + public void render(float delta) { + ScreenUtils.clear(0, 0, 0, 1f); + + stage.act(delta); + stage.draw(); + } + + @Override + public void resize(int width, int height) { + stage.getViewport().update(width, height); + } + + @Override + public void pause() { + + } + + @Override + public void resume() { + + } + + @Override + public void hide() { + Gdx.input.setInputProcessor(null); + } + + @Override + public void dispose() { + stage.dispose(); + } +} diff --git a/frontend/core/src/com/game/tankwars/view/LoginScreen.java b/frontend/core/src/com/game/tankwars/view/LoginScreen.java index d59d545b072b57f19e517cce5d29b0134e440306..9e7be8adb155f2235d5b018904ff00a2cfd76a07 100644 --- a/frontend/core/src/com/game/tankwars/view/LoginScreen.java +++ b/frontend/core/src/com/game/tankwars/view/LoginScreen.java @@ -56,7 +56,7 @@ public class LoginScreen implements Screen { skin.get("default", TextButton.TextButtonStyle.class)); //--- Layout - float lw = 2 * stage.getWidth() / 5f; + float lw = 2 * stage.getWidth() / 6f; float rw = stage.getWidth() - lw; Table rootTable = new Table(); diff --git a/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java b/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java index 08bdda59b6053737b193c24e98d39291c0fc0b03..768a7ecd4f68e0ea4077405362d6d8577a8ebe65 100644 --- a/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java +++ b/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; @@ -42,7 +43,7 @@ public class MainMenuScreen extends InputAdapter implements Screen { Skin skin = ResourceManager.getInstance().loadAndGetMenuAssets(); - Drawable background = skin.getDrawable("camo-background-landscape"); + Image background = new Image(skin.getDrawable("camo-background-landscape")); Image logo = new Image(skin.getDrawable("logo")); Drawable headerBox = skin.getDrawable("dark-menu-header"); @@ -82,12 +83,18 @@ public class MainMenuScreen extends InputAdapter implements Screen { panelTable.add(settingsButton).width(buttonWidth).expandX().height(buttonHeight); panelTable.add(logoutButton).width(buttonWidth).expandX().height(buttonHeight); - rootTable.background(background); rootTable.add(headerTable).fillX().height(2 * stage.getHeight() / 7f).top(); rootTable.row().expandY(); rootTable.add(panelTable).fillX().height(3 * stage.getHeight() / 7f).bottom(); - stage.addActor(rootTable); + Group group = new Group(); + group.setSize(stage.getWidth(), stage.getHeight()); + background.setSize(stage.getWidth(), background.getHeight() / background.getWidth() * stage.getWidth()); + background.setPosition(0, stage.getHeight() / 2f - background.getHeight() / 2f); + group.addActor(background); + group.addActor(rootTable); + + stage.addActor(group); new MainMenuController(this.tankWarsGame, findGameButton, highScoreButton, settingsButton, logoutButton); }