Skip to content
Snippets Groups Projects
Commit 76341434 authored by Sander Østrem Fagernes's avatar Sander Østrem Fagernes Committed by Jan Einar Thorvaldsen
Browse files

Resolve "Refactor main menu with scene2d"

parent c6946a27
No related branches found
No related tags found
1 merge request!29Resolve "Refactor main menu with scene2d"
......@@ -18,7 +18,7 @@
<activity
android:name="com.game.tankwars.AndroidLauncher"
android:label="@string/app_name"
android:screenOrientation="fullSensor"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize|screenLayout"
android:exported="true">
<intent-filter>
......
......@@ -53,6 +53,13 @@ logo
orig: 134, 40
offset: 0, 0
index: -1
transparent-white-box
rotate: false
xy: 907, 1009
size: 1, 1
orig: 1, 1
offset: 0, 0
index: -1
typing-cursor
rotate: false
xy: 2, 2
......
frontend/assets/menu-textures.png

48.6 KiB | W: | H:

frontend/assets/menu-textures.png

48.7 KiB | W: | H:

frontend/assets/menu-textures.png
frontend/assets/menu-textures.png
frontend/assets/menu-textures.png
frontend/assets/menu-textures.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -3,46 +3,16 @@
*/
package com.game.tankwars;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.game.tankwars.model.Box2dWorld;
import com.game.tankwars.model.Bullet;
import com.game.tankwars.model.Tank;
import com.game.tankwars.view.LoginScreen;
import com.game.tankwars.view.MainMenuScreen;
public class TankWarsGame extends Game {
public static int VIEWPORT_WIDTH = 80;
public static int VIEWPORT_HEIGHT = 50;
private SpriteBatch batch;
private BitmapFont font;
public static int VIEWPORT_WIDTH = 320;
public static int VIEWPORT_HEIGHT = 240;
@Override
public void create() {
batch = new SpriteBatch();
font = new BitmapFont();
this.setScreen(new LoginScreen(this));
}
......@@ -62,7 +32,5 @@ public class TankWarsGame extends Game {
@Override
public void dispose () {
ResourceManager.getInstance().dispose();
batch.dispose();
font.dispose();
}
}
......@@ -6,9 +6,8 @@ import com.badlogic.gdx.scenes.scene2d.Stage;
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;
/**
* Todo: Login user on backend
......@@ -24,7 +23,7 @@ public class LoginController {
private final TextButton loginButton;
private final TextField usernameField;
public LoginController(final TankWarsGame tankWarsGame, final TextButton loginButton, final TextField usernameField, final Stage stage) {
public LoginController(final TankWarsGame tankWarsGame, TextButton loginButton, TextField usernameField, Stage stage) {
this.tankWarsGame = tankWarsGame;
this.loginButton = loginButton;
this.usernameField = usernameField;
......@@ -34,6 +33,10 @@ public class LoginController {
}
public void setEventListeners() {
/*
* Calls the handleInput method when the login button is pressed,
* passing the username typed in the username field as an argument.
*/
loginButton.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
......@@ -42,11 +45,11 @@ public class LoginController {
}
});
/*
* Unfocus text field and remove keyboard when enter is pressed,
* and move camera back to original position.
*/
usernameField.addListener(new InputListener() {
/**
* Unfocus text field and remove keyboard when enter is pressed,
* and move camera back to original position.
*/
@Override
public boolean keyDown(InputEvent event, int keycode) {
super.keyDown(event, keycode);
......@@ -60,11 +63,11 @@ public class LoginController {
}
});
/*
* Move camera down when text field is clicked
* to make the field appear above the keyboard.
*/
usernameField.addListener(new ClickListener() {
/**
* Move camera down when text field is clicked
* to make the field appear above the keyboard.
*/
@Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
......@@ -77,9 +80,7 @@ public class LoginController {
public void handleInput(String username) {
System.out.println(username);
// TODO: Move clear line to MainMenuController when the main menu is operational
ResourceManager.getInstance().clear();
tankWarsGame.setScreen(new GameScreen(tankWarsGame));
tankWarsGame.setScreen(new MainMenuScreen(tankWarsGame));
}
}
package com.game.tankwars.controller;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
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.model.MenuButton;
import com.game.tankwars.view.GameScreen;
import com.game.tankwars.view.LeaderboardScreen;
import com.game.tankwars.view.LoginScreen;
/**
* Sets the event listeners for the buttons
* on the MainMenuScreen
*/
public class MainMenuController {
private final TankWarsGame tankWarsGame;
private String username;
private final Array<MenuButton> menuButtons;
private final TextButton findGameButton, highScoreButton, settingsButton, logoutButton;
public MainMenuController(final TankWarsGame tankWarsGame, final BitmapFont font) {
public MainMenuController(final TankWarsGame tankWarsGame, TextButton findGameButton,
TextButton highScoreButton, TextButton settingsButton,
TextButton logoutButton) {
this.tankWarsGame = tankWarsGame;
this.findGameButton = findGameButton;
this.highScoreButton = highScoreButton;
this.settingsButton = settingsButton;
this.logoutButton = logoutButton;
fetchUser();
this.menuButtons = new Array<>();
}
public Array<MenuButton> setMenuButtons(Texture buttonTexture, BitmapFont font) {
this.menuButtons.add(new MenuButton(buttonTexture, font, "Find Game"));
this.menuButtons.add(new MenuButton(buttonTexture, font, "Leaderboard"));
this.menuButtons.add(new MenuButton(buttonTexture, font, "Settings"));
this.menuButtons.add(new MenuButton(buttonTexture, font, "Log out"));
return menuButtons;
setEventListeners();
}
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
*/
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));
return true;
}
});
public void handleInput(Vector3 touchPos) {
for (int i = 0; i < menuButtons.size; i++) {
MenuButton menuButton = menuButtons.get(i);
if (touchPos.x >= menuButton.getX() && touchPos.x <= menuButton.getX() + menuButton.getWidth() &&
touchPos.y >= menuButton.getY() && touchPos.y <= menuButton.getY() + menuButton.getHeight()) {
switch (i) {
case 0: tankWarsGame.setScreen(new GameScreen(tankWarsGame)); break;
case 1: tankWarsGame.setScreen(new LeaderboardScreen(tankWarsGame)); break;
case 2: System.out.println("Settings button: Not yet functional"); break;
case 3: System.out.println("Log out button: Not yet functional"); break;
}
/*
* Transition to LeaderboardScreen
*/
highScoreButton.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
tankWarsGame.setScreen(new LeaderboardScreen(tankWarsGame));
return true;
}
}
}
});
/**
* TODO: Fetch user from backend. For now it only creates a dummy username to pass to the screen
*/
private void fetchUser() {
this.username = "Commander";
}
/*
* Transition to SettingsScreen (Dummy button for now)
* TODO: Implement the SettingsScreen class and add the transition
*/
settingsButton.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Settings screen: yet to be implemented");
return true;
}
});
public String getUsername() {
return username;
/*
* Transition to LoginScreen
* Log out the user
* TODO: Log out the user - must be done after login functionality is implemented
*/
logoutButton.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
tankWarsGame.setScreen(new LoginScreen(tankWarsGame));
return true;
}
});
}
}
......@@ -2,25 +2,15 @@ package com.game.tankwars.view;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Event;
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.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.Image;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.Value;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.FocusListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
......@@ -37,7 +27,6 @@ import com.game.tankwars.controller.LoginController;
public class LoginScreen implements Screen {
private final TankWarsGame tankWarsGame;
private Stage stage;
private TextField usernameField;
public LoginScreen(final TankWarsGame tankWarsGame) {
this.tankWarsGame = tankWarsGame;
......@@ -45,7 +34,7 @@ public class LoginScreen implements Screen {
@Override
public void show() {
stage = new Stage(new ExtendViewport(320, 240), new SpriteBatch());
stage = new Stage(new ExtendViewport(tankWarsGame.getViewportWidth(), tankWarsGame.getViewportHeight()), new SpriteBatch());
Gdx.input.setInputProcessor(stage);
Skin skin = ResourceManager.getInstance().loadAndGetMenuAssets();
......@@ -60,7 +49,7 @@ public class LoginScreen implements Screen {
Label loginLabel = new Label("Log in", skin.get("header", Label.LabelStyle.class));
Label usernameLabel = new Label("Username", skin.get("default", Label.LabelStyle.class));
usernameField = new TextField("",
TextField usernameField = new TextField("",
skin.get("default", TextField.TextFieldStyle.class));
usernameField.setAlignment(Align.center);
TextButton loginButton = new TextButton("Log in",
......@@ -126,6 +115,7 @@ public class LoginScreen implements Screen {
@Override
public void hide() {
Gdx.input.setInputProcessor(null);
dispose();
}
......
......@@ -3,116 +3,105 @@ package com.game.tankwars.view;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
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.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.game.tankwars.ResourceManager;
import com.game.tankwars.TankWarsGame;
import com.game.tankwars.controller.MainMenuController;
import com.game.tankwars.model.MenuButton;
/**
* Main menu screen with buttons leading to the different screens in the application.
*
* The following transitions from the buttons are supported by the MainMenuController:
* Find game button transitions to GameScreen
* Highscore button transitions to LeaderboardScreen
* Settings button transitions to no screen as of now
* Log out button transitions to log in screen
*/
public class MainMenuScreen extends InputAdapter implements Screen {
private final TankWarsGame tankWarsGame;
private final SpriteBatch batch;
private final BitmapFont font;
private final Viewport viewport;
private final MainMenuController controller;
private final Sprite logo;
private final Texture welcomeBox;
private final Texture background;
private final Texture menuButtonTexture;
private final GlyphLayout welcomeLayout, usernameLayout;
private final Array<MenuButton> menuButtons;
private final Vector3 touchPos;
private float heightPercentile;
/**
* Main menu
* Only supports portrait mode
*/
public MainMenuScreen(final TankWarsGame tankWarsGame, final SpriteBatch batch, final BitmapFont font, final OrthographicCamera camera) {
this.tankWarsGame = tankWarsGame;
this.batch = batch;
this.font = font;
this.font.getData().setScale(0.55f);
// TODO: Add landscape support, both on startup and on rotation
viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);
heightPercentile = viewport.getWorldHeight() / 100;
controller = new MainMenuController(this.tankWarsGame, this.font);
logo = new Sprite(new Texture("tankwars-logo.png"));
logo.setScale(1.3f);
logo.setPosition(-logo.getWidth() / 2, 32 * heightPercentile);
welcomeBox = new Texture("main-menu-welcome-box.png");
welcomeLayout = new GlyphLayout(font, "Welcome to duty");
usernameLayout = new GlyphLayout(font, controller.getUsername());
private Stage stage;
background = new Texture("menu-background.png");
menuButtonTexture = new Texture("menu-button-2.png");
menuButtons = controller.setMenuButtons(menuButtonTexture, font);
for (int i = 0; i < menuButtons.size; i++) {
menuButtons.get(i).setPosition(0, -(12 * i - 4) * heightPercentile);
}
touchPos = new Vector3();
public MainMenuScreen(final TankWarsGame tankWarsGame) {
this.tankWarsGame = tankWarsGame;
}
@Override
public void show() {
Gdx.input.setInputProcessor(this);
stage = new Stage(new ExtendViewport(tankWarsGame.getViewportWidth(), tankWarsGame.getViewportHeight()), new SpriteBatch());
Gdx.input.setInputProcessor(stage);
Skin skin = ResourceManager.getInstance().loadAndGetMenuAssets();
Drawable background = skin.getDrawable("camo-background-landscape");
Image logo = new Image(skin.getDrawable("logo"));
Drawable headerBox = skin.getDrawable("dark-menu-header");
Label loginLabel = new Label("Main Menu", skin.get("header", Label.LabelStyle.class));
Drawable panelBackground = skin.getDrawable("transparent-white-box");
TextButton findGameButton = new TextButton("Find game",
skin.get("default", TextButton.TextButtonStyle.class));
TextButton highScoreButton = new TextButton("Highscore",
skin.get("default", TextButton.TextButtonStyle.class));
TextButton settingsButton = new TextButton("Settings",
skin.get("default", TextButton.TextButtonStyle.class));
TextButton logoutButton = new TextButton("Log out",
skin.get("default", TextButton.TextButtonStyle.class));
//--- Layout
Table rootTable = new Table();
rootTable.setFillParent(true);
float logoWidth = stage.getWidth() / 4f;
Table headerTable = new Table();
headerTable.background(headerBox);
headerTable.add(logo).width(logoWidth).
height(logo.getHeight() / logo.getWidth() * logoWidth).expandX();
headerTable.add(loginLabel).expandX();
float buttonWidth = 3 * stage.getWidth() / 7f;
float buttonHeight = 32;
Table panelTable = new Table();
panelTable.background(panelBackground);
panelTable.row().expandY();
panelTable.add(findGameButton).width(buttonWidth).expandX().height(buttonHeight);
panelTable.add(highScoreButton).width(buttonWidth).expandX().height(buttonHeight);
panelTable.row().expandY();
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);
new MainMenuController(this.tankWarsGame, findGameButton, highScoreButton, settingsButton, logoutButton);
}
@Override
public void render(float delta) {
ScreenUtils.clear(0, 0, 0, 1);
batch.setProjectionMatrix(viewport.getCamera().combined);
batch.begin();
batch.draw(background, -background.getWidth() / 2f, -background.getHeight() / 2f);
logo.draw(batch);
batch.draw(welcomeBox, -welcomeBox.getWidth() / 2f, 12 * heightPercentile,
viewport.getWorldWidth(), welcomeBox.getHeight());
font.draw(batch, welcomeLayout, -welcomeLayout.width / 2,
12 * heightPercentile + welcomeBox.getHeight() * 4f/5f);
font.draw(batch, usernameLayout, -usernameLayout.width / 2,
12 * heightPercentile + welcomeBox.getHeight() * 4f/5f - 2 * welcomeLayout.height);
for (MenuButton menuButton : menuButtons) {
batch.draw(menuButton.getTexture(), menuButton.getX(), menuButton.getY());
font.draw(batch, menuButton.getContent(), menuButton.getContentX(), menuButton.getContentY());
}
batch.end();
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
touchPos.set(screenX, screenY, 0);
viewport.unproject(touchPos);
controller.handleInput(touchPos);
return true;
stage.act(delta);
stage.draw();
}
@Override
public void resize(int width, int height) {
viewport.update(width, height);
heightPercentile = viewport.getWorldHeight() / 100;
stage.getViewport().update(width, height);
}
@Override
......@@ -128,13 +117,11 @@ public class MainMenuScreen extends InputAdapter implements Screen {
@Override
public void hide() {
Gdx.input.setInputProcessor(null);
dispose();
}
@Override
public void dispose() {
logo.getTexture().dispose();
welcomeBox.dispose();
background.dispose();
menuButtonTexture.dispose();
stage.dispose();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment