diff --git a/backend/src/index.ts b/backend/src/index.ts index 439a97f5c8047ba04e5539588ff51175f8f95773..fc2b951f4475ee2833fcf9a04a9694f78d0664bf 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -74,10 +74,16 @@ app.get('/user/:idOrUsername', async (req, res) => { // create new user app.post('/user/create/:username', async (req, res) => { const usersRef = admin.firestore().collection('users'); - const querySnapshot = await usersRef.where('username', '==', req.params.username).get(); + const username = req.params.username; + const querySnapshot = await usersRef.where('username', '==', username).get(); if (!querySnapshot.empty) { - res.status(409).send('User already exists'); + const user: User[] = querySnapshot.docs.map((doc: any) => { + if (doc.data().username === username) { + return { id: doc.id, ...doc.data() }; + } + }); + res.status(409).send(user[0]); } else { const newUserRef = await usersRef.add({ username: req.params.username, @@ -86,7 +92,14 @@ app.post('/user/create/:username', async (req, res) => { wins: 0, losses: 0, }); - res.status(201).send(newUserRef.id); + res.status(201).send({ + username: req.params.username, + highscore: 0, + games: 0, + wins: 0, + losses: 0, + id: newUserRef.id, + } as User); } }); @@ -98,10 +111,13 @@ app.get('/highscores', async (req, res) => { if (querySnapshot.empty) { res.status(204).send('No highscores found'); } else { - const users = querySnapshot.docs.map((doc: any) => ({ - id: doc.id, - ...doc.data(), - })); + const users = querySnapshot.docs.map( + (doc: any) => + ({ + id: doc.id, + ...doc.data(), + } as User) + ); res.status(200).send(users); } }); diff --git a/backend/types/User.ts b/backend/types/User.ts index 7e207611346141494921b93f80a1808f0bca4bf9..fd36120d7257718d5ca36da7a411a3beca6f7feb 100644 --- a/backend/types/User.ts +++ b/backend/types/User.ts @@ -4,4 +4,5 @@ export type User = { wins: number; losses: number; highscore: number; + games: number; }; diff --git a/frontend/android/AndroidManifest.xml b/frontend/android/AndroidManifest.xml index a31d082ec1e82f0d323f663a815c40ac63b7c849..b0212e88ad8d4b29038c3f851290e49ecb34ad36 100644 --- a/frontend/android/AndroidManifest.xml +++ b/frontend/android/AndroidManifest.xml @@ -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> diff --git a/frontend/assets/menu-textures.atlas b/frontend/assets/menu-textures.atlas index eefba7954bb4313999cd11a8b3877bd43c77c9f2..23a3c9761a3a5be2727d2350d4129568ff94eac6 100644 --- a/frontend/assets/menu-textures.atlas +++ b/frontend/assets/menu-textures.atlas @@ -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 diff --git a/frontend/assets/menu-textures.png b/frontend/assets/menu-textures.png index 7781c29d8792adc05f5e4f081b3a5828211ed536..c5ba22ba5b4830efdc5441dd056fd6dac89a2b3a 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/ReceiverHandler.java b/frontend/core/src/com/game/tankwars/ReceiverHandler.java index e162baa86e8db900c064289c0fadbb304a44fcb0..4f16b98b91e6479f626057606e936d81817d1629 100644 --- a/frontend/core/src/com/game/tankwars/ReceiverHandler.java +++ b/frontend/core/src/com/game/tankwars/ReceiverHandler.java @@ -17,6 +17,7 @@ public class ReceiverHandler implements Net.HttpResponseListener { // Declare a Callback instance to handle the different responses private final Callback callback; + public static final int MAX_RETRIES = 5; // Constructor to initialize the Callback instance public ReceiverHandler(Callback callback) { diff --git a/frontend/core/src/com/game/tankwars/TankWarsGame.java b/frontend/core/src/com/game/tankwars/TankWarsGame.java index de102412f293fd2ec4980fa2d1cf4dece40b8320..e60522911110b9fdf610170f41b5d5de1cac4b6f 100644 --- a/frontend/core/src/com/game/tankwars/TankWarsGame.java +++ b/frontend/core/src/com/game/tankwars/TankWarsGame.java @@ -11,8 +11,8 @@ import com.game.tankwars.view.LoginScreen; public class TankWarsGame extends Game { public static final float SCALE = 10; - public static int VIEWPORT_WIDTH = 80; - public static int VIEWPORT_HEIGHT = 50; + public static int VIEWPORT_WIDTH = 320; + public static int VIEWPORT_HEIGHT = 240; public static final int GAMEPORT_WIDTH = 720; public static final int GAMEPORT_HEIGHT = 480; @@ -22,8 +22,6 @@ public class TankWarsGame extends Game { @Override public void create() { - batch = new SpriteBatch(); - font = new BitmapFont(); this.setScreen(new LoginScreen(this)); } @@ -43,7 +41,5 @@ public class TankWarsGame extends Game { @Override public void dispose () { ResourceManager.getInstance().dispose(); - batch.dispose(); - font.dispose(); } } diff --git a/frontend/core/src/com/game/tankwars/controller/GameController.java b/frontend/core/src/com/game/tankwars/controller/GameController.java index 35873e29469388e0beb4eac43122aafeaf7523b3..78b7051e1c2ca304cc7b27635e5571f066b24672 100644 --- a/frontend/core/src/com/game/tankwars/controller/GameController.java +++ b/frontend/core/src/com/game/tankwars/controller/GameController.java @@ -13,7 +13,7 @@ import com.game.tankwars.view.GameHud; public class GameController { - private TankWarsGame game; + private TankWarsGame tankWarsGame; private GameHud hud; @@ -24,13 +24,13 @@ public class GameController { private boolean moveRightTouched; private boolean moveLeftTouched; - public GameController(TankWarsGame game, GameHud hud, Tank tank) { - this.game = game; + public GameController(Tank tank, TankWarsGame tankWarsGame, GameHud hud) { this.hud = hud; this.tank = tank; + this.tankWarsGame = tankWarsGame; } - public void checkKeyInput(){ + public void checkKeyInput(Tank tank){ if(Gdx.input.isKeyPressed(Input.Keys.Q)) { tank.rotateCannonLeft(); } diff --git a/frontend/core/src/com/game/tankwars/controller/LeaderboardController.java b/frontend/core/src/com/game/tankwars/controller/LeaderboardController.java index 85becb0b976c1fb16dc86fd36df856b777235353..60750d17bf5541fffd209cce4f2e0afd6de54ced 100644 --- a/frontend/core/src/com/game/tankwars/controller/LeaderboardController.java +++ b/frontend/core/src/com/game/tankwars/controller/LeaderboardController.java @@ -18,11 +18,11 @@ public class LeaderboardController { Callback callback = new Callback() { // Method called if the response is successful @Override - public void onResult(String leaderboard) { + public void onResult(String result) { // Create a new Json instance to parse the response body Json json = new Json(); // Convert the response body to an Array of User objects using the Json instance - leaderboardUsers = json.fromJson(Array.class, User.class, leaderboard); + leaderboardUsers = json.fromJson(Array.class, User.class, result); } // Method called if the response fails @Override diff --git a/frontend/core/src/com/game/tankwars/controller/LoginController.java b/frontend/core/src/com/game/tankwars/controller/LoginController.java index 37830ddaf42c972655d0bada905645d48289f9c5..c3c4d57121c90df1b155dc5d781bdcb0c36ea9c9 100644 --- a/frontend/core/src/com/game/tankwars/controller/LoginController.java +++ b/frontend/core/src/com/game/tankwars/controller/LoginController.java @@ -1,14 +1,24 @@ package com.game.tankwars.controller; +import static com.game.tankwars.model.CurrentUser.getCurrentUser; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Net; +import com.badlogic.gdx.net.HttpRequestBuilder; 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.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.game.tankwars.ResourceManager; +import com.badlogic.gdx.utils.Json; +import com.game.tankwars.Callback; +import com.game.tankwars.ReceiverHandler; import com.game.tankwars.TankWarsGame; -import com.game.tankwars.view.GameScreen; +import com.game.tankwars.model.CurrentUser; +import com.game.tankwars.model.User; +import com.game.tankwars.view.MainMenuScreen; + /** * Todo: Login user on backend @@ -23,17 +33,24 @@ public class LoginController { private final Stage stage; private final TextButton loginButton; private final TextField usernameField; + private int retries = 0; + private boolean failed = false; + CurrentUser currentUser; - 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; this.stage = stage; - + currentUser = getCurrentUser(); setEventListeners(); } 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 +59,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 +77,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); @@ -75,11 +92,41 @@ 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)); + retries = 0; + failed = false; + fetchUser(username); + while (getCurrentUser().getUser() == null && !failed){ + } + if (!failed) + tankWarsGame.setScreen(new MainMenuScreen(tankWarsGame)); } + public void fetchUser(final String username) { + Callback callback = new Callback() { + @Override + public void onResult(String result) { + Json json = new Json(); + User user = json.fromJson(User.class, result); + currentUser.setUser(user); + } + + @Override + public void onFailed(Throwable t) { + retries += 1; + if (retries < ReceiverHandler.MAX_RETRIES) { + fetchUser(username); + } else { + failed = true; + } + } + }; + + String url = String.format("http://localhost:80/user/create/%s", username); + Net.HttpRequest httpRequest = new HttpRequestBuilder() + .newRequest() + .method(Net.HttpMethods.POST) + .url(url) + .build(); + Gdx.net.sendHttpRequest(httpRequest, new ReceiverHandler(callback)); + } } diff --git a/frontend/core/src/com/game/tankwars/controller/MainMenuController.java b/frontend/core/src/com/game/tankwars/controller/MainMenuController.java index f07836cb05399a96cf4dc90497d46a8e382615b7..38d14ea44e9a39069d7abf17d4ab51fd13562f1c 100644 --- a/frontend/core/src/com/game/tankwars/controller/MainMenuController.java +++ b/frontend/core/src/com/game/tankwars/controller/MainMenuController.java @@ -1,64 +1,84 @@ 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; + } + }); } } diff --git a/frontend/core/src/com/game/tankwars/model/CurrentUser.java b/frontend/core/src/com/game/tankwars/model/CurrentUser.java new file mode 100644 index 0000000000000000000000000000000000000000..28fbdea0085ae021127b7e76abab4d8a9cf4f942 --- /dev/null +++ b/frontend/core/src/com/game/tankwars/model/CurrentUser.java @@ -0,0 +1,28 @@ +package com.game.tankwars.model; + +public class CurrentUser { + + User user; + private static CurrentUser INSTANCE; + + private CurrentUser() { + } + + public static CurrentUser getCurrentUser(){ + if (INSTANCE == null) { + INSTANCE = new CurrentUser(); + } + return INSTANCE; + } + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } + + @Override + public String toString() { + return "CurrentUser is: " + user ; + } +} diff --git a/frontend/core/src/com/game/tankwars/model/Tank.java b/frontend/core/src/com/game/tankwars/model/Tank.java index ff84658a6925f2f7217fb04e290972f459a90d61..c961532e24efbaf7609b14c49fb4a62b0cae04a9 100644 --- a/frontend/core/src/com/game/tankwars/model/Tank.java +++ b/frontend/core/src/com/game/tankwars/model/Tank.java @@ -34,14 +34,14 @@ public class Tank { Body cannon; BodyDef bodyDef = new BodyDef(); FixtureDef fixtureDef = new FixtureDef(); - RevoluteJoint joint; Terrain terrain; private Vector2[] vertices; int posInVertArr; float cannonAngle = 90; private int power; + boolean directionLeft; - public Tank(int posInVertArr, Texture chassisTexture, Texture cannonTexture, Terrain terrain, TankWarsGame tankWarsGame) { + public Tank(int posInVertArr, Texture chassisTexture, Texture cannonTexture, Terrain terrain, TankWarsGame tankWarsGame, boolean directionLeft) { VIEWPORT_HEIGHT = tankWarsGame.getViewportHeight(); VIEWPORT_WIDTH = tankWarsGame.getViewportWidth(); @@ -84,6 +84,14 @@ public class Tank { cannon.setUserData(cannonSprite); shape.dispose(); + updateCannonPos(); + moveLeft(); + if(directionLeft){ + moveRight(); + } + else{ + moveLeft(); + } } public void moveRight() { @@ -91,6 +99,10 @@ public class Tank { Vector2 newPos = new Vector2(vertices[posInVertArr + 1]); float angle = new Vector2(newPos.x - curPos.x, newPos.y - curPos.y).angleRad(); + if(directionLeft){ + chassisSprite.flip(true, false); + directionLeft = false; + } if (chassis.getPosition().x <= VIEWPORT_WIDTH - TANK_WIDTH){ setPosition(newPos); chassis.setTransform(newPos.x, newPos.y + 0.11f, angle); @@ -108,6 +120,11 @@ public class Tank { Vector2 newPos = new Vector2(vertices[posInVertArr - 1]); float angle = new Vector2(newPos.x - curPos.x, newPos.y - curPos.y).angleRad(); + if(!directionLeft){ + chassisSprite.flip(true, false); + directionLeft = true; + } + if (chassis.getPosition().x >= TANK_WIDTH){ setPosition(newPos); chassis.setTransform(newPos.x, newPos.y + 0.11f, angle); diff --git a/frontend/core/src/com/game/tankwars/model/User.java b/frontend/core/src/com/game/tankwars/model/User.java index 9b60990981d1baf0d0f14afacd8e4143954d1981..350382411a8f1f9ca334231366ab6a9e41b35e85 100644 --- a/frontend/core/src/com/game/tankwars/model/User.java +++ b/frontend/core/src/com/game/tankwars/model/User.java @@ -8,15 +8,6 @@ public class User { public String username; public String id; - public User(int games, float highscore, int losses, int wins, String username, String id) { - this.games = games; - this.highscore = highscore; - this.losses = losses; - this.wins = wins; - this.username = username; - this.id = id; - } - public User() { // Initialize default values for the fields games = 0; diff --git a/frontend/core/src/com/game/tankwars/view/GameScreen.java b/frontend/core/src/com/game/tankwars/view/GameScreen.java index 96c2369ff73dfd09d5d6ea666988083f780e4ca9..cb2b2b08b8f2b5645c67412aaa4cf03eda52d7d2 100644 --- a/frontend/core/src/com/game/tankwars/view/GameScreen.java +++ b/frontend/core/src/com/game/tankwars/view/GameScreen.java @@ -1,14 +1,19 @@ package com.game.tankwars.view; +import static com.game.tankwars.model.CurrentUser.getCurrentUser; + import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Mesh; 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.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; import com.badlogic.gdx.physics.box2d.World; @@ -23,12 +28,14 @@ import com.game.tankwars.model.Terrain; public class GameScreen implements Screen { final TankWarsGame tankWarsGame; - + int VIEWPORT_WIDTH; + int VIEWPORT_HEIGHT; int horizontalScaling; int verticalScaling; SpriteBatch batch; ShapeRenderer shapeRender; - Tank tank; + Tank myTank; + Tank opponentTank; GameHud hud; Box2dWorld model; World world; @@ -43,6 +50,9 @@ public class GameScreen implements Screen { public GameScreen(final TankWarsGame tankWarsGame){ this.tankWarsGame = tankWarsGame; + VIEWPORT_HEIGHT = tankWarsGame.getViewportHeight(); + VIEWPORT_WIDTH = tankWarsGame.getViewportWidth(); + batch = new SpriteBatch(); shapeRender = new ShapeRenderer(); @@ -62,15 +72,27 @@ public class GameScreen implements Screen { terrain = new Terrain(); - int initPos = 50; - tank = new Tank(initPos, new Texture("tank-khaki.png"), new Texture("cannon.png"),terrain, tankWarsGame); - /*horizontalScaling = Gdx.graphics.getWidth() / VIEWPORT_WIDTH; - verticalScaling = Gdx.graphics.getHeight() / VIEWPORT_HEIGHT;*/ + int myPos = 50; + int opponentPos = terrain.getVertices().length - 150; + + myTank = new Tank(myPos, + new Texture("tank-khaki.png"), + new Texture("cannon.png"), + terrain, + tankWarsGame, true); + opponentTank = new Tank(opponentPos, + new Texture("tank-khaki.png"), + new Texture("cannon.png"), + terrain, + tankWarsGame, false); + horizontalScaling = Gdx.graphics.getWidth() / TankWarsGame.GAMEPORT_WIDTH; + verticalScaling = Gdx.graphics.getHeight() / TankWarsGame.GAMEPORT_HEIGHT; + + controller = new GameController(myTank, tankWarsGame, hud); hud = new GameHud(new FitViewport(TankWarsGame.GAMEPORT_WIDTH, TankWarsGame.GAMEPORT_HEIGHT, hudCam), batch); Gdx.input.setInputProcessor(hud.getStage()); - controller = new GameController(tankWarsGame, hud, tank); controller.handleHudEvents(); } @Override @@ -81,7 +103,7 @@ public class GameScreen implements Screen { debugRenderer.render(world, worldCam.combined); shapeRender.setProjectionMatrix(worldCam.combined); - controller.checkKeyInput(); + controller.checkKeyInput(myTank); Array<Body> bodies = new Array<Body>(); world.getBodies(bodies); @@ -91,13 +113,20 @@ public class GameScreen implements Screen { Sprite s = (Sprite) b.getUserData(); if (s != null) { - s.setPosition(b.getPosition().x * (float) TankWarsGame.SCALE - s.getWidth() / 2, (b.getPosition().y + 0.25f) * (float) TankWarsGame.SCALE); - if (s.equals(tank.getChassisSprite())) { - s.setRotation(tank.getAngle()); + s.setPosition(b.getPosition().x * (float) horizontalScaling - s.getWidth() / 2, (b.getPosition().y + 0.25f) * (float) verticalScaling); + if (s.equals(myTank.getChassisSprite())) { + s.setRotation(myTank.getAngle()); + } + if (s.equals(opponentTank.getChassisSprite())) { + s.setRotation(opponentTank.getAngle()); } - if (s.equals(tank.getCannonSprite())) { + if (s.equals(myTank.getCannonSprite())) { s.setOrigin(s.getWidth() / 2, 0); - s.setRotation(tank.getCannonAngle()); + s.setRotation(myTank.getCannonAngle()); + } + if (s.equals(opponentTank.getCannonSprite())) { + s.setOrigin(s.getWidth() / s.getWidth(), 0); + s.setRotation(opponentTank.getCannonAngle()); } } } @@ -107,8 +136,10 @@ public class GameScreen implements Screen { shapeRender.end(); batch.begin(); - tank.getChassisSprite().draw(batch); - tank.getCannonSprite().draw(batch); + myTank.getChassisSprite().draw(batch); + myTank.getCannonSprite().draw(batch); + opponentTank.getChassisSprite().draw(batch); + opponentTank.getCannonSprite().draw(batch); batch.end(); batch.setProjectionMatrix(hud.getStage().getCamera().combined); @@ -119,7 +150,6 @@ public class GameScreen implements Screen { public void show() { } - @Override public void resize(int width, int height) { @@ -142,9 +172,9 @@ public class GameScreen implements Screen { @Override public void dispose() { + myTank.getChassisTexture().dispose(); + myTank.getCannonTexture().dispose(); hud.getStage().dispose(); - tank.getChassisTexture().dispose(); - tank.getCannonTexture().dispose(); batch.dispose(); shapeRender.dispose(); } diff --git a/frontend/core/src/com/game/tankwars/view/LoginScreen.java b/frontend/core/src/com/game/tankwars/view/LoginScreen.java index a02ac785fa4938a19e2ddad721aadc29edf2ee18..4f410c55b2d685af1fc66249d80897c4062075b5 100644 --- a/frontend/core/src/com/game/tankwars/view/LoginScreen.java +++ b/frontend/core/src/com/game/tankwars/view/LoginScreen.java @@ -2,15 +2,25 @@ 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; @@ -27,7 +37,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; @@ -35,7 +44,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(); @@ -50,7 +59,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", @@ -116,6 +125,7 @@ public class LoginScreen implements Screen { @Override public void hide() { //Gdx.input.setInputProcessor(null); + dispose(); } diff --git a/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java b/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java index 5f665eca1c8d107a7da082fbd28ae1af64cf14c4..08bdda59b6053737b193c24e98d39291c0fc0b03 100644 --- a/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java +++ b/frontend/core/src/com/game/tankwars/view/MainMenuScreen.java @@ -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(); } }