From 8a5d38409323cb69d601d8340c60e70ef1b48904 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Mon, 17 Aug 2020 18:27:44 +0530 Subject: [PATCH 01/35] Implemented focus properties for dialogs contents. That's one more TODO down. Also, removed default focus on buttons for Android since it's unlikely users are going to play the game with a keyboard attached on Android --- core/src/com/cg/zoned/MapSelector.java | 8 ++++- .../cg/zoned/screens/ClientLobbyScreen.java | 5 ++- .../com/cg/zoned/screens/MainMenuScreen.java | 5 ++- .../cg/zoned/screens/ServerLobbyScreen.java | 19 +++++++--- core/src/com/cg/zoned/ui/FocusableStage.java | 35 +++++++++++++------ 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/core/src/com/cg/zoned/MapSelector.java b/core/src/com/cg/zoned/MapSelector.java index 8a9e4c6..9133c94 100644 --- a/core/src/com/cg/zoned/MapSelector.java +++ b/core/src/com/cg/zoned/MapSelector.java @@ -2,6 +2,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; @@ -124,6 +125,7 @@ private void showExtraParamDialog(final MapExtraParams prompts, final MapEntity Table contentTable = new Table(); contentTable.center(); + Array focusableDialogButtons = new Array<>(); for (int i = 0; i < prompts.spinnerVars.size + 1; i++) { Label label; if (i == 0) { @@ -146,6 +148,10 @@ private void showExtraParamDialog(final MapExtraParams prompts, final MapEntity spinners[i - 1].snapToStep(snapValue - lowValue); contentTable.add(label).left(); contentTable.add(spinners[i - 1]); + + focusableDialogButtons.add(spinners[i - 1].getLeftButton()); + focusableDialogButtons.add(spinners[i - 1].getRightButton()); + focusableDialogButtons.add(null); } contentTable.row(); } @@ -154,7 +160,7 @@ private void showExtraParamDialog(final MapExtraParams prompts, final MapEntity buttonTexts.add("Cancel"); buttonTexts.add("Set"); - stage.showDialog(contentTable, buttonTexts, false, scaleFactor, + stage.showDialog(contentTable, focusableDialogButtons, buttonTexts, false, scaleFactor, new FocusableStage.DialogResultListener() { @Override public void dialogResult(String buttonText) { diff --git a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java index ec5b6d7..47d6fe0 100644 --- a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java @@ -1,5 +1,6 @@ package com.cg.zoned.screens; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; @@ -279,7 +280,9 @@ public void changed(ChangeEvent event, Actor actor) { stage.addFocusableActor(colorSelector); stage.addFocusableActor(startPosSelector); stage.row(); - stage.setFocusedActor(colorSelector); + if (Gdx.app.getType() == Application.ApplicationType.Desktop) { + stage.setFocusedActor(colorSelector); + } } else { Label colorLabel = new Label(color, game.skin); colorLabel.setName("color-label"); diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index 1e4e41d..a9d2333 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -1,5 +1,6 @@ package com.cg.zoned.screens; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; @@ -168,7 +169,9 @@ public void clicked(InputEvent event, float x, float y) { } mainMenuUIButtons.add(exitButton); - mainStage.setFocusedActor(playButton); + if (Gdx.app.getType() == Application.ApplicationType.Desktop) { + mainStage.setFocusedActor(playButton); + } mainStage.addActor(mainTable); } diff --git a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java index b61aab6..3ac99dc 100644 --- a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java @@ -1,5 +1,6 @@ package com.cg.zoned.screens; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; @@ -129,15 +130,21 @@ private void setUpServerLobbyStage() { mapSelectorTable.add(mapSpinner).pad(10f); final TextButton mapButton = new TextButton(mapSelector.getMapManager().getMapList().get(mapSpinner.getPositionIndex()).getName(), game.skin); + + final Array buttonTexts = new Array<>(); + buttonTexts.add("Cancel"); + buttonTexts.add("Set Map"); + + final Array focusableDialogButtons = new Array<>(); + focusableDialogButtons.add(mapSpinner.getLeftButton()); + focusableDialogButtons.add(mapSpinner.getRightButton()); + mapButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { final int prevIndex = mapSpinner.getPositionIndex(); - Array buttonTexts = new Array<>(); - buttonTexts.add("Cancel"); - buttonTexts.add("Set Map"); - stage.showDialog(mapSelectorTable, buttonTexts, + stage.showDialog(mapSelectorTable, focusableDialogButtons, buttonTexts, false, game.getScaleFactor(), new FocusableStage.DialogResultListener() { @Override @@ -283,7 +290,9 @@ public void changed(ChangeEvent event, Actor actor) { stage.addFocusableActor(colorSelector); stage.addFocusableActor(startPosSelector); stage.row(); - stage.setFocusedActor(colorSelector); + if (Gdx.app.getType() == Application.ApplicationType.Desktop) { + stage.setFocusedActor(colorSelector); + } } else { Label colorLabel = new Label(Constants.PLAYER_COLORS.keySet().iterator().next(), game.skin); colorLabel.setName("color-label"); diff --git a/core/src/com/cg/zoned/ui/FocusableStage.java b/core/src/com/cg/zoned/ui/FocusableStage.java index 39f785b..5f2176a 100644 --- a/core/src/com/cg/zoned/ui/FocusableStage.java +++ b/core/src/com/cg/zoned/ui/FocusableStage.java @@ -1,5 +1,6 @@ package com.cg.zoned.ui; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Color; @@ -217,20 +218,22 @@ private void defocus(Actor actor) { * @param dialogResultListener Interface for beaming back the selected dialog option * @param skin The skin to use for the dialog */ - public void showDialog(String msg, Array buttonTexts, - boolean useVerticalButtonList, + public void showDialog(String msg, + Array buttonTexts, boolean useVerticalButtonList, float scaleFactor, DialogResultListener dialogResultListener, Skin skin) { - showDialog(new Label(msg, skin), buttonTexts, useVerticalButtonList, scaleFactor, dialogResultListener, skin); + showDialog(new Label(msg, skin), null, buttonTexts, useVerticalButtonList, + scaleFactor, dialogResultListener, skin); } - public void showDialog(Table contentTable, Array buttonTexts, - boolean useVerticalButtonList, + public void showDialog(Table contentTable, Array dialogFocusableActorArray, + Array buttonTexts, boolean useVerticalButtonList, float scaleFactor, DialogResultListener dialogResultListener, Skin skin) { - showDialog((Actor) contentTable, buttonTexts, useVerticalButtonList, scaleFactor, dialogResultListener, skin); + showDialog((Actor) contentTable, dialogFocusableActorArray, buttonTexts, useVerticalButtonList, + scaleFactor, dialogResultListener, skin); } - private void showDialog(Actor content, Array buttonTexts, - boolean useVerticalButtonList, + private void showDialog(Actor content, Array dialogFocusableActorArray, + Array buttonTexts, boolean useVerticalButtonList, float scaleFactor, final DialogResultListener dialogResultListener, Skin skin) { final Array backupCurrentActorArray = new Array<>(this.focusableActorArray); final Actor backupFocusedActor = this.currentFocusedActor; @@ -258,7 +261,6 @@ protected void result(Object object) { dialog.getButtonTable().defaults().width(200f * scaleFactor); dialog.getButtonTable().padBottom(10f).padLeft(10f).padRight(10f); dialog.setScale(0); - // TODO: Focus props on content table if (content instanceof Label) { Label label = (Label) content; @@ -266,6 +268,11 @@ protected void result(Object object) { } this.focusableActorArray.clear(); + if (dialogFocusableActorArray != null) { + this.focusableActorArray.addAll(dialogFocusableActorArray); + this.focusableActorArray.add(null); + } + for (int i = 0; i < buttonTexts.size; i++) { TextButton textButton = new TextButton(buttonTexts.get(i), skin); dialog.button(textButton, textButton.getText().toString()); @@ -276,11 +283,19 @@ protected void result(Object object) { } } + if (Gdx.app.getType() == Application.ApplicationType.Android) { + // Unlikely people are going to use keyboards with playing on Android + // Looks a bit weird with the focus in those cases. So just defocus + defocus(backupFocusedActor); + } else { + // Focus the first button in the Dialog when on Desktop + focus(this.focusableActorArray.get(0)); + } + dialog.getStyle().stageBackground = new TextureRegionDrawable(dialogBackgroundTexture); dialog.show(this, Actions.scaleTo(1f, 1f, .2f, Interpolation.fastSlow)); dialog.setOrigin(dialog.getWidth() / 2, dialog.getHeight() / 2); dialog.setPosition(Math.round((getWidth() - dialog.getWidth()) / 2), Math.round((getHeight() - dialog.getHeight()) / 2)); - focus(this.focusableActorArray.get(0)); } public void resize(int width, int height) { From 38c0f9ce88125b593773de3d499589d3ff87e6b7 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Mon, 17 Aug 2020 20:57:00 +0530 Subject: [PATCH 02/35] Version update script works on README too, App bundle default filename Both ain't perfect. Will improve versionUpdate.sh soon. Currently it works but it is stupid --- android/build.gradle | 2 ++ versionUpdate.sh | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index c92737e..7691bb1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,6 +26,8 @@ android { // And project.setVersion in Desktop's build.gradle // And the version in the badge in the README file // Or for Linux users, use the versionUpdate.sh script + + setProperty("archivesBaseName", "${appName}-${versionName}") } buildTypes { release { diff --git a/versionUpdate.sh b/versionUpdate.sh index 05560ba..3c6d5a0 100755 --- a/versionUpdate.sh +++ b/versionUpdate.sh @@ -20,7 +20,19 @@ if [ "$proceed" == "Y" ]; then sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" done - echo "Warning: Versions in the README file aren't updated. Do it manually" + hyphenPos=`echo "$oldVersionName" | grep '-' -oba --color=never | cut -c1` + oldHyphenDoubled=`echo "${oldVersionName:0:$hyphenPos}-${oldVersionName:$hyphenPos}"` + newHyphenDoubled=`echo "${newVersionName:0:$hyphenPos}-${newVersionName:$hyphenPos}"` + + grep -l "$oldHyphenDoubled" README.md | while read filename + do + sed -i -e "s/$oldHyphenDoubled/$newHyphenDoubled/g" "$filename" + done + + grep -l "$oldVersionName" README.md | while read filename + do + sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" + done grep -l "ENABLE_DISCORD_RPC = false" core/src/com/cg/zoned/Constants.java | while read filename do From 1c50da30b2d8e5283fa848093e3c18831da3907d Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:08:38 +0530 Subject: [PATCH 03/35] Improved the versionUpdate.sh script --- versionUpdate.sh | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/versionUpdate.sh b/versionUpdate.sh index 3c6d5a0..21160e5 100755 --- a/versionUpdate.sh +++ b/versionUpdate.sh @@ -5,39 +5,24 @@ read -p "New version name: " newVersionName read -p "Are you sure you wanna do this? (Y/N) " proceed if [ "$proceed" == "Y" ]; then - grep -l "$oldVersionName" android/build.gradle | while read filename - do - sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" - done + files=( + "android/build.gradle" + "desktop/build.gradle" + "core/src/com/cg/zoned/Constants.java" + "README.md" + ) - grep -l "$oldVersionName" desktop/build.gradle | while read filename - do - sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" - done - - grep -l "$oldVersionName" core/src/com/cg/zoned/Constants.java | while read filename - do - sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" - done + sed -i -e "s/$oldVersionName/$newVersionName/g" "${files[@]}" hyphenPos=`echo "$oldVersionName" | grep '-' -oba --color=never | cut -c1` oldHyphenDoubled=`echo "${oldVersionName:0:$hyphenPos}-${oldVersionName:$hyphenPos}"` newHyphenDoubled=`echo "${newVersionName:0:$hyphenPos}-${newVersionName:$hyphenPos}"` - grep -l "$oldHyphenDoubled" README.md | while read filename - do - sed -i -e "s/$oldHyphenDoubled/$newHyphenDoubled/g" "$filename" - done + sed -i -e "s/$oldHyphenDoubled/$newHyphenDoubled/g" "README.md" - grep -l "$oldVersionName" README.md | while read filename - do - sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" - done + sed -i -e "s/ENABLE_DISCORD_RPC = false/ENABLE_DISCORD_RPC = true/g" "core/src/com/cg/zoned/Constants.java" - grep -l "ENABLE_DISCORD_RPC = false" core/src/com/cg/zoned/Constants.java | while read filename - do - sed -i -e "s/ENABLE_DISCORD_RPC = false/ENABLE_DISCORD_RPC = true/g" "$filename" - done + echo "Done :D" else - echo "Alright, aborted" + echo "Alright, aborted :/" fi From d74f9738a1a4733d03e150124bceb6e6900c49d0 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 19 Aug 2020 14:13:34 +0530 Subject: [PATCH 04/35] Recreate map texture when wall are added dynamically Fixes issue #1 --- core/src/com/cg/zoned/Map.java | 4 ++-- core/src/com/cg/zoned/screens/TutorialScreen.java | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index f96e938..eacd114 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -88,7 +88,7 @@ private void createPlayerTexture(ShapeDrawer shapeDrawer) { playerTextureRegion.flip(false, true); } - private void createMapTexture(ShapeDrawer shapeDrawer) { + public void createMapTexture(ShapeDrawer shapeDrawer) { int width = (int) ((cols * Constants.CELL_SIZE) + Constants.MAP_GRID_LINE_WIDTH); int height = (int) ((rows * Constants.CELL_SIZE) + Constants.MAP_GRID_LINE_WIDTH); @@ -217,7 +217,7 @@ public void update(PlayerManager playerManager, Player[] players, float delta) { continue; } - mapColorUpdated = false; // Might need a bit more testing + mapColorUpdated = false; Direction direction = player.direction; if (direction == Direction.UP && player.position.y < rows - 1 && diff --git a/core/src/com/cg/zoned/screens/TutorialScreen.java b/core/src/com/cg/zoned/screens/TutorialScreen.java index c3b6dd4..1825624 100644 --- a/core/src/com/cg/zoned/screens/TutorialScreen.java +++ b/core/src/com/cg/zoned/screens/TutorialScreen.java @@ -204,6 +204,11 @@ public void clicked(InputEvent event, float x, float y) { players[0].position.x = Math.round(players[0].position.x); players[0].position.y = Math.round(players[0].position.y); + if (mapGrid[(int) players[0].position.y][(int) players[0].position.x].cellColor == null) { + mapGrid[(int) players[0].position.y][(int) players[0].position.x].cellColor = + new Color(players[0].color.r, players[0].color.g, players[0].color.b, 0.1f); + } + if (tutorialPromptIndex[0] == tutorialPrompts.size) { togglePlayerInterable(false); animationManager.fadeOutStage(stage, TutorialScreen.this, new MainMenuScreen(game)); @@ -226,6 +231,7 @@ public void run() { String mainText = tutorialPrompts.get(tutorialPromptIndex[0]).mainItem; if (mainText.contains("Walls")) { generateRandomWalls(); + map.createMapTexture(shapeDrawer); } displayNextTutorialText(mainLabel, subLabel, mainText, tutorialPrompts.get(tutorialPromptIndex[0]).subItem); From 6ad7bd91e3aeb8410bf923a7a1f98a576036d39f Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 19 Aug 2020 19:48:13 +0530 Subject: [PATCH 05/35] Improved ScoreBar code --- core/src/com/cg/zoned/ScoreBar.java | 44 ++++++++++++----------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/core/src/com/cg/zoned/ScoreBar.java b/core/src/com/cg/zoned/ScoreBar.java index 8c8ae71..341bb70 100644 --- a/core/src/com/cg/zoned/ScoreBar.java +++ b/core/src/com/cg/zoned/ScoreBar.java @@ -8,18 +8,16 @@ import com.badlogic.gdx.utils.viewport.Viewport; public class ScoreBar { + private static final float SCOREBAR_LERP_VALUE = 3.0f; + public float scoreBarHeight; private float totalWidth; private float totalHeight; - private float[] currentPos; - private float[] scoreBarStartX; private float[] scoreBarWidths; public ScoreBar(Viewport viewport, int size, float scaleFactor) { - currentPos = new float[size]; - scoreBarStartX = new float[size]; scoreBarWidths = new float[size]; totalWidth = viewport.getWorldWidth(); @@ -34,8 +32,6 @@ public void resize(int width, int height) { } public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array teamData, float delta) { - float lerpVal = 3.0f; - float currentWidthPos = 0; float offsetY = totalHeight - scoreBarHeight; @@ -54,35 +50,31 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea for (int i = 0; i < teamData.size; i++) { float barWidth = ((teamData.get(i).score / totalScore) * totalWidth); - float drawWidth = currentPos[i] + (barWidth - currentPos[i]) * lerpVal * delta; + float drawWidth = scoreBarWidths[i] + (barWidth - scoreBarWidths[i]) * SCOREBAR_LERP_VALUE * delta; shapeDrawer.setColor(teamData.get(i).color); + font.setColor(getGoodTextColor(teamData.get(i).color)); - if (i == 0) { // First bar - shapeDrawer.filledRectangle(currentWidthPos, offsetY, drawWidth, scoreBarHeight); - scoreBarStartX[i] = currentWidthPos; - } else if (i == teamData.size - 1) { // Last bar - shapeDrawer.filledRectangle(totalWidth - drawWidth, offsetY, drawWidth, scoreBarHeight); // Can draw upto drawWidth or totalWidth. Should be the same - scoreBarStartX[i] = totalWidth - drawWidth; - } else { // Mid bar(s) - //shapeDrawer.filledRectangle(currentWidthPos + (barWidth / 2) - (drawWidth / 2), offsetY, (drawWidth / 2), BAR_HEIGHT); - shapeDrawer.filledRectangle(currentWidthPos + (barWidth / 2), offsetY, -drawWidth / 2, scoreBarHeight); - shapeDrawer.filledRectangle(currentWidthPos + (barWidth / 2), offsetY, drawWidth / 2, scoreBarHeight); - //shapeDrawer.filledRectangle(currentWidthPos + (barWidth / 2) - (drawWidth / 2), offsetY, drawWidth, BAR_HEIGHT); + float barStartX; + if (i == 0) { // First bar + barStartX = currentWidthPos; + shapeDrawer.filledRectangle(barStartX, offsetY, drawWidth, scoreBarHeight); + } else if (i == teamData.size - 1) { // Last bar + barStartX = totalWidth - drawWidth; + shapeDrawer.filledRectangle(barStartX, offsetY, drawWidth, scoreBarHeight); // Can draw upto drawWidth or totalWidth. Should be the same + } else { // Mid bar(s) + barStartX = currentWidthPos; + shapeDrawer.filledRectangle(barStartX + (barWidth / 2), offsetY, -drawWidth / 2, scoreBarHeight); + shapeDrawer.filledRectangle(barStartX + (barWidth / 2), offsetY, drawWidth / 2, scoreBarHeight); //TODO: Need to polish this - scoreBarStartX[i] = currentWidthPos; } scoreBarWidths[i] = drawWidth; - currentPos[i] = drawWidth; - currentWidthPos += drawWidth; - } - - for (int i = 0; i < scoreBarWidths.length; i++) { - font.setColor(getGoodTextColor(teamData.get(i).color)); font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), - scoreBarStartX[i], totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), + barStartX, totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), scoreBarWidths[i], Align.center, false); + + currentWidthPos += drawWidth; } } From 3348539f1c25963202486a6701cebac6fa93217b Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Thu, 20 Aug 2020 19:50:57 +0530 Subject: [PATCH 06/35] Polished ScoreBar code That's one more TODO down. After several hours trying to make ScoreBars work the way I wanted it to, I finally got it right! ScoreBar movement should now be smooth and fluid and there should no longer be any abrupt "jumps" when the score changes --- core/src/com/cg/zoned/ScoreBar.java | 78 +++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/core/src/com/cg/zoned/ScoreBar.java b/core/src/com/cg/zoned/ScoreBar.java index 341bb70..a375cf4 100644 --- a/core/src/com/cg/zoned/ScoreBar.java +++ b/core/src/com/cg/zoned/ScoreBar.java @@ -15,24 +15,44 @@ public class ScoreBar { private float totalWidth; private float totalHeight; - private float[] scoreBarWidths; + private float[] scoreBarCurrentWidth; + private float[] scoreBarTargetWidth; + private float[] scoreBarDrawStartPos; public ScoreBar(Viewport viewport, int size, float scaleFactor) { - scoreBarWidths = new float[size]; + scoreBarCurrentWidth = new float[size]; + scoreBarTargetWidth = new float[size]; + scoreBarDrawStartPos = new float[size]; totalWidth = viewport.getWorldWidth(); totalHeight = viewport.getWorldHeight(); + computeDrawStartPos(); + scoreBarHeight = 16f * scaleFactor; } + private void computeDrawStartPos() { + int size = scoreBarDrawStartPos.length; + + float splitScreenWidth = totalWidth / size; + for (int i = 1; i < size - 1; i++) { + scoreBarDrawStartPos[i] = splitScreenWidth * i; + scoreBarDrawStartPos[i] += (splitScreenWidth / 2); + } + if (size != 1) { + scoreBarDrawStartPos[size - 1] = totalWidth; + } else { + scoreBarDrawStartPos[size - 1] = totalWidth / 2; + } + } + public void resize(int width, int height) { totalWidth = width; totalHeight = height; } public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array teamData, float delta) { - float currentWidthPos = 0; float offsetY = totalHeight - scoreBarHeight; float totalScore = 0; @@ -50,31 +70,45 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea for (int i = 0; i < teamData.size; i++) { float barWidth = ((teamData.get(i).score / totalScore) * totalWidth); - float drawWidth = scoreBarWidths[i] + (barWidth - scoreBarWidths[i]) * SCOREBAR_LERP_VALUE * delta; + scoreBarTargetWidth[i] = barWidth; + + float drawWidth = scoreBarCurrentWidth[i] + ((scoreBarTargetWidth[i] - scoreBarCurrentWidth[i]) * SCOREBAR_LERP_VALUE * delta); + scoreBarCurrentWidth[i] = drawWidth; shapeDrawer.setColor(teamData.get(i).color); font.setColor(getGoodTextColor(teamData.get(i).color)); - float barStartX; - if (i == 0) { // First bar - barStartX = currentWidthPos; - shapeDrawer.filledRectangle(barStartX, offsetY, drawWidth, scoreBarHeight); - } else if (i == teamData.size - 1) { // Last bar - barStartX = totalWidth - drawWidth; - shapeDrawer.filledRectangle(barStartX, offsetY, drawWidth, scoreBarHeight); // Can draw upto drawWidth or totalWidth. Should be the same - } else { // Mid bar(s) - barStartX = currentWidthPos; - shapeDrawer.filledRectangle(barStartX + (barWidth / 2), offsetY, -drawWidth / 2, scoreBarHeight); - shapeDrawer.filledRectangle(barStartX + (barWidth / 2), offsetY, drawWidth / 2, scoreBarHeight); - //TODO: Need to polish this + float barStartX = 0; + for (int j = 0; j < i; j++) { + barStartX += scoreBarTargetWidth[j]; } - scoreBarWidths[i] = drawWidth; - font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), - barStartX, totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), - scoreBarWidths[i], Align.center, false); - - currentWidthPos += drawWidth; + if (i == 0) { + /* ScoreBar at the left */ + scoreBarDrawStartPos[i] = scoreBarDrawStartPos[i] + ((barStartX - scoreBarDrawStartPos[i]) * SCOREBAR_LERP_VALUE * delta); + + shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, drawWidth, scoreBarHeight); + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + scoreBarDrawStartPos[i], totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), + drawWidth, Align.center, false); + } else if (i == teamData.size - 1) { + /* ScoreBar at the right */ + scoreBarDrawStartPos[i] = scoreBarDrawStartPos[i] + ((barStartX + scoreBarTargetWidth[i] - scoreBarDrawStartPos[i]) * SCOREBAR_LERP_VALUE * delta); + + shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, -drawWidth, scoreBarHeight); + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + scoreBarDrawStartPos[i] - drawWidth, totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), + drawWidth, Align.center, false); + } else { + /* ScoreBars at the middle */ + scoreBarDrawStartPos[i] = scoreBarDrawStartPos[i] + ((barStartX + (scoreBarTargetWidth[i] / 2) - scoreBarDrawStartPos[i]) * SCOREBAR_LERP_VALUE * delta); + + shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, drawWidth / 2, scoreBarHeight); + shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, -drawWidth / 2, scoreBarHeight); + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + scoreBarDrawStartPos[i] - (drawWidth / 2), totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), + drawWidth, Align.center, false); + } } } From 7392ec5db7d4a2a47ddf4b58db8e148225b8b894 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 21 Aug 2020 19:52:32 +0530 Subject: [PATCH 07/35] Grid render "optimization" That's the last TODO down, but this was my mistake. I should benchmark before optimizing stuff because this "optimized" version is actually slower than the previous code. Turns out the grid render code runs really fast already, any "optimizations" is likely to make it worse. Just wanted to get this into git's history because it took some hours to get it right and might be useful elsewhere --- core/src/com/cg/zoned/Map.java | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index eacd114..9195328 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -40,6 +40,7 @@ public class Map { private FrameBuffer mapFbo = null; private TextureRegion mapTextureRegion = null; + private TextureRegion mapSubTextureRegion = null; /** * Creates the map object with features like processing each turn and managing score, rendering @@ -114,6 +115,8 @@ public void createMapTexture(ShapeDrawer shapeDrawer) { mapTextureRegion = new TextureRegion(mapFbo.getColorBufferTexture(), width, height); mapTextureRegion.flip(false, true); + + mapSubTextureRegion = new TextureRegion(mapTextureRegion); } public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, BitmapFont playerLabelFont) { @@ -279,6 +282,7 @@ private void setMapColors(PlayerManager playerManager, Player[] players) { int posX = Math.round(player.position.x); int posY = Math.round(player.position.y); if (mapGrid[posY][posX].cellColor == null && mapGrid[posY][posX].playerCount == 1) { + // Should we allow multiple players of the same team in the same location capture the cell? mapGrid[posY][posX].cellColor = new Color(player.color.r, player.color.g, player.color.b, 0.1f); if (playerManager != null) { playerManager.incrementScore(player); @@ -408,8 +412,20 @@ private void drawColors(ShapeDrawer shapeDrawer, Rectangle userViewRect, float d } private void drawGrid(Rectangle userViewRect, Batch batch) { - // TODO: Optimization: Draw only the region that is in view - batch.draw(mapTextureRegion, -Constants.MAP_GRID_LINE_WIDTH / 2, -Constants.MAP_GRID_LINE_WIDTH / 2); + int x = (int) Math.max(0, userViewRect.getX()); + int y = (int) Math.max(0, userViewRect.getY()); + int width = (int) Math.max(0, + Math.min(mapTextureRegion.getRegionWidth() - x, + (userViewRect.getX() + userViewRect.getWidth() + Constants.MAP_GRID_LINE_WIDTH))); + int height = (int) Math.max(0, Math.min(mapTextureRegion.getRegionHeight() - y, + (userViewRect.getY() + userViewRect.getHeight() + Constants.MAP_GRID_LINE_WIDTH))); + + mapSubTextureRegion.setRegion(x, y, width, height); + mapSubTextureRegion.flip(false, true); + + batch.draw(mapSubTextureRegion, + -Constants.MAP_GRID_LINE_WIDTH / 2 + mapSubTextureRegion.getRegionX(), + -Constants.MAP_GRID_LINE_WIDTH / 2 + mapSubTextureRegion.getRegionY() - mapSubTextureRegion.getRegionHeight()); } public void renderPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { From 759a13cee1534c4af5b7a47706186dc4bf7aec0e Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 21 Aug 2020 19:59:35 +0530 Subject: [PATCH 08/35] Revert grid render "optimization" --- core/src/com/cg/zoned/Map.java | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index 9195328..abc43ee 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -40,7 +40,6 @@ public class Map { private FrameBuffer mapFbo = null; private TextureRegion mapTextureRegion = null; - private TextureRegion mapSubTextureRegion = null; /** * Creates the map object with features like processing each turn and managing score, rendering @@ -115,8 +114,6 @@ public void createMapTexture(ShapeDrawer shapeDrawer) { mapTextureRegion = new TextureRegion(mapFbo.getColorBufferTexture(), width, height); mapTextureRegion.flip(false, true); - - mapSubTextureRegion = new TextureRegion(mapTextureRegion); } public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, BitmapFont playerLabelFont) { @@ -375,7 +372,7 @@ public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera Batch batch = shapeDrawer.getBatch(); batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); - drawGrid(userViewRect, batch); + drawGrid(batch); drawPlayers(players, userViewRect, batch); renderPlayerLabels(players, userViewRect, batch); @@ -411,21 +408,8 @@ private void drawColors(ShapeDrawer shapeDrawer, Rectangle userViewRect, float d } } - private void drawGrid(Rectangle userViewRect, Batch batch) { - int x = (int) Math.max(0, userViewRect.getX()); - int y = (int) Math.max(0, userViewRect.getY()); - int width = (int) Math.max(0, - Math.min(mapTextureRegion.getRegionWidth() - x, - (userViewRect.getX() + userViewRect.getWidth() + Constants.MAP_GRID_LINE_WIDTH))); - int height = (int) Math.max(0, Math.min(mapTextureRegion.getRegionHeight() - y, - (userViewRect.getY() + userViewRect.getHeight() + Constants.MAP_GRID_LINE_WIDTH))); - - mapSubTextureRegion.setRegion(x, y, width, height); - mapSubTextureRegion.flip(false, true); - - batch.draw(mapSubTextureRegion, - -Constants.MAP_GRID_LINE_WIDTH / 2 + mapSubTextureRegion.getRegionX(), - -Constants.MAP_GRID_LINE_WIDTH / 2 + mapSubTextureRegion.getRegionY() - mapSubTextureRegion.getRegionHeight()); + private void drawGrid(Batch batch) { + batch.draw(mapTextureRegion, -Constants.MAP_GRID_LINE_WIDTH / 2, -Constants.MAP_GRID_LINE_WIDTH / 2); } public void renderPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { From aba8406f6c75b7f33fca5246313776785bc08adf Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Sat, 22 Aug 2020 21:02:21 +0530 Subject: [PATCH 09/35] Improved player texture crispness, Fixed blending issues FINALLY! This took waay too much time to get it working. Phew! --- core/src/com/cg/zoned/Map.java | 27 +++++++++---------- core/src/com/cg/zoned/Player.java | 12 +++++---- core/src/com/cg/zoned/screens/GameScreen.java | 2 +- .../com/cg/zoned/screens/MainMenuScreen.java | 1 + 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index abc43ee..ee16644 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -36,6 +36,7 @@ public class Map { private TextureRegion[] playerLabels = null; private FrameBuffer playerFbo = null; + private float playerTextureRegionScale = 2f; private TextureRegion playerTextureRegion = null; private FrameBuffer mapFbo = null; @@ -62,7 +63,7 @@ public Map(Cell[][] mapGrid, int wallCount, ShapeDrawer shapeDrawer) { } private void createPlayerTexture(ShapeDrawer shapeDrawer) { - int size = (int) Constants.CELL_SIZE; + int size = (int) (((int) Constants.CELL_SIZE) * playerTextureRegionScale); Batch batch = shapeDrawer.getBatch(); batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0, 0, size, size)); @@ -71,15 +72,16 @@ private void createPlayerTexture(ShapeDrawer shapeDrawer) { playerFbo.dispose(); } - playerFbo = new FrameBuffer(Pixmap.Format.RGB565, size, size, false); + playerFbo = new FrameBuffer(Pixmap.Format.RGBA4444, size, size, false); playerFbo.begin(); batch.begin(); - Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClearColor(0, 0, 0, 0); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); shapeDrawer.setColor(Constants.PLAYER_CIRCLE_COLOR); - shapeDrawer.circle(size / 2f, size / 2f, size / 3f, Constants.PLAYER_CIRCLE_WIDTH, JoinType.SMOOTH); + shapeDrawer.circle(size / 2f, size / 2f, size / 3f, + Constants.PLAYER_CIRCLE_WIDTH * playerTextureRegionScale, JoinType.SMOOTH); batch.end(); playerFbo.end(); @@ -100,11 +102,11 @@ public void createMapTexture(ShapeDrawer shapeDrawer) { mapFbo.dispose(); } - mapFbo = new FrameBuffer(Pixmap.Format.RGB565, width, height, false); + mapFbo = new FrameBuffer(Pixmap.Format.RGBA4444, width, height, false); mapFbo.begin(); batch.begin(); - Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClearColor(0, 0, 0, 0); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); drawGrid(shapeDrawer); @@ -119,7 +121,7 @@ public void createMapTexture(ShapeDrawer shapeDrawer) { public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, BitmapFont playerLabelFont) { playerLabels = new TextureRegion[players.length]; - int totalHeight = ((int) playerLabelFont.getLineHeight()) * players.length; + int totalHeight = (((int) (playerLabelFont.getLineHeight() - (Constants.MAP_GRID_LINE_WIDTH / 2))) * players.length); int height = totalHeight / players.length; int width = (int) (Constants.CELL_SIZE * 3f); float radius = height / 2f; @@ -131,11 +133,11 @@ public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, playerLabelFbo.dispose(); } - playerLabelFbo = new FrameBuffer(Pixmap.Format.RGB565, width, totalHeight, false); + playerLabelFbo = new FrameBuffer(Pixmap.Format.RGBA4444, width, totalHeight, false); playerLabelFbo.begin(); batch.begin(); - Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClearColor(0, 0, 0, 0); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); for (int i = 0; i < playerLabels.length; i++) { @@ -279,7 +281,7 @@ private void setMapColors(PlayerManager playerManager, Player[] players) { int posX = Math.round(player.position.x); int posY = Math.round(player.position.y); if (mapGrid[posY][posX].cellColor == null && mapGrid[posY][posX].playerCount == 1) { - // Should we allow multiple players of the same team in the same location capture the cell? + // TODO: Should we allow multiple players of the same team in the same location capture the cell? mapGrid[posY][posX].cellColor = new Color(player.color.r, player.color.g, player.color.b, 0.1f); if (playerManager != null) { playerManager.incrementScore(player); @@ -370,18 +372,15 @@ public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera drawColors(shapeDrawer, userViewRect, delta); Batch batch = shapeDrawer.getBatch(); - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); drawGrid(batch); drawPlayers(players, userViewRect, batch); renderPlayerLabels(players, userViewRect, batch); - - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } private void drawPlayers(Player[] players, Rectangle userViewRect, Batch batch) { for (Player player : players) { - player.render(userViewRect, batch, playerTextureRegion); + player.render(userViewRect, batch, playerTextureRegion, playerTextureRegionScale); } } diff --git a/core/src/com/cg/zoned/Player.java b/core/src/com/cg/zoned/Player.java index 0590176..5f01034 100644 --- a/core/src/com/cg/zoned/Player.java +++ b/core/src/com/cg/zoned/Player.java @@ -14,17 +14,17 @@ public class Player extends InputAdapter { public String name; public int score; - public Vector2 position; public int[] controls; public Direction direction; public Direction updatedDirection; + public Vector2 position; public Vector2 prevPosition; + public Vector2 targetPosition; public boolean dummyMoving; private Vector2 dummyPosition; - public Vector2 targetPosition; private float timeElapsed; public Player(Color color, String name) { @@ -69,7 +69,7 @@ public void moveTo(Vector2 targetPosition, float delta) { } } - public void dummyMoveTo(Vector2 targetPosition, float delta) { // Simulate a fake movement for proper timing for server-client synchronization + public void dummyMoveTo(Vector2 targetPosition, float delta) { // Simulate a fake movement for timed movement from all players if (this.targetPosition == null) { this.targetPosition = targetPosition; this.dummyMoving = true; @@ -87,12 +87,14 @@ public void dummyMoveTo(Vector2 targetPosition, float delta) { // Simulate a fak } } - public void render(Rectangle userViewRect, Batch batch, TextureRegion playerTexture) { + public void render(Rectangle userViewRect, Batch batch, TextureRegion playerTexture, float playerTextureRegionScale) { float startX = (this.position.x * Constants.CELL_SIZE); float startY = (this.position.y * Constants.CELL_SIZE); if (userViewRect.contains(startX, startY)) { - batch.draw(playerTexture, startX, startY); + batch.draw(playerTexture, startX, startY, + playerTexture.getRegionWidth() / playerTextureRegionScale, + playerTexture.getRegionHeight() / playerTextureRegionScale); } } diff --git a/core/src/com/cg/zoned/screens/GameScreen.java b/core/src/com/cg/zoned/screens/GameScreen.java index ea6f923..ebad886 100644 --- a/core/src/com/cg/zoned/screens/GameScreen.java +++ b/core/src/com/cg/zoned/screens/GameScreen.java @@ -47,7 +47,7 @@ public class GameScreen extends ScreenAdapter implements InputProcessor { private Map map; - private ExtendViewport[] playerViewports; // Two viewports in split-screen mode; else one + private ExtendViewport[] playerViewports; private ShapeDrawer shapeDrawer; private SpriteBatch batch; diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index a9d2333..f285bbb 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -95,6 +95,7 @@ public void run() { public void run() { roundedCornerBgColorTexture = new Texture(pixmap); usedTextures.add(roundedCornerBgColorTexture); + // TODO: Try to Ninepatchify this pixmap.dispose(); } }); From dc8b8baee98049664f3b56c77f26534679052e35 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Tue, 25 Aug 2020 20:10:10 +0530 Subject: [PATCH 10/35] Custom external map functionality for local network multiplayer mode Used a Ninepatch for the playmode stage, so I think it would be faster? At least it should look better now. Also, changed version to v0.0.3-dev to show that this is a development version and avoid clashes with the beta versions. Tested the networking, but might have bugs, hard to test every possible scenario. A bit of cleanup on the code coming soon --- README.md | 2 +- android/build.gradle | 2 +- core/src/com/cg/zoned/Constants.java | 2 +- core/src/com/cg/zoned/KryoHelper.java | 3 + core/src/com/cg/zoned/Map.java | 7 +- .../com/cg/zoned/buffers/BufferMapData.java | 8 ++ .../com/cg/zoned/buffers/BufferNewMap.java | 1 + .../zoned/listeners/ClientLobbyListener.java | 6 +- .../zoned/listeners/ServerLobbyListener.java | 4 + .../ClientLobbyConnectionManager.java | 58 +++++++++- .../src/com/cg/zoned/managers/MapManager.java | 36 ++++++- .../ServerLobbyConnectionManager.java | 101 +++++++++++++++--- .../com/cg/zoned/maps/ExternalMapReader.java | 93 +++++++++------- .../cg/zoned/screens/ClientLobbyScreen.java | 79 +++++++++++--- .../com/cg/zoned/screens/HostJoinScreen.java | 7 +- .../com/cg/zoned/screens/MainMenuScreen.java | 35 +++--- .../cg/zoned/screens/ServerLobbyScreen.java | 24 ++++- desktop/build.gradle | 2 +- .../com/cg/zoned/desktop/DesktopLauncher.java | 1 + 19 files changed, 369 insertions(+), 102 deletions(-) create mode 100644 core/src/com/cg/zoned/buffers/BufferMapData.java diff --git a/README.md b/README.md index 6a241e3..a737fc9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Zoned   [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Version: 0.0.2-beta](https://img.shields.io/badge/version-0.0.2--beta-orange)](https://github.com/Spikatrix/Zoned/releases/tag/v0.0.2-beta) +# Zoned   [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Version: 0.0.3-dev](https://img.shields.io/badge/version-0.0.3--dev-orange)](https://github.com/Spikatrix/Zoned/releases/tag/v0.0.3-dev) Zoned Icon diff --git a/android/build.gradle b/android/build.gradle index 7691bb1..630c476 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,7 +21,7 @@ android { minSdkVersion 14 targetSdkVersion 29 versionCode 2 - versionName "0.0.2-beta" + versionName "0.0.3-dev" // Remember to update the GAME_VERSION in Constants.java // And project.setVersion in Desktop's build.gradle // And the version in the badge in the README file diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 1e3bd19..0bcb671 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -7,7 +7,7 @@ import java.util.Map; public final class Constants { - public static final String GAME_VERSION = "0.0.2-beta"; + public static final String GAME_VERSION = "0.0.3-dev"; // Remember to update the versionName in Android's build.gradle // And project.setVersion in Desktop's build.gradle // And the version in the badge in the README file diff --git a/core/src/com/cg/zoned/KryoHelper.java b/core/src/com/cg/zoned/KryoHelper.java index c10972f..409913f 100644 --- a/core/src/com/cg/zoned/KryoHelper.java +++ b/core/src/com/cg/zoned/KryoHelper.java @@ -4,6 +4,7 @@ import com.cg.zoned.buffers.BufferClientConnect; import com.cg.zoned.buffers.BufferDirections; import com.cg.zoned.buffers.BufferGameStart; +import com.cg.zoned.buffers.BufferMapData; import com.cg.zoned.buffers.BufferNewMap; import com.cg.zoned.buffers.BufferPlayerData; import com.cg.zoned.buffers.BufferPlayerDisconnected; @@ -19,10 +20,12 @@ public static void registerClasses(Kryo kryo) { kryo.register(BufferPlayerData.class); kryo.register(BufferDirections.class); kryo.register(BufferGameStart.class); + kryo.register(BufferMapData.class); kryo.register(BufferNewMap.class); kryo.register(Direction[].class); kryo.register(Direction.class); kryo.register(String[].class); + kryo.register(byte[].class); kryo.register(int[].class); } } \ No newline at end of file diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index ee16644..13996fe 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -369,13 +369,12 @@ private Rectangle calcUserViewRect(OrthographicCamera camera) { public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera camera, float delta) { Rectangle userViewRect = calcUserViewRect(camera); - drawColors(shapeDrawer, userViewRect, delta); - Batch batch = shapeDrawer.getBatch(); + drawColors(shapeDrawer, userViewRect, delta); drawGrid(batch); drawPlayers(players, userViewRect, batch); - renderPlayerLabels(players, userViewRect, batch); + drawPlayerLabels(players, userViewRect, batch); } private void drawPlayers(Player[] players, Rectangle userViewRect, Batch batch) { @@ -411,7 +410,7 @@ private void drawGrid(Batch batch) { batch.draw(mapTextureRegion, -Constants.MAP_GRID_LINE_WIDTH / 2, -Constants.MAP_GRID_LINE_WIDTH / 2); } - public void renderPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { + public void drawPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { if (playerLabels != null) { for (int i = 0; i < players.length; i++) { float posX = (players[i].position.x * Constants.CELL_SIZE) - (playerLabels[i].getRegionWidth() / 2f) + (Constants.CELL_SIZE / 2); diff --git a/core/src/com/cg/zoned/buffers/BufferMapData.java b/core/src/com/cg/zoned/buffers/BufferMapData.java new file mode 100644 index 0000000..022c190 --- /dev/null +++ b/core/src/com/cg/zoned/buffers/BufferMapData.java @@ -0,0 +1,8 @@ +package com.cg.zoned.buffers; + +public class BufferMapData { + public String mapName; + public String mapData; + public int mapHash; + public byte[] mapPreviewData; +} diff --git a/core/src/com/cg/zoned/buffers/BufferNewMap.java b/core/src/com/cg/zoned/buffers/BufferNewMap.java index 92abaaa..e4da02e 100644 --- a/core/src/com/cg/zoned/buffers/BufferNewMap.java +++ b/core/src/com/cg/zoned/buffers/BufferNewMap.java @@ -3,4 +3,5 @@ public class BufferNewMap { public String mapName; public int[] mapExtraParams; + public int mapHash; } diff --git a/core/src/com/cg/zoned/listeners/ClientLobbyListener.java b/core/src/com/cg/zoned/listeners/ClientLobbyListener.java index 9ddd3e9..cf24a4d 100644 --- a/core/src/com/cg/zoned/listeners/ClientLobbyListener.java +++ b/core/src/com/cg/zoned/listeners/ClientLobbyListener.java @@ -1,6 +1,7 @@ package com.cg.zoned.listeners; import com.cg.zoned.buffers.BufferGameStart; +import com.cg.zoned.buffers.BufferMapData; import com.cg.zoned.buffers.BufferNewMap; import com.cg.zoned.buffers.BufferPlayerData; import com.cg.zoned.buffers.BufferServerRejectedConnection; @@ -25,7 +26,10 @@ public void received(Connection connection, Object object) { clientLobbyConnectionManager.connectionRejected(bsrc.errorMsg); } else if (object instanceof BufferNewMap) { BufferNewMap bnm = (BufferNewMap) object; - clientLobbyConnectionManager.newMapSet(bnm.mapName, bnm.mapExtraParams); + clientLobbyConnectionManager.newMapSet(bnm.mapName, bnm.mapExtraParams, bnm.mapHash); + } else if (object instanceof BufferMapData) { + BufferMapData bmd = (BufferMapData) object; + clientLobbyConnectionManager.downloadMap(bmd.mapName, bmd.mapData, bmd.mapHash, bmd.mapPreviewData); } else if (object instanceof BufferGameStart) { clientLobbyConnectionManager.startGame(); } diff --git a/core/src/com/cg/zoned/listeners/ServerLobbyListener.java b/core/src/com/cg/zoned/listeners/ServerLobbyListener.java index dd512e4..cf0e203 100644 --- a/core/src/com/cg/zoned/listeners/ServerLobbyListener.java +++ b/core/src/com/cg/zoned/listeners/ServerLobbyListener.java @@ -1,6 +1,7 @@ package com.cg.zoned.listeners; import com.cg.zoned.buffers.BufferClientConnect; +import com.cg.zoned.buffers.BufferMapData; import com.cg.zoned.buffers.BufferPlayerData; import com.cg.zoned.managers.ServerLobbyConnectionManager; import com.esotericsoftware.kryonet.Connection; @@ -21,6 +22,9 @@ public void received(Connection connection, Object object) { } else if (object instanceof BufferPlayerData) { BufferPlayerData bpd = (BufferPlayerData) object; serverLobbyConnectionManager.receiveClientData(connection, bpd.nameStrings[0], bpd.whoStrings[0], bpd.readyStrings[0], bpd.colorStrings[0], bpd.startPosStrings[0]); + } else if (object instanceof BufferMapData) { + BufferMapData bmd = (BufferMapData) object; + serverLobbyConnectionManager.serveMap(connection, bmd.mapName); } super.received(connection, object); diff --git a/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java b/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java index b47e20c..c2a88b3 100644 --- a/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java +++ b/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java @@ -1,11 +1,14 @@ package com.cg.zoned.managers; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.GdxRuntimeException; import com.cg.zoned.Constants; import com.cg.zoned.buffers.BufferClientConnect; +import com.cg.zoned.buffers.BufferMapData; import com.cg.zoned.buffers.BufferPlayerData; import com.cg.zoned.listeners.ClientLobbyListener; import com.cg.zoned.ui.DropDownMenu; @@ -76,12 +79,59 @@ public void run() { * * @param mapName The name of the new map * @param mapExtraParams The extra params of the new map, if any + * @param mapHash The hash of the contents of the map in the server */ - public void newMapSet(final String mapName, final int[] mapExtraParams) { + public void newMapSet(final String mapName, final int[] mapExtraParams, final int mapHash) { Gdx.app.postRunnable(new Runnable() { @Override public void run() { - clientPlayerListener.mapChanged(mapName, mapExtraParams); + clientPlayerListener.mapChanged(mapName, mapExtraParams, mapHash, false); + } + }); + } + + /** + * Called by the client to request new external map data as it doesn't exist in the client + * + * @param mapName The name of the map to request from the server + */ + public void requestMap(String mapName) { + BufferMapData bmd = new BufferMapData(); + bmd.mapName = mapName; + bmd.mapData = null; + bmd.mapPreviewData = null; + + client.sendTCP(bmd); + } + + public void downloadMap(final String mapName, final String mapData, final int mapHash, final byte[] mapPreviewData) { + Gdx.app.postRunnable(new Runnable() { + @Override + public void run() { + FileHandle externalMapDir = clientPlayerListener.getExternalMapDir(); + + try { + FileHandle mapFile = externalMapDir.child(mapName + ".map"); + mapFile.writeString(mapData, false); + } catch (GdxRuntimeException e) { + clientPlayerListener.displayServerError("Failed to download the map '" + "' (" + e.getMessage() + ")"); + return; + } + + if (mapPreviewData != null) { + try { + FileHandle mapPreviewDataFile = externalMapDir.child(mapName + ".png"); + mapPreviewDataFile.writeBytes(mapPreviewData, false); + + Gdx.app.log(Constants.LOG_TAG, "Downloaded map '" + mapName + "'"); + } catch (GdxRuntimeException e) { + Gdx.app.log(Constants.LOG_TAG, "Downloaded map '" + mapName + "'. Failed to download preview"); + } + } else { + Gdx.app.log(Constants.LOG_TAG, "Downloaded map '" + mapName + "'. Map preview unavailable"); + } + + clientPlayerListener.mapChanged(mapName, null, mapHash, true); } }); } @@ -155,8 +205,10 @@ public interface ClientPlayerListener { void disconnected(); - void mapChanged(String mapName, int[] extraParams); + void mapChanged(String mapName, int[] extraParams, int mapHash, boolean reloadExternalMaps); void updatePlayers(Array playerNames, String[] nameStrings, String[] whoStrings, String[] readyStrings, String[] colorStrings, String[] startPosStrings); + + FileHandle getExternalMapDir(); } } diff --git a/core/src/com/cg/zoned/managers/MapManager.java b/core/src/com/cg/zoned/managers/MapManager.java index db5951b..69d6a2c 100644 --- a/core/src/com/cg/zoned/managers/MapManager.java +++ b/core/src/com/cg/zoned/managers/MapManager.java @@ -30,27 +30,36 @@ public class MapManager { private Array preparedStartPositions = null; private Array preparedStartPosNames = null; private int wallCount = 0; + private int internalMapCount = 0; + private ExternalMapReader externalMapReader; private FileHandle externalMapDir = null; public MapManager() { this.mapList = new Array<>(); loadDefaultMaps(); + + this.externalMapReader = new ExternalMapReader(); + externalMapDir = externalMapReader.getExternalMapDir(); } private void loadDefaultMaps() { mapList.add(new RectangleMap()); mapList.add(new HoloMap()); mapList.add(new XMap()); + + internalMapCount = mapList.size; } public void loadExternalMaps(final OnExternalMapLoadListener mapLoadListener) { new Thread(new Runnable() { @Override public void run() { - ExternalMapReader externalMapReader = new ExternalMapReader(); - externalMapDir = externalMapReader.getExternalMapDir(); + if (mapList.size != internalMapCount) { + mapList.removeRange(internalMapCount, mapList.size - 1); + } + externalMapReader.scanAndParseExternalMaps(); Array externalLoadedMaps = externalMapReader.getLoadedMaps(); @@ -64,6 +73,25 @@ public void run() { }).start(); } + public void loadExternalMap(String mapName) { + // Loading on the main thread itself because it's just one map + // (And because new threads messes up stuff in client lobby where this is called xD) + + for (MapEntity map : mapList) { + if (map.getName().equals(mapName)) { // Map already loaded + return; + } + } + + int sizeBefore = externalMapReader.getLoadedMaps().size; + externalMapReader.parseExternalMap(mapName); + Array externalMapList = externalMapReader.getLoadedMaps(); + + if (externalMapList.size > sizeBefore) { + mapList.add(externalMapList.get(sizeBefore)); + } + } + public Texture getMapPreview(String mapName) { // Scan for the map preview in the internal directory try { @@ -191,6 +219,10 @@ public int getWallCount() { return wallCount; } + public FileHandle getExternalMapDir() { + return externalMapDir; + } + public interface OnExternalMapLoadListener { void onExternalMapLoaded(Array mapList, int externalMapStartIndex); } diff --git a/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java b/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java index 6db54fd..0d70259 100644 --- a/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java +++ b/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java @@ -1,6 +1,7 @@ package com.cg.zoned.managers; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; @@ -8,12 +9,15 @@ import com.badlogic.gdx.utils.SnapshotArray; import com.cg.zoned.Constants; import com.cg.zoned.buffers.BufferGameStart; +import com.cg.zoned.buffers.BufferMapData; import com.cg.zoned.buffers.BufferNewMap; import com.cg.zoned.buffers.BufferPlayerData; import com.cg.zoned.buffers.BufferServerRejectedConnection; import com.cg.zoned.listeners.ServerLobbyListener; +import com.cg.zoned.maps.MapEntity; import com.cg.zoned.maps.MapExtraParams; import com.cg.zoned.ui.DropDownMenu; +import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryonet.Connection; import com.esotericsoftware.kryonet.Server; @@ -94,7 +98,8 @@ public void receiveClientName(final Connection connection, final String clientNa @Override public void run() { if (!Constants.GAME_VERSION.equals(clientGameVersion)) { - rejectConnection(connection, "Server client version mismatch\nServer game version: " + Constants.GAME_VERSION + "\nYour game version: " + clientGameVersion); + rejectConnection(connection, "Server client version mismatch!\n" + + "Server game version: " + Constants.GAME_VERSION + "\nYour game version: " + clientGameVersion); return; } @@ -182,12 +187,7 @@ public void broadcastPlayerInfo(SnapshotArray playerItems, int index) { } } - Connection[] connections = server.getConnections(); - for (int i = 0; i < connections.length; i++) { - if (playerNameResolved.get(i)) { - connections[i].sendTCP(bpd); - } - } + sentToAcceptedClients(bpd); } /** @@ -235,9 +235,13 @@ public void run() { }); } - public void acceptPlayer(int playerIndex, MapManager mapManager) { + /** + * Called when a player is accepted by the server + * + * @param playerIndex The index of the player accepted + */ + public void acceptPlayer(int playerIndex) { playerNameResolved.set(playerIndex, true); - sendMapDetails(playerIndex, mapManager); } /** @@ -252,21 +256,84 @@ public void sendMapDetails(int playerIndex, MapManager mapManager) { // Send map details to the client BufferNewMap bnm = new BufferNewMap(); bnm.mapName = mapManager.getPreparedMap().getName(); + bnm.mapHash = mapManager.getMap(bnm.mapName).getMapData().hashCode(); bnm.mapExtraParams = extraParams != null ? extraParams.extraParams : null; - if (playerIndex > -1) { + if (playerIndex > -1 && playerNameResolved.get(playerIndex)) { Connection connection = playerConnections.get(playerIndex); connection.sendTCP(bnm); } else { - server.sendToAllTCP(bnm); + sentToAcceptedClients(bnm); } } - public String validateServerData(SnapshotArray playerItems) { - if (server.getConnections().length < 1) { - return "Insufficient players to start the match"; + /** + * Called when a client requests external map data which it did not have + * Server serves the map file data and its preview to the client + * + * @param connection The connection of the client that requested the map data + * @param mapName The name of the map requested by the client + */ + public void serveMap(final Connection connection, final String mapName) { + Gdx.app.postRunnable(new Runnable() { + @Override + public void run() { + FileHandle externalMapDir = serverPlayerListener.getExternalMapDir(); + FileHandle mapFile = Gdx.files.external(externalMapDir + "/" + mapName + ".map"); + FileHandle mapPreviewFile = Gdx.files.external(externalMapDir + "/" + mapName + ".png"); + + MapEntity map = serverPlayerListener.fetchMap(mapName); + + BufferMapData bmd = new BufferMapData(); + bmd.mapName = mapName; + bmd.mapData = mapFile.readString(); + bmd.mapHash = map.getMapData().hashCode(); + if (mapPreviewFile.exists()) { + bmd.mapPreviewData = mapPreviewFile.readBytes(); + } else { + bmd.mapPreviewData = null; + } + + try { + connection.sendTCP(bmd); + } catch (KryoException e) { + // Probably a buffer overflow due to the map preview image being too big + Gdx.app.log(Constants.LOG_TAG, "Failed to serve map data (Is the map preview too large?): " + e.getMessage()); + Gdx.app.log(Constants.LOG_TAG, "Retrying to server without the map preview image..."); + + // Resend map data without the preview + bmd.mapPreviewData = null; + connection.sendTCP(bmd); + } + } + }); + } + + /** + * Sends the specified packets to only the accepted clients rather than all of them + * + * @param packet The object to send + */ + private void sentToAcceptedClients(Object packet) { + if (playerNameResolved.size == 0) { + return; + } + + Connection[] connections = server.getConnections(); + for (int i = 0; i < connections.length; i++) { + if (playerNameResolved.get(i)) { + connections[i].sendTCP(packet); + } } + } + /** + * Called to validate all data before starting the match + * + * @param playerItems The array of player data + * @return null if no errors, a string showing the error otherwise + */ + public String validateServerData(SnapshotArray playerItems) { for (int i = 1; i < playerItems.size; i++) { Table playerItem = (Table) playerItems.get(i); @@ -282,7 +349,7 @@ public String validateServerData(SnapshotArray playerItems) { public void broadcastGameStart() { BufferGameStart bgs = new BufferGameStart(); - server.sendToAllTCP(bgs); + sentToAcceptedClients(bgs); emptyBuffers(); } @@ -320,5 +387,9 @@ public interface ServerPlayerListener { void updatePlayerDetails(int index, String name, String who, String ready, String color, String startPos); void playerDisconnected(int itemIndex); + + FileHandle getExternalMapDir(); + + MapEntity fetchMap(String mapName); } } diff --git a/core/src/com/cg/zoned/maps/ExternalMapReader.java b/core/src/com/cg/zoned/maps/ExternalMapReader.java index d90c5c2..80efb90 100644 --- a/core/src/com/cg/zoned/maps/ExternalMapReader.java +++ b/core/src/com/cg/zoned/maps/ExternalMapReader.java @@ -39,7 +39,9 @@ private void setExternalMapDir() { // - On Desktop (Linux): /home// // - On Desktop (Windows): C:\Users\\ + externalMapDir = null; if (Gdx.app.getType() == Application.ApplicationType.Android) { + // Android externalMapDir = Gdx.files.external("Android/data/com.cg.zoned/files/" + mapDirName); } else if (Gdx.app.getType() == Application.ApplicationType.Desktop) { if (Gdx.files.getExternalStoragePath().startsWith("/home")) { @@ -66,6 +68,15 @@ public void scanAndParseExternalMaps() { } } + public void parseExternalMap(String mapName) { + FileHandle mapFile = externalMapDir.child(mapName + ".map"); + if (!mapFile.exists() || mapFile.isDirectory()) { + return; + } + + parseMap(mapFile); + } + private Array scanExternalMaps() { Array mapFiles = new Array<>(); @@ -92,56 +103,60 @@ private Array scanExternalMaps() { private void parseScannedMaps(Array mapFiles) { Gdx.app.log(Constants.LOG_TAG, "Preparing to parse the scanned maps"); for (FileHandle mapFile : mapFiles) { - String fileContents = mapFile.readString(); + parseMap(mapFile); + } + Gdx.app.log(Constants.LOG_TAG, "Map parsing completed"); + } - String mapGrid = null, mapName = mapFile.nameWithoutExtension(); - Array startPosNames = new Array<>(); - int rowCount = 0, colCount = 0; + private void parseMap(FileHandle mapFile) { + String fileContents = mapFile.readString(); - StringBuilder mapGridBuilder = new StringBuilder(); + String mapGrid = null, mapName = mapFile.nameWithoutExtension(); + Array startPosNames = new Array<>(); + int rowCount = 0, colCount = 0; - String rowCountPrompt = "Row count:"; - String colCountPrompt = "Col count:"; + StringBuilder mapGridBuilder = new StringBuilder(); - Pattern startPosPattern = Pattern.compile( - "(^[" + MapManager.VALID_START_POSITIONS.charAt(0) + "-" + MapManager.VALID_START_POSITIONS.charAt(MapManager.VALID_START_POSITIONS.length() - 1) + "])" + - ":(.*)", - Pattern.MULTILINE); + String rowCountPrompt = "Row count:"; + String colCountPrompt = "Col count:"; - String[] fileLines = fileContents.split("\r?\n"); - for (String fileLine : fileLines) { - if (fileLine.startsWith(rowCountPrompt)) { - rowCount = Integer.parseInt(fileLine.substring(rowCountPrompt.length()).trim()); - } else if (fileLine.startsWith(colCountPrompt)) { - colCount = Integer.parseInt(fileLine.substring(colCountPrompt.length()).trim()); - } else { - Matcher matcher = startPosPattern.matcher(fileLine); - if (matcher.matches()) { - char startPosChar = matcher.group(1).trim().charAt(0); - String startPosName = matcher.group(2).trim(); - - int index = startPosChar - MapManager.VALID_START_POSITIONS.charAt(0); - for (int j = startPosNames.size; j <= index; j++) { - startPosNames.add(null); - } - - startPosNames.set(index, startPosName); - } else { - mapGridBuilder.append(fileLine).append('\n'); + Pattern startPosPattern = Pattern.compile( + "(^[" + MapManager.VALID_START_POSITIONS.charAt(0) + "-" + MapManager.VALID_START_POSITIONS.charAt(MapManager.VALID_START_POSITIONS.length() - 1) + "])" + + ":(.*)", + Pattern.MULTILINE); + + String[] fileLines = fileContents.split("\r?\n"); + for (String fileLine : fileLines) { + if (fileLine.startsWith(rowCountPrompt)) { + rowCount = Integer.parseInt(fileLine.substring(rowCountPrompt.length()).trim()); + } else if (fileLine.startsWith(colCountPrompt)) { + colCount = Integer.parseInt(fileLine.substring(colCountPrompt.length()).trim()); + } else { + Matcher matcher = startPosPattern.matcher(fileLine); + if (matcher.matches()) { + char startPosChar = matcher.group(1).trim().charAt(0); + String startPosName = matcher.group(2).trim(); + + int index = startPosChar - MapManager.VALID_START_POSITIONS.charAt(0); + for (int j = startPosNames.size; j <= index; j++) { + startPosNames.add(null); } + + startPosNames.set(index, startPosName); + } else { + mapGridBuilder.append(fileLine).append('\n'); } } + } - mapGrid = mapGridBuilder.toString(); + mapGrid = mapGridBuilder.toString(); - if (!mapGrid.isEmpty() && mapName != null && rowCount > 0 && colCount > 0) { - loadedMaps.add(new ExternalMapTemplate(mapName, mapGrid, startPosNames, rowCount, colCount)); - Gdx.app.log(Constants.LOG_TAG, "Successfully parsed " + mapFile.name()); - } else { - Gdx.app.log(Constants.LOG_TAG, "Failed to parse " + mapFile.name()); - } + if (!mapGrid.isEmpty() && mapName != null && rowCount > 0 && colCount > 0) { + loadedMaps.add(new ExternalMapTemplate(mapName, mapGrid, startPosNames, rowCount, colCount)); + Gdx.app.log(Constants.LOG_TAG, "Successfully parsed " + mapFile.name()); + } else { + Gdx.app.log(Constants.LOG_TAG, "Failed to parse " + mapFile.name()); } - Gdx.app.log(Constants.LOG_TAG, "Map parsing completed"); } public Array getLoadedMaps() { diff --git a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java index 47d6fe0..e821f30 100644 --- a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.ScreenAdapter; +import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; @@ -106,7 +107,12 @@ public void show() { animationManager.setAnimationListener(new AnimationManager.AnimationListener() { @Override public void animationEnd(Stage stage) { - connectionManager.sendClientNameToServer(clientName); + mapManager.loadExternalMaps(new MapManager.OnExternalMapLoadListener() { + @Override + public void onExternalMapLoaded(Array mapList, int externalMapStartIndex) { + connectionManager.sendClientNameToServer(clientName); + } + }); animationManager.setAnimationListener(null); } }); @@ -138,9 +144,9 @@ private void setUpClientLobbyStage() { clientLobbyTable.row(); readyButton = new TextButton("Ready up", game.skin); - readyButton.addListener(new ClickListener() { + readyButton.addListener(new ChangeListener() { @Override - public void clicked(InputEvent event, float x, float y) { + public void changed(ChangeEvent event, Actor actor) { Table playerItem = (Table) playerList.getChild(0); Label readyLabel = playerItem.findActor("ready-label"); DropDownMenu colorSelector = playerItem.findActor("color-selector"); @@ -153,6 +159,7 @@ public void clicked(InputEvent event, float x, float y) { //colorSelector.setDisabled(true); Why is there literally no visual indication for being disabled :/ //startPosSelector.setDisabled(true); + // TODO: Disable options once user is ready } else { readyLabel.setColor(Color.RED); readyLabel.setText("Not ready"); @@ -196,18 +203,21 @@ public void clicked(InputEvent event, float x, float y) { }); } + public void performClick(Actor actor) { + InputEvent touchDownEvent = new InputEvent(); + touchDownEvent.setType(InputEvent.Type.touchDown); + actor.fire(touchDownEvent); + + InputEvent touchUpEvent = new InputEvent(); + touchUpEvent.setType(InputEvent.Type.touchUp); + actor.fire(touchUpEvent); + } + @Override public void pause() { if (readyButton.getText().toString().equals("Unready")) { // Game was minimized in the mobile; so make the player unready - - InputEvent touchDownEvent = new InputEvent(); - touchDownEvent.setType(InputEvent.Type.touchDown); - readyButton.fire(touchDownEvent); - - InputEvent touchUpEvent = new InputEvent(); - touchUpEvent.setType(InputEvent.Type.touchUp); - readyButton.fire(touchUpEvent); + performClick(readyButton); } } @@ -344,11 +354,31 @@ private void addNewPlayerIntoMap(String name, String color, String startPos) { } @Override - public void mapChanged(String mapName, int[] mapExtraParams) { + public FileHandle getExternalMapDir() { + return this.mapManager.getExternalMapDir(); + } + + @Override + public void mapChanged(final String mapName, final int[] mapExtraParams, final int mapHash, boolean isNewMap) { + if (readyButton.getText().toString().equals("Unready")) { + performClick(readyButton); + } + + if (isNewMap) { + // If true, a new external map was just downloaded from the server + + this.mapManager.loadExternalMap(mapName); + this.mapLabel.setText(""); + } + + setMap(mapName, mapExtraParams, mapHash); + } + + private void setMap(String mapName, int[] mapExtraParams, int mapHash) { startLocations.clear(); MapManager mapManager = this.mapManager; - if (!loadNewMap(mapManager, mapName, mapExtraParams)) { + if (!loadNewMap(mapManager, mapName, mapExtraParams, mapHash)) { return; } @@ -374,6 +404,7 @@ public void mapChanged(String mapName, int[] mapExtraParams) { resetStartPosLabels(startLocations); this.mapLabel.setText(mapManager.getPreparedMap().getName()); + readyButton.setDisabled(false); } private void resetStartPosLabels(Array startLocations) { @@ -390,11 +421,13 @@ private void resetStartPosLabels(Array startLocations) { } } - private boolean loadNewMap(MapManager mapManager, String mapName, int[] mapExtraParams) { + private boolean loadNewMap(MapManager mapManager, String mapName, int[] mapExtraParams, int serverMapHash) { MapEntity map = mapManager.getMap(mapName); if (map == null) { - // Should never happen cause server loads a valid internal map before sending it to all the clients - displayServerError("Unknown map received: '" + mapName + "'"); + // Server probably selected an external map which is unavailable in the client + this.mapLabel.setText("Downloading map '" + mapName + "'"); + connectionManager.requestMap(mapName); + readyButton.setDisabled(true); return false; } @@ -403,6 +436,15 @@ private boolean loadNewMap(MapManager mapManager, String mapName, int[] mapExtra map.applyExtraParams(); } + int clientMapHash = map.getMapData().hashCode(); + if (clientMapHash != serverMapHash) { + // Map in the server and client have the same name, but different contents + displayServerError("Server client map content mismatch!\n" + + "Looks like the map content for the map '" + mapName + "'\n is different for you and the server\n" + + "(Server: " + serverMapHash + ", Client: " + clientMapHash + ")"); + return false; + } + try { mapManager.prepareMap(map); } catch (InvalidMapCharacter | NoStartPositionsFound | InvalidMapDimensions e) { @@ -652,7 +694,10 @@ public void dispose() { for (Texture texture : usedTextures) { texture.dispose(); } - map.dispose(); + if (map != null) { + map.dispose(); + map = null; + } } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/HostJoinScreen.java b/core/src/com/cg/zoned/screens/HostJoinScreen.java index d747c64..2e938d1 100644 --- a/core/src/com/cg/zoned/screens/HostJoinScreen.java +++ b/core/src/com/cg/zoned/screens/HostJoinScreen.java @@ -40,6 +40,9 @@ public class HostJoinScreen extends ScreenAdapter implements InputProcessor { final Zoned game; + // Bigger buffer as map preview images, which is bigger than text data, are sent + private static final int CONNECTION_BUFFER_SIZE = 131072; // 2^17 + private Array usedTextures = new Array<>(); private FocusableStage stage; @@ -179,7 +182,7 @@ public void clicked(InputEvent event, float x, float y) { } private void startServerLobby(final String playerName) { - final Server server = new Server(); + final Server server = new Server(CONNECTION_BUFFER_SIZE, 2048); Kryo kryo = server.getKryo(); KryoHelper.registerClasses(kryo); @@ -199,7 +202,7 @@ private void startServerLobby(final String playerName) { } private void startClientLobby(final String playerName, final Label searchingLabel) { - final Client client = new Client(); + final Client client = new Client(8192, CONNECTION_BUFFER_SIZE); Kryo kryo = client.getKryo(); KryoHelper.registerClasses(kryo); diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index f285bbb..4a282d4 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -12,6 +12,7 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.ParticleEffect; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; @@ -23,7 +24,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Stack; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Scaling; @@ -51,7 +51,7 @@ public class MainMenuScreen extends ScreenAdapter implements InputProcessor { private AnimationManager animationManager; private boolean showFPSCounter; private BitmapFont font; - private Texture roundedCornerBgColorTexture; + private NinePatch roundedCornerNP; private ParticleEffect emitterLeft, emitterRight; @@ -88,14 +88,16 @@ public void animationEnd(Stage stage) { new Thread(new Runnable() { @Override public void run() { - final Pixmap pixmap = getRoundedCornerPixmap(Color.GREEN, 480, 640, 50); - // I suspect pixmap generation caused a noticeable lag so run in a new thread + final int radius = 40; + final int width = 10 + (radius * 2); + final int height = 10 + (radius * 2); + final Pixmap pixmap = getRoundedCornerPixmap(Color.GREEN, width, height, radius); Gdx.app.postRunnable(new Runnable() { @Override public void run() { - roundedCornerBgColorTexture = new Texture(pixmap); + Texture roundedCornerBgColorTexture = new Texture(pixmap); usedTextures.add(roundedCornerBgColorTexture); - // TODO: Try to Ninepatchify this + roundedCornerNP = new NinePatch(roundedCornerBgColorTexture, radius, radius, radius, radius); pixmap.dispose(); } }); @@ -117,6 +119,8 @@ private void setUpMainMenu() { mainStage.addFocusableActor(playButton); mainStage.row(); + // TODO: Button ClickListener -> ChangeListener? Research. + UIButtonManager uiButtonManager = new UIButtonManager(mainStage, game.getScaleFactor(), usedTextures); HoverImageButton settingsButton = uiButtonManager.addSettingsButtonToStage(game.assets.getSettingsButtonTexture()); HoverImageButton creditsButton = uiButtonManager.addCreditsButtonToStage(game.assets.getCreditsButtonTexture()); @@ -205,7 +209,7 @@ private HoverImageButton setUpAnimatedPlayButton(Table mainTable) { playButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - if (roundedCornerBgColorTexture == null) { + if (roundedCornerNP == null) { // Thread didn't finish loading the pixmap // Should almost never happen cause processors are hella fast, even mobile ones return; @@ -236,8 +240,6 @@ private void setUpPlayMenu() { final int gameModeCount = 2; - TextureRegionDrawable whiteBG = new TextureRegionDrawable(roundedCornerBgColorTexture); - String[] backgroundImageLocations = new String[]{ "icons/multiplayer_icons/ic_splitscreen_multiplayer.png", "icons/multiplayer_icons/ic_local_multiplayer.png", @@ -251,6 +253,8 @@ private void setUpPlayMenu() { HostJoinScreen.class, }; + // TODO: Clean up this mess using an object + if (screenClasses.length != gameModeCount || modeLabelStrings.length != gameModeCount || backgroundImageLocations.length != gameModeCount) { @@ -264,7 +268,7 @@ private void setUpPlayMenu() { Table table = new Table(); table.center(); - final Image backgroundColorImage = new Image(whiteBG); + final Image backgroundColorImage = new Image(roundedCornerNP); backgroundColorImage.getColor().a = normalAlpha; backgroundColorImage.setScaling(Scaling.stretch); @@ -323,9 +327,16 @@ public void clicked(InputEvent event, float x, float y) { Stack stack = new Stack(backgroundColorImage, backgroundImage, modeLabel); - table.add(stack).expand().pad(40f); + float optionPadding = 50f; + if (i == 0) { + table.add(stack).grow().padLeft(optionPadding).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding / 2); + } else if (i == gameModeCount - 1) { + table.add(stack).grow().padLeft(optionPadding / 2).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding); + } else { + table.add(stack).grow().padLeft(optionPadding / 2).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding / 2); + } - playModeTable.add(table).expand().uniform(); + playModeTable.add(table).grow().uniform(); playModeStage.addFocusableActor(table); } diff --git a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java index 3ac99dc..605f660 100644 --- a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.ScreenAdapter; +import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; @@ -39,6 +40,7 @@ import com.cg.zoned.managers.MapManager; import com.cg.zoned.managers.ServerLobbyConnectionManager; import com.cg.zoned.managers.UIButtonManager; +import com.cg.zoned.maps.MapEntity; import com.cg.zoned.ui.DropDownMenu; import com.cg.zoned.ui.FocusableStage; import com.cg.zoned.ui.HoverImageButton; @@ -84,6 +86,8 @@ public ServerLobbyScreen(final Zoned game, Server server, String name) { animationManager = new AnimationManager(this.game, this); font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getName()); + // TODO: Fix bogus client ip being sent to some clients when a map is changed while a new client was joining + startLocations = new Array<>(); this.serverName = name; this.connectionManager = new ServerLobbyConnectionManager(server, this); @@ -165,7 +169,7 @@ public void dialogResult(String buttonText) { }, game.skin); } }); - // mapSelector.loadExternalMaps(); Not yet + mapSelector.loadExternalMaps(); serverLobbyTable.add(mapButton).width(200f * game.getScaleFactor()); serverLobbyTable.row(); @@ -336,7 +340,8 @@ public void updatePlayerDetails(int playerIndex, String clientName) { Label nameLabel = playerItem.findActor("name-label"); nameLabel.setText(clientName); - connectionManager.acceptPlayer(playerIndex, mapSelector.getMapManager()); + connectionManager.acceptPlayer(playerIndex); + connectionManager.sendMapDetails(playerIndex, mapSelector.getMapManager()); connectionManager.broadcastPlayerInfo(playerList.getChildren(), -1); // Send info about the new player to other clients and vice-versa } @@ -400,6 +405,16 @@ private void mapChanged(Array startLocations) { connectionManager.sendMapDetails(-1, mapSelector.getMapManager()); } + @Override + public FileHandle getExternalMapDir() { + return this.mapSelector.getMapManager().getExternalMapDir(); + } + + @Override + public MapEntity fetchMap(String mapName) { + return this.mapSelector.getMapManager().getMap(mapName); + } + private void startGame(MapManager mapManager) { Player[] players = inflatePlayerList(mapManager); clearMapGrid(); @@ -576,7 +591,10 @@ public void dispose() { for (Texture texture : usedTextures) { texture.dispose(); } - map.dispose(); + if (map != null) { + map.dispose(); + map = null; + } } private void onBackPressed() { diff --git a/desktop/build.gradle b/desktop/build.gradle index 2ac780f..7574f90 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -6,7 +6,7 @@ sourceSets.main.java.srcDirs = [ "src/" ] project.ext.mainClassName = "com.cg.zoned.desktop.DesktopLauncher" project.ext.assetsDir = new File("../android/assets") project.setProperty("archivesBaseName", appName) -project.setVersion("0.0.2-beta") +project.setVersion("0.0.3-dev") // Remember to update the GAME_VERSION in Constants.java // And versionName in Android's build.gradle // And the version in the badge in the README file diff --git a/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java b/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java index 313c4fa..b534f64 100644 --- a/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java +++ b/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java @@ -10,6 +10,7 @@ public class DesktopLauncher { public static void main(String[] args) { if (args.length > 0 && !args[0].equals(Constants.GAME_VERSION)) { // Used as a precaution + // TODO: Too annoying. Remove? System.err.println("GAME VERSION MISMATCH (" + args[0] + " and " + Constants.GAME_VERSION + ")"); return; } From a10a58ccdc6374cb4db99fd1cd9fe3ff923f3246 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 26 Aug 2020 16:58:06 +0530 Subject: [PATCH 11/35] Fixed incorrect grid color fade-in when they were not visible earlier Also, removed annoying args restriction for the desktop launcher. Furthermore, first GitHub Action test yay --- core/src/com/cg/zoned/Map.java | 13 +++++++------ .../src/com/cg/zoned/desktop/DesktopLauncher.java | 8 -------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index 13996fe..884b707 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -389,17 +389,18 @@ private void drawColors(ShapeDrawer shapeDrawer, Rectangle userViewRect, float d float startX = j * Constants.CELL_SIZE; float startY = i * Constants.CELL_SIZE; - if (mapGrid[i][j].cellColor != null && userViewRect.contains(startX, startY)) { - shapeDrawer.setColor(mapGrid[i][j].cellColor); - shapeDrawer.filledRectangle(startX, startY, - Constants.CELL_SIZE, Constants.CELL_SIZE); - - mapGrid[i][j].cellColor.add(0, 0, 0, 2f * delta); + if (mapGrid[i][j].cellColor != null) { + if (userViewRect.contains(startX, startY)) { + shapeDrawer.setColor(mapGrid[i][j].cellColor); + shapeDrawer.filledRectangle(startX, startY, Constants.CELL_SIZE, Constants.CELL_SIZE); + } // Use the constant color object to avoid too many redundant color objects Color constColor = PlayerColorHelper.getConstantColor(mapGrid[i][j].cellColor); if (constColor != null) { mapGrid[i][j].cellColor = constColor; + } else { + mapGrid[i][j].cellColor.add(0, 0, 0, 2f * delta); } } } diff --git a/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java b/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java index b534f64..6c80b03 100644 --- a/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java +++ b/desktop/src/com/cg/zoned/desktop/DesktopLauncher.java @@ -3,18 +3,10 @@ import com.badlogic.gdx.Files; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; -import com.cg.zoned.Constants; import com.cg.zoned.Zoned; public class DesktopLauncher { public static void main(String[] args) { - if (args.length > 0 && !args[0].equals(Constants.GAME_VERSION)) { - // Used as a precaution - // TODO: Too annoying. Remove? - System.err.println("GAME VERSION MISMATCH (" + args[0] + " and " + Constants.GAME_VERSION + ")"); - return; - } - LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); config.title = "Zoned"; config.vSyncEnabled = true; From 965c85f1819f71d20a0feb8ff9ac58bcc11ff961 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 26 Aug 2020 17:03:18 +0530 Subject: [PATCH 12/35] GitHub Actions workflow file --- .github/workflows/release-snapshot.yml | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/release-snapshot.yml diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml new file mode 100644 index 0000000..65840d2 --- /dev/null +++ b/.github/workflows/release-snapshot.yml @@ -0,0 +1,41 @@ +name: Auto publish development releases (Bleeding edge releases) for Desktop + +# Controls when the action will run +on: + push: + branches: + - dev + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # Workflows + jar: + runs-on: ubuntu-latest + + steps: + - name: Checkout dev branch + uses: actions/checkout@v2 + with: + repository: dev + + - name: Set up JDK 8 + uses: actions/setup-java@v1.4.2 + with: + java-version: 1.8 + + - name: Fix gradlew file permissions + run: chmod +x gradlew + + - name: Build jar + run: ./gradlew desktop:dist + + - name: Upload jar as a release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: desktop/build/libs/*.jar + file_glob: true + tag: ${{ github.ref }} + overwrite: true + prerelease: true + body: "Latest bleeding edge version of Zoned. Might be buggy" From cb922c3e89ccff8740c7133da6482b4a564846fc Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 26 Aug 2020 17:11:35 +0530 Subject: [PATCH 13/35] Fixed checkout step params --- .github/workflows/release-snapshot.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 65840d2..474c726 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -15,8 +15,6 @@ jobs: steps: - name: Checkout dev branch uses: actions/checkout@v2 - with: - repository: dev - name: Set up JDK 8 uses: actions/setup-java@v1.4.2 From ec66381d5df9353c066015f5c7bd5acb7776b797 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 26 Aug 2020 19:48:43 +0530 Subject: [PATCH 14/35] Cleanup for game modes --- core/src/com/cg/zoned/GameMode.java | 13 +++++ .../com/cg/zoned/screens/MainMenuScreen.java | 53 ++++++++----------- 2 files changed, 35 insertions(+), 31 deletions(-) create mode 100644 core/src/com/cg/zoned/GameMode.java diff --git a/core/src/com/cg/zoned/GameMode.java b/core/src/com/cg/zoned/GameMode.java new file mode 100644 index 0000000..b72d6ac --- /dev/null +++ b/core/src/com/cg/zoned/GameMode.java @@ -0,0 +1,13 @@ +package com.cg.zoned; + +public class GameMode { + public String previewLocation; + public String name; + public Class targetClass; + + public GameMode(String name, String previewLocation, Class targetClass) { + this.name = name; + this.previewLocation = previewLocation; + this.targetClass = targetClass; + } +} diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index 4a282d4..a1339b3 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -30,6 +30,7 @@ import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; import com.cg.zoned.Constants; +import com.cg.zoned.GameMode; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -238,33 +239,15 @@ private void setUpPlayMenu() { playModeTable.add(chooseMode).expandX().pad(20f).colspan(2); playModeTable.row(); - final int gameModeCount = 2; - - String[] backgroundImageLocations = new String[]{ - "icons/multiplayer_icons/ic_splitscreen_multiplayer.png", - "icons/multiplayer_icons/ic_local_multiplayer.png", - }; - String[] modeLabelStrings = new String[]{ - "Splitscreen\nMultiplayer", - "Local\nNetwork\nMultiplayer", - }; - final Class[] screenClasses = new Class[]{ - PlayerSetUpScreen.class, - HostJoinScreen.class, + final GameMode[] gameModes = new GameMode[]{ + new GameMode("Splitscreen\nMultiplayer", "icons/multiplayer_icons/ic_splitscreen_multiplayer.png", PlayerSetUpScreen.class), + new GameMode("Local\nNetwork\nMultiplayer", "icons/multiplayer_icons/ic_local_multiplayer.png", HostJoinScreen.class), }; - // TODO: Clean up this mess using an object - - if (screenClasses.length != gameModeCount || - modeLabelStrings.length != gameModeCount || - backgroundImageLocations.length != gameModeCount) { - throw new IndexOutOfBoundsException("Game mode count does not match asset the count"); - } - final float normalAlpha = .15f; final float hoverAlpha = .3f; final float clickAlpha = .7f; - for (int i = 0; i < gameModeCount; i++) { + for (int i = 0; i < gameModes.length; i++) { Table table = new Table(); table.center(); @@ -272,13 +255,16 @@ private void setUpPlayMenu() { backgroundColorImage.getColor().a = normalAlpha; backgroundColorImage.setScaling(Scaling.stretch); - Texture backgroundImageTexture = new Texture(Gdx.files.internal(backgroundImageLocations[i])); - usedTextures.add(backgroundImageTexture); - Image backgroundImage = new Image(backgroundImageTexture); - backgroundImage.setScaling(Scaling.fit); - backgroundImage.getColor().a = .3f; + Image backgroundImage = null; + if (gameModes[i].previewLocation != null) { + Texture backgroundImageTexture = new Texture(Gdx.files.internal(gameModes[i].previewLocation)); + usedTextures.add(backgroundImageTexture); + backgroundImage = new Image(backgroundImageTexture); + backgroundImage.setScaling(Scaling.fit); + backgroundImage.getColor().a = .3f; + } - Label modeLabel = new Label(modeLabelStrings[i], game.skin); + Label modeLabel = new Label(gameModes[i].name, game.skin); modeLabel.setAlignment(Align.center); final int finalI = i; @@ -318,19 +304,24 @@ public void clicked(InputEvent event, float x, float y) { emitterLeft.allowCompletion(); emitterRight.allowCompletion(); try { - animationManager.fadeOutStage(playModeStage, MainMenuScreen.this, (Screen) screenClasses[finalI].getConstructors()[0].newInstance(game)); + animationManager.fadeOutStage(playModeStage, MainMenuScreen.this, (Screen) gameModes[finalI].targetClass.getConstructors()[0].newInstance(game)); } catch (Exception e) { e.printStackTrace(); } } }); - Stack stack = new Stack(backgroundColorImage, backgroundImage, modeLabel); + Stack stack; + if (backgroundImage != null) { + stack = new Stack(backgroundColorImage, backgroundImage, modeLabel); + } else { + stack = new Stack(backgroundColorImage, modeLabel); + } float optionPadding = 50f; if (i == 0) { table.add(stack).grow().padLeft(optionPadding).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding / 2); - } else if (i == gameModeCount - 1) { + } else if (i == gameModes.length - 1) { table.add(stack).grow().padLeft(optionPadding / 2).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding); } else { table.add(stack).grow().padLeft(optionPadding / 2).padTop(optionPadding).padBottom(optionPadding).padRight(optionPadding / 2); From 46fc62f2353db8c0035223c4a69ae0d5bc90643d Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 26 Aug 2020 20:05:05 +0530 Subject: [PATCH 15/35] Corrections in the workflow file --- .github/workflows/release-snapshot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 474c726..3edba19 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -1,4 +1,4 @@ -name: Auto publish development releases (Bleeding edge releases) for Desktop +name: Publish development release # Controls when the action will run on: @@ -26,14 +26,14 @@ jobs: - name: Build jar run: ./gradlew desktop:dist - + - name: Upload jar as a release uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: desktop/build/libs/*.jar file_glob: true - tag: ${{ github.ref }} + tag: v-dev overwrite: true prerelease: true body: "Latest bleeding edge version of Zoned. Might be buggy" From 125f859df9894d595f28759eb944ec2f64c87f63 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 28 Aug 2020 16:26:46 +0530 Subject: [PATCH 16/35] Crisper player labels, workflow master pull --- .github/workflows/release-snapshot.yml | 24 +++++++++++++++++++++++- core/src/com/cg/zoned/Constants.java | 3 ++- core/src/com/cg/zoned/Map.java | 10 ++++++---- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 3edba19..f74364c 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -27,7 +27,18 @@ jobs: - name: Build jar run: ./gradlew desktop:dist - - name: Upload jar as a release + - name: Build apk + run: ./gradlew android:assembleDebug + + - name: Cleanup previous tags and releases + uses: dev-drprasad/delete-tag-and-release@v0.1.2 + with: + delete_release: true + tag_name: v-dev + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload jar release uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -37,3 +48,14 @@ jobs: overwrite: true prerelease: true body: "Latest bleeding edge version of Zoned. Might be buggy" + + - name: Upload apk release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: android/build/outputs/apk/debug/*.apk + file_glob: true + tag: v-dev + overwrite: true + prerelease: true + diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 0bcb671..4365c60 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -113,7 +113,8 @@ public enum FONT_MANAGER { LARGE("large-font", 80), REGULAR("regular-font", 32), SMALL("small-font", 18), - PLAYER_LABEL("player-label-font-noscale", 20); + PLAYER_LABEL("player-label-font-noscale", // Height based on cell size minus a bit of line width as calculated below + (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (3 * Constants.MAP_GRID_LINE_WIDTH / 2)))); private String name; private int size; diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index 884b707..ace6e52 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -33,10 +33,11 @@ public class Map { private Rectangle userViewRect = null; private FrameBuffer playerLabelFbo = null; + public static float playerLabelRegionScale = 2f; // Rendered at higher (2x rn) res, downscaled to required size private TextureRegion[] playerLabels = null; private FrameBuffer playerFbo = null; - private float playerTextureRegionScale = 2f; + public static float playerTextureRegionScale = 2f; // Rendered at higher (2x rn) res, downscaled to required size private TextureRegion playerTextureRegion = null; private FrameBuffer mapFbo = null; @@ -123,7 +124,7 @@ public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, int totalHeight = (((int) (playerLabelFont.getLineHeight() - (Constants.MAP_GRID_LINE_WIDTH / 2))) * players.length); int height = totalHeight / players.length; - int width = (int) (Constants.CELL_SIZE * 3f); + int width = (int) (((int) (Constants.CELL_SIZE * 3f)) * playerLabelRegionScale); float radius = height / 2f; Batch batch = shapeDrawer.getBatch(); @@ -414,11 +415,12 @@ private void drawGrid(Batch batch) { public void drawPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { if (playerLabels != null) { for (int i = 0; i < players.length; i++) { - float posX = (players[i].position.x * Constants.CELL_SIZE) - (playerLabels[i].getRegionWidth() / 2f) + (Constants.CELL_SIZE / 2); + float posX = (players[i].position.x * Constants.CELL_SIZE) - (playerLabels[i].getRegionWidth() / (playerLabelRegionScale * 2f)) + (Constants.CELL_SIZE / 2); float posY = (players[i].position.y * Constants.CELL_SIZE) + Constants.CELL_SIZE + (Constants.MAP_GRID_LINE_WIDTH / 2); if (userViewRect.contains(posX + playerLabels[i].getRegionWidth(), posY - (Constants.CELL_SIZE / 2)) || userViewRect.contains(posX, posY - (Constants.CELL_SIZE / 2))) { - batch.draw(playerLabels[i], posX, posY); + batch.draw(playerLabels[i], posX, posY, + playerLabels[i].getRegionWidth() / playerLabelRegionScale, playerLabels[i].getRegionHeight() / playerLabelRegionScale); } } } From d6fe1cf8d6408fb05934771de23654bab7d73648 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 28 Aug 2020 17:03:22 +0530 Subject: [PATCH 17/35] CI: Install required NDK --- .github/workflows/release-snapshot.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index f74364c..1e2933d 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -9,7 +9,7 @@ on: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # Workflows - jar: + release_development_builds: runs-on: ubuntu-latest steps: @@ -21,6 +21,9 @@ jobs: with: java-version: 1.8 + - name: Install NDK + run: echo "y" | sudo /usr/local/lib/android/sdk/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT} + - name: Fix gradlew file permissions run: chmod +x gradlew From 363ec07f3619f2fd9754b255d5ccf2afafc4784f Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 28 Aug 2020 17:19:10 +0530 Subject: [PATCH 18/35] CI: Default release name --- .github/workflows/release-snapshot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 1e2933d..83c80c3 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -50,6 +50,7 @@ jobs: tag: v-dev overwrite: true prerelease: true + release_name: "Zoned Developer Build" body: "Latest bleeding edge version of Zoned. Might be buggy" - name: Upload apk release From 77633824645a7c653d6e2417084d769c471f76fd Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Sat, 29 Aug 2020 09:33:11 +0530 Subject: [PATCH 19/35] Current player label is rendered on top of others --- .github/workflows/release-snapshot.yml | 1 + core/src/com/cg/zoned/Constants.java | 2 +- core/src/com/cg/zoned/Map.java | 32 ++++++++++++++----- core/src/com/cg/zoned/screens/GameScreen.java | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 83c80c3..8bb507f 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -62,4 +62,5 @@ jobs: tag: v-dev overwrite: true prerelease: true + release_name: "Zoned Developer Build" diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 4365c60..46bfb41 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -114,7 +114,7 @@ public enum FONT_MANAGER { REGULAR("regular-font", 32), SMALL("small-font", 18), PLAYER_LABEL("player-label-font-noscale", // Height based on cell size minus a bit of line width as calculated below - (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (3 * Constants.MAP_GRID_LINE_WIDTH / 2)))); + (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (2 * Constants.MAP_GRID_LINE_WIDTH)))); private String name; private int size; diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index ace6e52..d49df7c 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -368,6 +368,10 @@ private Rectangle calcUserViewRect(OrthographicCamera camera) { } public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera camera, float delta) { + render(players, 0, shapeDrawer, camera, delta); + } + + public void render(Player[] players, int playerIndex, ShapeDrawer shapeDrawer, OrthographicCamera camera, float delta) { Rectangle userViewRect = calcUserViewRect(camera); Batch batch = shapeDrawer.getBatch(); @@ -375,7 +379,7 @@ public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera drawColors(shapeDrawer, userViewRect, delta); drawGrid(batch); drawPlayers(players, userViewRect, batch); - drawPlayerLabels(players, userViewRect, batch); + drawPlayerLabels(players, playerIndex, userViewRect, batch); } private void drawPlayers(Player[] players, Rectangle userViewRect, Batch batch) { @@ -391,6 +395,8 @@ private void drawColors(ShapeDrawer shapeDrawer, Rectangle userViewRect, float d float startY = i * Constants.CELL_SIZE; if (mapGrid[i][j].cellColor != null) { + // TODO: Performance wise taxing part? + if (userViewRect.contains(startX, startY)) { shapeDrawer.setColor(mapGrid[i][j].cellColor); shapeDrawer.filledRectangle(startX, startY, Constants.CELL_SIZE, Constants.CELL_SIZE); @@ -412,17 +418,27 @@ private void drawGrid(Batch batch) { batch.draw(mapTextureRegion, -Constants.MAP_GRID_LINE_WIDTH / 2, -Constants.MAP_GRID_LINE_WIDTH / 2); } - public void drawPlayerLabels(Player[] players, Rectangle userViewRect, Batch batch) { + public void drawPlayerLabels(Player[] players, int playerIndex, Rectangle userViewRect, Batch batch) { if (playerLabels != null) { for (int i = 0; i < players.length; i++) { - float posX = (players[i].position.x * Constants.CELL_SIZE) - (playerLabels[i].getRegionWidth() / (playerLabelRegionScale * 2f)) + (Constants.CELL_SIZE / 2); - float posY = (players[i].position.y * Constants.CELL_SIZE) + Constants.CELL_SIZE + (Constants.MAP_GRID_LINE_WIDTH / 2); - if (userViewRect.contains(posX + playerLabels[i].getRegionWidth(), posY - (Constants.CELL_SIZE / 2)) || - userViewRect.contains(posX, posY - (Constants.CELL_SIZE / 2))) { - batch.draw(playerLabels[i], posX, posY, - playerLabels[i].getRegionWidth() / playerLabelRegionScale, playerLabels[i].getRegionHeight() / playerLabelRegionScale); + if (i == playerIndex) { + continue; } + renderPlayerLabel(players[i], playerLabels[i], userViewRect, batch); } + + // Render the current player's label on top of other labels + renderPlayerLabel(players[playerIndex], playerLabels[playerIndex], userViewRect, batch); + } + } + + private void renderPlayerLabel(Player player, TextureRegion playerLabel, Rectangle userViewRect, Batch batch) { + float posX = (player.position.x * Constants.CELL_SIZE) - (playerLabel.getRegionWidth() / (playerLabelRegionScale * 2f)) + (Constants.CELL_SIZE / 2); + float posY = (player.position.y * Constants.CELL_SIZE) + Constants.CELL_SIZE + (Constants.MAP_GRID_LINE_WIDTH / 2); + if (userViewRect.contains(posX + playerLabel.getRegionWidth(), posY - (Constants.CELL_SIZE / 2)) || + userViewRect.contains(posX, posY - (Constants.CELL_SIZE / 2))) { + batch.draw(playerLabel, posX, posY, + playerLabel.getRegionWidth() / playerLabelRegionScale, playerLabel.getRegionHeight() / playerLabelRegionScale); } } diff --git a/core/src/com/cg/zoned/screens/GameScreen.java b/core/src/com/cg/zoned/screens/GameScreen.java index ebad886..5ea40c5 100644 --- a/core/src/com/cg/zoned/screens/GameScreen.java +++ b/core/src/com/cg/zoned/screens/GameScreen.java @@ -322,7 +322,7 @@ private void renderMap(int index, float delta) { batch.setProjectionMatrix(viewport.getCamera().combined); batch.begin(); - map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + map.render(players, index, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); batch.end(); } From 95af7c6cb2c9797911385e7771c8923d6ea12c03 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Sun, 30 Aug 2020 20:28:30 +0530 Subject: [PATCH 20/35] Player labels in the map select screen because why not ;-) --- .../src/com/cg/zoned/screens/MapStartPosScreen.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/src/com/cg/zoned/screens/MapStartPosScreen.java b/core/src/com/cg/zoned/screens/MapStartPosScreen.java index bd6ef78..cd0e9d9 100644 --- a/core/src/com/cg/zoned/screens/MapStartPosScreen.java +++ b/core/src/com/cg/zoned/screens/MapStartPosScreen.java @@ -113,6 +113,7 @@ public void show() { private void setUpMap() { map = new Map(mapGrid, 0, shapeDrawer); // Wall count is unnecessary in this case so 0 + map.createPlayerLabelTextures(players, shapeDrawer, game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getName())); mapDarkOverlayColor = new Color(0, 0, 0, 0.8f); mapViewports = new ExtendViewport[splitScreenCount]; for (int i = 0; i < players.length; i++) { @@ -399,14 +400,16 @@ public void clicked(InputEvent event, float x, float y) { }); } - private void focusAndRenderViewport(Viewport viewport, Player player, Vector2 vel, float delta) { - focusCameraOnPlayer(viewport, player, vel, delta); + private void renderMap(int playerIndex, float delta) { + int mapViewportIndex = playerIndex - this.playerIndex; + Viewport viewport = mapViewports[mapViewportIndex]; + + focusCameraOnPlayer(viewport, players[playerIndex], dragOffset[mapViewportIndex], delta); viewport.apply(); batch.setProjectionMatrix(viewport.getCamera().combined); - batch.begin(); - map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + map.render(players, playerIndex, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); batch.end(); } @@ -481,7 +484,7 @@ public void render(float delta) { for (int i = 0; i < mapViewports.length; i++) { if (playerIndex + i < players.length) { - focusAndRenderViewport(mapViewports[i], players[playerIndex + i], dragOffset[i], delta); + renderMap(playerIndex + i, delta); } } From 82bbc68a32568dc555ee1d69a5147c7598d42e4e Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Mon, 31 Aug 2020 13:09:47 +0530 Subject: [PATCH 21/35] Improved performance when there are many cells filled --- core/src/com/cg/zoned/Constants.java | 10 +++++----- core/src/com/cg/zoned/Map.java | 16 +++++----------- core/src/com/cg/zoned/PlayerColorHelper.java | 7 ++++++- .../com/cg/zoned/managers/ControlManager.java | 1 - core/src/com/cg/zoned/screens/LoadingScreen.java | 2 ++ .../com/cg/zoned/screens/MapStartPosScreen.java | 5 ----- .../src/com/cg/zoned/screens/TutorialScreen.java | 3 ++- 7 files changed, 20 insertions(+), 24 deletions(-) diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 46bfb41..784f5e2 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -57,11 +57,11 @@ public final class Constants { */ public static final Map PLAYER_COLORS = new LinkedHashMap() { { - put("GREEN", new Color(0, 0.8f, 0, 1.0f)); - put("RED", new Color(0.8f, 0, 0, 1.0f)); - put("BLUE", new Color(0, 0, 0.8f, 1.0f)); - put("YELLOW", new Color(0.8f, 0.8f, 0, 1.0f)); - put("PINK", new Color(0.8f, 0, 0.8f, 1.0f)); + put("GREEN", new Color(0, 0.8f, 0, 1.0f)); // Alpha won't matter + put("RED", new Color(0.8f, 0, 0, 1.0f)); + put("BLUE", new Color(0, 0, 0.8f, 1.0f)); + put("YELLOW", new Color(0.8f, 0.8f, 0, 1.0f)); + put("PINK", new Color(0.8f, 0, 0.8f, 1.0f)); } }; diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index d49df7c..f3f2f73 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -376,7 +376,7 @@ public void render(Player[] players, int playerIndex, ShapeDrawer shapeDrawer, O Batch batch = shapeDrawer.getBatch(); - drawColors(shapeDrawer, userViewRect, delta); + drawColors(shapeDrawer, playerIndex, userViewRect, delta); drawGrid(batch); drawPlayers(players, userViewRect, batch); drawPlayerLabels(players, playerIndex, userViewRect, batch); @@ -388,27 +388,21 @@ private void drawPlayers(Player[] players, Rectangle userViewRect, Batch batch) } } - private void drawColors(ShapeDrawer shapeDrawer, Rectangle userViewRect, float delta) { + private void drawColors(ShapeDrawer shapeDrawer, int playerIndex, Rectangle userViewRect, float delta) { for (int i = 0; i < this.rows; i++) { for (int j = 0; j < this.cols; j++) { float startX = j * Constants.CELL_SIZE; float startY = i * Constants.CELL_SIZE; if (mapGrid[i][j].cellColor != null) { - // TODO: Performance wise taxing part? + if (playerIndex == 0 && mapGrid[i][j].cellColor.a != 1f) { + mapGrid[i][j].cellColor.add(0, 0, 0, 2f * delta); + } if (userViewRect.contains(startX, startY)) { shapeDrawer.setColor(mapGrid[i][j].cellColor); shapeDrawer.filledRectangle(startX, startY, Constants.CELL_SIZE, Constants.CELL_SIZE); } - - // Use the constant color object to avoid too many redundant color objects - Color constColor = PlayerColorHelper.getConstantColor(mapGrid[i][j].cellColor); - if (constColor != null) { - mapGrid[i][j].cellColor = constColor; - } else { - mapGrid[i][j].cellColor.add(0, 0, 0, 2f * delta); - } } } } diff --git a/core/src/com/cg/zoned/PlayerColorHelper.java b/core/src/com/cg/zoned/PlayerColorHelper.java index b146ab4..5514cd8 100644 --- a/core/src/com/cg/zoned/PlayerColorHelper.java +++ b/core/src/com/cg/zoned/PlayerColorHelper.java @@ -1,11 +1,16 @@ package com.cg.zoned; import com.badlogic.gdx.graphics.Color; -import com.cg.zoned.Constants; import java.util.Map; public final class PlayerColorHelper { + public static void resetPlayerColorAlpha() { + for (Map.Entry entry : Constants.PLAYER_COLORS.entrySet()) { + entry.getValue().a = 1f; + } + } + public static Color getColorFromString(String color) { return Constants.PLAYER_COLORS.get(color.toUpperCase()); } diff --git a/core/src/com/cg/zoned/managers/ControlManager.java b/core/src/com/cg/zoned/managers/ControlManager.java index 7c4ff1d..2d3c3ed 100644 --- a/core/src/com/cg/zoned/managers/ControlManager.java +++ b/core/src/com/cg/zoned/managers/ControlManager.java @@ -90,7 +90,6 @@ public void setUpOverlay(boolean isSplitScreen, int controls, Skin skin, float s Input.Keys.toString(players[i].controls[3]); controlLabels[i] = new Label(controlString, skin); Color labelColor = new Color(players[i].color); - labelColor.mul(10); controlLabels[i].setColor(labelColor); controlLabels[i].setAlignment(Align.center); } diff --git a/core/src/com/cg/zoned/screens/LoadingScreen.java b/core/src/com/cg/zoned/screens/LoadingScreen.java index b281453..221f0f3 100644 --- a/core/src/com/cg/zoned/screens/LoadingScreen.java +++ b/core/src/com/cg/zoned/screens/LoadingScreen.java @@ -27,6 +27,7 @@ import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.cg.zoned.Constants; +import com.cg.zoned.PlayerColorHelper; import com.cg.zoned.Zoned; public class LoadingScreen extends ScreenAdapter { @@ -45,6 +46,7 @@ public class LoadingScreen extends ScreenAdapter { public LoadingScreen(final Zoned game) { this.game = game; game.discordRPCManager.updateRPC("Loading game"); + PlayerColorHelper.resetPlayerColorAlpha(); } @Override diff --git a/core/src/com/cg/zoned/screens/MapStartPosScreen.java b/core/src/com/cg/zoned/screens/MapStartPosScreen.java index cd0e9d9..721e949 100644 --- a/core/src/com/cg/zoned/screens/MapStartPosScreen.java +++ b/core/src/com/cg/zoned/screens/MapStartPosScreen.java @@ -144,9 +144,6 @@ private void updateDividerColors(int playerIndex) { } else { dividerRightColor[i] = Color.BLACK; } - - dividerLeftColor[i].mul(10); - dividerRightColor[i].mul(10); } } @@ -170,7 +167,6 @@ private void setUpStage() { if (i < players.length) { playerLabels[i] = new Label("Player " + (i + 1), game.skin); Color labelColor = new Color(players[i].color); - labelColor.mul(10); playerLabels[i].setColor(labelColor); if (alignLeft) { table.add(playerLabels[i]).padBottom(10f * game.getScaleFactor()).left().expandX(); @@ -349,7 +345,6 @@ public void clicked(InputEvent event, float x, float y) { playerLabels[i].setText("Player " + (i + playerIndex + 1)); Color labelColor = new Color(players[i + playerIndex].color); - labelColor.mul(10); playerLabels[i].setColor(labelColor); radioButtons[i][(i + playerIndex) % radioButtons[i].length].setChecked(true); diff --git a/core/src/com/cg/zoned/screens/TutorialScreen.java b/core/src/com/cg/zoned/screens/TutorialScreen.java index 1825624..6e72210 100644 --- a/core/src/com/cg/zoned/screens/TutorialScreen.java +++ b/core/src/com/cg/zoned/screens/TutorialScreen.java @@ -31,6 +31,7 @@ import com.cg.zoned.Constants; import com.cg.zoned.Map; import com.cg.zoned.Player; +import com.cg.zoned.PlayerColorHelper; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TutorialItem; import com.cg.zoned.UITextDisplayer; @@ -95,7 +96,7 @@ private void initMap() { this.mapNoOverlayColor = new Color(0, 0, 0, 0f); this.drawOverlay = true; this.players = new Player[1]; - this.players[0] = new Player(Constants.PLAYER_COLORS.get("GREEN"), "Player"); + this.players[0] = new Player(PlayerColorHelper.getColorFromString("GREEN"), "Player"); this.players[0].position = new Vector2(Math.round(this.mapGrid.length / 2f), Math.round(this.mapGrid[0].length / 2f)); this.players[0].setControlIndex(0); this.playerLabelFont = game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getName()); From f283e1d1f211042e8cd9516d7005643247fbf77a Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:58:49 +0530 Subject: [PATCH 22/35] Client option lock when ready, need polishing ClickListener works as expected already, not really worth it to migrate to ChangeListener, especially because I need some of ClickListener's features in some places and it'll be messy when it is a mix of both throughout the code. Hence, removed that TODO reminder --- android/assets/neon-skin/neon-ui.atlas | 9 +++++++++ android/assets/neon-skin/neon-ui.json | 7 ++++++- android/assets/neon-skin/neon-ui.png | Bin 189077 -> 133971 bytes .../cg/zoned/screens/ClientLobbyScreen.java | 10 +++++----- .../com/cg/zoned/screens/MainMenuScreen.java | 2 -- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/android/assets/neon-skin/neon-ui.atlas b/android/assets/neon-skin/neon-ui.atlas index ebcfe4b..1827be1 100644 --- a/android/assets/neon-skin/neon-ui.atlas +++ b/android/assets/neon-skin/neon-ui.atlas @@ -230,6 +230,15 @@ select-box-pressed orig: 52, 42 offset: 0, 0 index: -1 +select-box-disabled + rotate: false + xy: 263, 164 + size: 52, 42 + split: 18, 22, 14, 22 + pad: 15, 23, 14, 14 + orig: 52, 42 + offset: 0, 0 + index: -1 slider rotate: false xy: 228, 341 diff --git a/android/assets/neon-skin/neon-ui.json b/android/assets/neon-skin/neon-ui.json index 0999a5b..e493679 100644 --- a/android/assets/neon-skin/neon-ui.json +++ b/android/assets/neon-skin/neon-ui.json @@ -136,6 +136,10 @@ "name": "select-box-pressed", "color": "color" }, + "select-box-disabled-c": { + "name": "select-box-disabled", + "color": "color" + }, "slider-before-c": { "name": "slider-before", "color": "color" @@ -347,7 +351,8 @@ "scrollStyle": "default", "listStyle": "default", "backgroundOver": "select-box-over-c", - "backgroundOpen": "select-box-pressed-c" + "backgroundOpen": "select-box-pressed-c", + "backgroundDisabled": "select-box-disabled-c" } }, "com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle": { diff --git a/android/assets/neon-skin/neon-ui.png b/android/assets/neon-skin/neon-ui.png index b32f029991495948181f667193c6dce752b12a77..50e079ffcfd0921829430e7728a6321b7088cc99 100644 GIT binary patch literal 133971 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%0AZbHSjkcbu~H(JkXCs=Q+_ReA41s|a%a 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

5v$@X*%bmYR>i(F?xGsoF{hBKuQvy#M0j;_M8V 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 z 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 ChangeListener? Research. - UIButtonManager uiButtonManager = new UIButtonManager(mainStage, game.getScaleFactor(), usedTextures); HoverImageButton settingsButton = uiButtonManager.addSettingsButtonToStage(game.assets.getSettingsButtonTexture()); HoverImageButton creditsButton = uiButtonManager.addCreditsButtonToStage(game.assets.getCreditsButtonTexture()); From e0c56e95195e6ad495c802830193fe7c0072a3b4 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Tue, 1 Sep 2020 16:45:39 +0530 Subject: [PATCH 23/35] Updated libGDX logo and link in the credits, RPC code improvements Android builds should now be smaller as the Discord RPC code will no longer be bundled in it --- android/assets/icons/ic_libgdx.png | Bin 6985 -> 1876 bytes android/src/com/cg/zoned/AndroidLauncher.java | 2 +- build.gradle | 14 ++-- core/src/com/cg/zoned/Zoned.java | 12 ++-- .../cg/zoned/managers/DiscordRPCBridge.java | 11 ++++ .../cg/zoned/managers/DiscordRPCManager.java | 51 ++++----------- .../com/cg/zoned/screens/CreditsScreen.java | 2 +- .../com/cg/zoned/desktop/DesktopLauncher.java | 2 +- .../cg/zoned/desktop/DiscordRPCManager.java | 61 ++++++++++++++++++ 9 files changed, 96 insertions(+), 59 deletions(-) create mode 100644 core/src/com/cg/zoned/managers/DiscordRPCBridge.java create mode 100644 desktop/src/com/cg/zoned/desktop/DiscordRPCManager.java diff --git a/android/assets/icons/ic_libgdx.png b/android/assets/icons/ic_libgdx.png index b9ba1371d347ae605d67e6c81c6992462df846f6..eca80590002659553bd368f7508864e046fd8033 100644 GIT binary patch literal 1876 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ℑnXWsra>6+Ql&q?Emg|NpO*8Z2nH4prwFOc%u9p@?8-h9jAe0TkqWKmfUhX#uUH)M5<&1*f} zL@vpn(m^s~{%1Hu(a(Q=V`G+i;%$0EN<$P0-y}Byl&1*a<8{IT{EW}L$124vN&-QM zilppaJ!Biw Date: Tue, 1 Sep 2020 20:43:41 +0530 Subject: [PATCH 24/35] Cleanups on the Discord RPC code, setting for toggling it --- core/src/com/cg/zoned/Constants.java | 1 + core/src/com/cg/zoned/Zoned.java | 4 +-- .../cg/zoned/managers/DiscordRPCManager.java | 5 ++- .../com/cg/zoned/maps/ExternalMapReader.java | 4 +-- .../com/cg/zoned/screens/LoadingScreen.java | 10 ++++-- .../com/cg/zoned/screens/SettingsScreen.java | 31 +++++++++++++++++++ .../cg/zoned/desktop/DiscordRPCManager.java | 5 ++- 7 files changed, 52 insertions(+), 8 deletions(-) diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 784f5e2..3175337 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -103,6 +103,7 @@ public final class Constants { public static final String SPLITSCREEN_PLAYER_COUNT_PREFERENCE = "Splitscreen_Player_Count_Preference"; public static final String MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE = "Map_Start_Pos_Splitscreen_Count_Preference"; public static final String DEV_MODE_PREFERENCE = "Dev_Mode_Preference"; + public static final String DISCORD_RPC_PREFERENCE = "DISCORD_RPC_PREFERENCE"; public static final int PIE_MENU_CONTROL = 0; public static final int FLING_CONTROL = 1; diff --git a/core/src/com/cg/zoned/Zoned.java b/core/src/com/cg/zoned/Zoned.java index 5db04a9..06129a5 100644 --- a/core/src/com/cg/zoned/Zoned.java +++ b/core/src/com/cg/zoned/Zoned.java @@ -21,9 +21,9 @@ public class Zoned extends Game { private static float SCALE_FACTOR = 1.0f; - public Zoned(DiscordRPCBridge discordRPCManager) { + public Zoned(DiscordRPCBridge discordRPCBridge) { super(); - this.discordRPCManager = new DiscordRPCManager(discordRPCManager); + this.discordRPCManager = new DiscordRPCManager(discordRPCBridge); } @Override diff --git a/core/src/com/cg/zoned/managers/DiscordRPCManager.java b/core/src/com/cg/zoned/managers/DiscordRPCManager.java index 45eb066..c08bafc 100644 --- a/core/src/com/cg/zoned/managers/DiscordRPCManager.java +++ b/core/src/com/cg/zoned/managers/DiscordRPCManager.java @@ -1,11 +1,14 @@ package com.cg.zoned.managers; -public class DiscordRPCManager { +public class DiscordRPCManager implements DiscordRPCBridge { private DiscordRPCBridge discordRPCBridge; public DiscordRPCManager(DiscordRPCBridge discordRPCBridge) { this.discordRPCBridge = discordRPCBridge; + } + @Override + public void initRPC() { if (this.discordRPCBridge != null) { this.discordRPCBridge.initRPC(); } diff --git a/core/src/com/cg/zoned/maps/ExternalMapReader.java b/core/src/com/cg/zoned/maps/ExternalMapReader.java index 80efb90..6d70c8e 100644 --- a/core/src/com/cg/zoned/maps/ExternalMapReader.java +++ b/core/src/com/cg/zoned/maps/ExternalMapReader.java @@ -57,7 +57,7 @@ private void setExternalMapDir() { externalMapDir.mkdirs(); // Create them folders if they don't exist } catch (NullPointerException e) { e.printStackTrace(); - Gdx.app.log(Constants.LOG_TAG, "Failed to create external map directory"); + Gdx.app.error(Constants.LOG_TAG, "Failed to create external map directory"); } } @@ -94,7 +94,7 @@ private Array scanExternalMaps() { Gdx.app.log(Constants.LOG_TAG, "External map scan complete (" + mapFiles.size + " maps found)"); } catch (NullPointerException e) { e.printStackTrace(); - Gdx.app.log(Constants.LOG_TAG, "NPE during external map scan: " + e.getMessage()); + Gdx.app.error(Constants.LOG_TAG, "NPE during external map scan: " + e.getMessage()); } return mapFiles; diff --git a/core/src/com/cg/zoned/screens/LoadingScreen.java b/core/src/com/cg/zoned/screens/LoadingScreen.java index 221f0f3..0063bcf 100644 --- a/core/src/com/cg/zoned/screens/LoadingScreen.java +++ b/core/src/com/cg/zoned/screens/LoadingScreen.java @@ -46,6 +46,14 @@ public class LoadingScreen extends ScreenAdapter { public LoadingScreen(final Zoned game) { this.game = game; game.discordRPCManager.updateRPC("Loading game"); + initSetup(); + } + + private void initSetup() { + game.preferences = Gdx.app.getPreferences(Constants.ZONED_PREFERENCES); + if (game.preferences.getBoolean(Constants.DISCORD_RPC_PREFERENCE, true)) { + game.discordRPCManager.initRPC(); + } PlayerColorHelper.resetPlayerColorAlpha(); } @@ -68,8 +76,6 @@ public void show() { generateCustomFont("fonts/glametrix.otf", Constants.FONT_MANAGER.REGULAR); generateCustomFont("fonts/bebasneue.otf", Constants.FONT_MANAGER.SMALL); generateCustomFont("fonts/bebasneue.otf", Constants.FONT_MANAGER.PLAYER_LABEL); - - game.preferences = Gdx.app.getPreferences(Constants.ZONED_PREFERENCES); } private void setUpLoadingUI() { diff --git a/core/src/com/cg/zoned/screens/SettingsScreen.java b/core/src/com/cg/zoned/screens/SettingsScreen.java index 544f398..7a10e2a 100644 --- a/core/src/com/cg/zoned/screens/SettingsScreen.java +++ b/core/src/com/cg/zoned/screens/SettingsScreen.java @@ -1,5 +1,6 @@ package com.cg.zoned.screens; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; @@ -146,6 +147,32 @@ public void changed(ChangeEvent event, Actor actor) { }); table.add(showFPS).colspan(2).padTop(30f); + table.row(); + + HoverCheckBox discordRPCSwitch = null; + if (Gdx.app.getType() == Application.ApplicationType.Desktop) { + discordRPCSwitch = new HoverCheckBox("Enable Discord Rich Presence", game.skin); + discordRPCSwitch.getImageCell().width(discordRPCSwitch.getLabel().getPrefHeight()).height(discordRPCSwitch.getLabel().getPrefHeight()); + discordRPCSwitch.getImage().setScaling(Scaling.fill); + discordRPCSwitch.setChecked(game.preferences.getBoolean(Constants.DISCORD_RPC_PREFERENCE, true)); + discordRPCSwitch.addListener(new ChangeListener() { + @Override + public void changed(ChangeEvent event, Actor actor) { + HoverCheckBox discordRPCSwitch = (HoverCheckBox) actor; + if (discordRPCSwitch.isChecked()) { + game.discordRPCManager.initRPC(); + game.discordRPCManager.updateRPC("Configuring Settings"); + } else { + game.discordRPCManager.shutdownRPC(); + } + + game.preferences.putBoolean(Constants.DISCORD_RPC_PREFERENCE, discordRPCSwitch.isChecked()); + game.preferences.flush(); + } + }); + + table.add(discordRPCSwitch).colspan(2).padTop(30f); + } masterTable.add(screenScrollPane).grow(); stage.addActor(masterTable); @@ -153,6 +180,10 @@ public void changed(ChangeEvent event, Actor actor) { stage.addFocusableActor(flingControl); stage.row(); stage.addFocusableActor(showFPS, 2); + if (Gdx.app.getType() == Application.ApplicationType.Desktop) { + stage.row(); + stage.addFocusableActor(discordRPCSwitch, 2); + } stage.setScrollFocus(screenScrollPane); } diff --git a/desktop/src/com/cg/zoned/desktop/DiscordRPCManager.java b/desktop/src/com/cg/zoned/desktop/DiscordRPCManager.java index b23e959..659d705 100644 --- a/desktop/src/com/cg/zoned/desktop/DiscordRPCManager.java +++ b/desktop/src/com/cg/zoned/desktop/DiscordRPCManager.java @@ -13,7 +13,10 @@ public class DiscordRPCManager implements DiscordRPCBridge { private DiscordRichPresence richPresence = null; + private final long startTime; + public DiscordRPCManager() { + startTime = System.currentTimeMillis(); } public void initRPC() { @@ -22,7 +25,7 @@ public void initRPC() { DiscordRPC.discordInitialize(applicationID, null, false); richPresence = new DiscordRichPresence.Builder("") .setBigImage("zoned_logo", "v" + Constants.GAME_VERSION) - .setStartTimestamps(System.currentTimeMillis()) + .setStartTimestamps(startTime) .build(); } else { Gdx.app.error(Constants.LOG_TAG, "Ignoring RPC init request as the previous RPC hasn't been shutdown"); From 9b1707d06a89ba4523c0ca99196eedc02f65cd7c Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 2 Sep 2020 14:02:08 +0530 Subject: [PATCH 25/35] Cleanups, changed external map directory on Linux --- core/src/com/cg/zoned/Constants.java | 15 +++++-- .../src/com/cg/zoned/managers/MapManager.java | 6 ++- .../com/cg/zoned/maps/ExternalMapReader.java | 40 +++++++++++++------ .../cg/zoned/screens/PlayerSetUpScreen.java | 1 + 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 3175337..8c24a84 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -95,15 +95,24 @@ public final class Constants { public static final String LOG_TAG = "ZONED"; + // Preferences file name public static final String ZONED_PREFERENCES = "Zoned_Preferences"; + // Show FPS or not public static final String FPS_PREFERENCE = "FPS_Preference"; + // 0 = Piemenu control, 1 = Fling control public static final String CONTROL_PREFERENCE = "Control_Preference"; - public static final String NAME_PREFERENCE = "Name_Preference"; // The last used name - public static final String SHOW_TUTORIAL_PREFERENCE = "Show_Tutorial_Preference"; // Shows the tutorial dialog prompt the first time + // The last used name to be autofilled in the Player name field in the Host join screen + public static final String NAME_PREFERENCE = "Name_Preference"; + // Shows the tutorial prompt the first time the user visits the splitscreen multiplayer screen + public static final String SHOW_TUTORIAL_PREFERENCE = "Show_Tutorial_Preference"; + // Player count in splitscreen multiplayer mode (Developer options) public static final String SPLITSCREEN_PLAYER_COUNT_PREFERENCE = "Splitscreen_Player_Count_Preference"; + // Splitscreen count in the Map start pos screen (Developer option) public static final String MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE = "Map_Start_Pos_Splitscreen_Count_Preference"; + // Developer mode unlocked or not public static final String DEV_MODE_PREFERENCE = "Dev_Mode_Preference"; - public static final String DISCORD_RPC_PREFERENCE = "DISCORD_RPC_PREFERENCE"; + // Enable Discord RPC or not + public static final String DISCORD_RPC_PREFERENCE = "Discord_RPC_Preference"; public static final int PIE_MENU_CONTROL = 0; public static final int FLING_CONTROL = 1; diff --git a/core/src/com/cg/zoned/managers/MapManager.java b/core/src/com/cg/zoned/managers/MapManager.java index 69d6a2c..160f477 100644 --- a/core/src/com/cg/zoned/managers/MapManager.java +++ b/core/src/com/cg/zoned/managers/MapManager.java @@ -33,7 +33,7 @@ public class MapManager { private int internalMapCount = 0; private ExternalMapReader externalMapReader; - private FileHandle externalMapDir = null; + private FileHandle externalMapDir; public MapManager() { this.mapList = new Array<>(); @@ -199,6 +199,10 @@ private void parseMapData(String mapData) throws InvalidMapCharacter, NoStartPos this.wallCount = wallCount; } + public void enableExternalMapLogging(boolean enableExternalMapLogging) { + this.externalMapReader.enableExternalMapLogging(enableExternalMapLogging); + } + public MapEntity getPreparedMap() { return preparedMap; } diff --git a/core/src/com/cg/zoned/maps/ExternalMapReader.java b/core/src/com/cg/zoned/maps/ExternalMapReader.java index 6d70c8e..364cdac 100644 --- a/core/src/com/cg/zoned/maps/ExternalMapReader.java +++ b/core/src/com/cg/zoned/maps/ExternalMapReader.java @@ -18,7 +18,7 @@ *

* Directory to save the .map and the .png preview files * - On Android: /storage/emulated/0/Android/data/com.cg.zoned/files/ZonedExternalMaps/ - * - On Linux: /home/username/Zoned/ZonedExternalMaps/ + * - On Linux: /home/username/.zoned/ZonedExternalMaps/ * - On Windows: C:\\Users\\username\\Documents\\Zoned\\ZonedExternalMaps\\ */ public class ExternalMapReader { @@ -26,6 +26,7 @@ public class ExternalMapReader { private FileHandle externalMapDir; private Array loadedMaps; + private boolean enableExternalMapLogging = false; public ExternalMapReader() { this.loadedMaps = new Array<>(); @@ -46,7 +47,7 @@ private void setExternalMapDir() { } else if (Gdx.app.getType() == Application.ApplicationType.Desktop) { if (Gdx.files.getExternalStoragePath().startsWith("/home")) { // Linux - externalMapDir = Gdx.files.external("Zoned/" + mapDirName); + externalMapDir = Gdx.files.external(".zoned/" + mapDirName); } else { // Windows externalMapDir = Gdx.files.external("Documents/Zoned/" + mapDirName); @@ -81,17 +82,22 @@ private Array scanExternalMaps() { Array mapFiles = new Array<>(); try { - Gdx.app.log(Constants.LOG_TAG, "Scanning for external maps on " - + Gdx.files.getExternalStoragePath() + externalMapDir.path()); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "Scanning for external maps on " + + Gdx.files.getExternalStoragePath() + externalMapDir.path()); + } for (FileHandle mapFile : externalMapDir.list(".map")) { if (!mapFile.isDirectory()) { - Gdx.app.log(Constants.LOG_TAG, "Map found: " + mapFile.name()); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "Map found: " + mapFile.name()); + } mapFiles.add(mapFile); } } - - Gdx.app.log(Constants.LOG_TAG, "External map scan complete (" + mapFiles.size + " maps found)"); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "External map scan complete (" + mapFiles.size + " maps found)"); + } } catch (NullPointerException e) { e.printStackTrace(); Gdx.app.error(Constants.LOG_TAG, "NPE during external map scan: " + e.getMessage()); @@ -101,11 +107,15 @@ private Array scanExternalMaps() { } private void parseScannedMaps(Array mapFiles) { - Gdx.app.log(Constants.LOG_TAG, "Preparing to parse the scanned maps"); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "Preparing to parse the scanned maps"); + } for (FileHandle mapFile : mapFiles) { parseMap(mapFile); } - Gdx.app.log(Constants.LOG_TAG, "Map parsing completed"); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "Map parsing completed"); + } } private void parseMap(FileHandle mapFile) { @@ -153,12 +163,18 @@ private void parseMap(FileHandle mapFile) { if (!mapGrid.isEmpty() && mapName != null && rowCount > 0 && colCount > 0) { loadedMaps.add(new ExternalMapTemplate(mapName, mapGrid, startPosNames, rowCount, colCount)); - Gdx.app.log(Constants.LOG_TAG, "Successfully parsed " + mapFile.name()); - } else { - Gdx.app.log(Constants.LOG_TAG, "Failed to parse " + mapFile.name()); + if (enableExternalMapLogging) { + Gdx.app.log(Constants.LOG_TAG, "Successfully parsed " + mapFile.name()); + } + } else if (enableExternalMapLogging) { + Gdx.app.error(Constants.LOG_TAG, "Failed to parse " + mapFile.name()); } } + public void enableExternalMapLogging(boolean enableExternalMapLogging) { + this.enableExternalMapLogging = enableExternalMapLogging; + } + public Array getLoadedMaps() { return loadedMaps; } diff --git a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java index a329b0f..5441789 100644 --- a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java +++ b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java @@ -181,6 +181,7 @@ public void buttonPressed(Button button) { final MapSelector mapSelector = new MapSelector(stage, game.getScaleFactor(), game.assets, game.skin); mapSelector.setUsedTextureArray(usedTextures); + mapSelector.getMapManager().enableExternalMapLogging(true); Spinner mapSpinner = mapSelector.loadMapSelectorSpinner(150 * game.getScaleFactor(), game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getName()).getLineHeight() * 3); mapSelector.loadExternalMaps(); From 4db9bd35b7bee9a06c60d8ea7ee29d56ebcc0a81 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 2 Sep 2020 14:05:41 +0530 Subject: [PATCH 26/35] Revert auto code formatter stuff --- core/src/com/cg/zoned/Constants.java | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 8c24a84..09d4a9a 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -57,11 +57,11 @@ public final class Constants { */ public static final Map PLAYER_COLORS = new LinkedHashMap() { { - put("GREEN", new Color(0, 0.8f, 0, 1.0f)); // Alpha won't matter - put("RED", new Color(0.8f, 0, 0, 1.0f)); - put("BLUE", new Color(0, 0, 0.8f, 1.0f)); - put("YELLOW", new Color(0.8f, 0.8f, 0, 1.0f)); - put("PINK", new Color(0.8f, 0, 0.8f, 1.0f)); + put("GREEN", new Color(0, 0.8f, 0, 1.0f)); // Alpha won't matter + put("RED", new Color(0.8f, 0, 0, 1.0f)); + put("BLUE", new Color(0, 0, 0.8f, 1.0f)); + put("YELLOW", new Color(0.8f, 0.8f, 0, 1.0f)); + put("PINK", new Color(0.8f, 0, 0.8f, 1.0f)); } }; @@ -86,11 +86,11 @@ public final class Constants { public static final float DESKTOP_FONT_SCALE_FACTOR = 1.0f; // Values from https://developer.android.com/training/multiscreen/screendensities - public static final float ANDROID_LDPI_FONT_SCALE_FACTOR = 0.75f; - public static final float ANDROID_MDPI_FONT_SCALE_FACTOR = 1.0f; - public static final float ANDROID_HDPI_FONT_SCALE_FACTOR = 1.5f; - public static final float ANDROID_XHDPI_FONT_SCALE_FACTOR = 2.0f; - public static final float ANDROID_XXHDPI_FONT_SCALE_FACTOR = 3.0f; + public static final float ANDROID_LDPI_FONT_SCALE_FACTOR = 0.75f; + public static final float ANDROID_MDPI_FONT_SCALE_FACTOR = 1.0f; + public static final float ANDROID_HDPI_FONT_SCALE_FACTOR = 1.5f; + public static final float ANDROID_XHDPI_FONT_SCALE_FACTOR = 2.0f; + public static final float ANDROID_XXHDPI_FONT_SCALE_FACTOR = 3.0f; public static final float ANDROID_XXXHDPI_FONT_SCALE_FACTOR = 4.0f; public static final String LOG_TAG = "ZONED"; @@ -120,9 +120,9 @@ public final class Constants { public enum Direction {UP, LEFT, DOWN, RIGHT} public enum FONT_MANAGER { - LARGE("large-font", 80), + LARGE("large-font", 80), REGULAR("regular-font", 32), - SMALL("small-font", 18), + SMALL("small-font", 18), PLAYER_LABEL("player-label-font-noscale", // Height based on cell size minus a bit of line width as calculated below (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (2 * Constants.MAP_GRID_LINE_WIDTH)))); From c9f78d71080ef45f1bd18b584156b53b463400b5 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 2 Sep 2020 20:18:09 +0530 Subject: [PATCH 27/35] Removed player score param, TeamData cleanups --- core/src/com/cg/zoned/Map.java | 2 +- core/src/com/cg/zoned/Player.java | 2 -- core/src/com/cg/zoned/ScoreBar.java | 14 +++++------ core/src/com/cg/zoned/TeamData.java | 25 +++++++++++++------ .../com/cg/zoned/managers/PlayerManager.java | 17 ++++++------- .../cg/zoned/screens/ClientLobbyScreen.java | 4 +-- core/src/com/cg/zoned/screens/GameScreen.java | 8 +++--- .../cg/zoned/screens/ServerLobbyScreen.java | 4 +-- .../com/cg/zoned/screens/VictoryScreen.java | 21 ++++++++-------- 9 files changed, 53 insertions(+), 44 deletions(-) diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index f3f2f73..841dd2c 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -517,7 +517,7 @@ public boolean gameComplete(Array teamData) { if (teamData.size == 2) { for (TeamData td : teamData) { // For two team games, end the game when a team has captured more than 50% of the cells - if (100 * (td.score / (((double) this.rows * this.cols) - this.wallCount)) > 50.0) { + if (100 * (td.getScore() / (((double) this.rows * this.cols) - this.wallCount)) > 50.0) { return true; } } diff --git a/core/src/com/cg/zoned/Player.java b/core/src/com/cg/zoned/Player.java index 5f01034..2d30f60 100644 --- a/core/src/com/cg/zoned/Player.java +++ b/core/src/com/cg/zoned/Player.java @@ -12,7 +12,6 @@ public class Player extends InputAdapter { public Color color; public String name; - public int score; public int[] controls; public Direction direction; @@ -30,7 +29,6 @@ public class Player extends InputAdapter { public Player(Color color, String name) { this.color = color; this.name = name; - this.score = 0; this.position = new Vector2(); this.prevPosition = null; diff --git a/core/src/com/cg/zoned/ScoreBar.java b/core/src/com/cg/zoned/ScoreBar.java index a375cf4..abf0f9e 100644 --- a/core/src/com/cg/zoned/ScoreBar.java +++ b/core/src/com/cg/zoned/ScoreBar.java @@ -57,7 +57,7 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea float totalScore = 0; for (TeamData td : teamData) { - totalScore += td.score; + totalScore += td.getScore(); } if (totalScore == 0) { @@ -69,14 +69,14 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, Color.BLACK, Color.BLACK); for (int i = 0; i < teamData.size; i++) { - float barWidth = ((teamData.get(i).score / totalScore) * totalWidth); + float barWidth = ((teamData.get(i).getScore() / totalScore) * totalWidth); scoreBarTargetWidth[i] = barWidth; float drawWidth = scoreBarCurrentWidth[i] + ((scoreBarTargetWidth[i] - scoreBarCurrentWidth[i]) * SCOREBAR_LERP_VALUE * delta); scoreBarCurrentWidth[i] = drawWidth; - shapeDrawer.setColor(teamData.get(i).color); - font.setColor(getGoodTextColor(teamData.get(i).color)); + shapeDrawer.setColor(teamData.get(i).getColor()); + font.setColor(getGoodTextColor(teamData.get(i).getColor())); float barStartX = 0; for (int j = 0; j < i; j++) { @@ -88,7 +88,7 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea scoreBarDrawStartPos[i] = scoreBarDrawStartPos[i] + ((barStartX - scoreBarDrawStartPos[i]) * SCOREBAR_LERP_VALUE * delta); shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, drawWidth, scoreBarHeight); - font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).getScore()), scoreBarDrawStartPos[i], totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), drawWidth, Align.center, false); } else if (i == teamData.size - 1) { @@ -96,7 +96,7 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea scoreBarDrawStartPos[i] = scoreBarDrawStartPos[i] + ((barStartX + scoreBarTargetWidth[i] - scoreBarDrawStartPos[i]) * SCOREBAR_LERP_VALUE * delta); shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, -drawWidth, scoreBarHeight); - font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).getScore()), scoreBarDrawStartPos[i] - drawWidth, totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), drawWidth, Align.center, false); } else { @@ -105,7 +105,7 @@ public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array tea shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, drawWidth / 2, scoreBarHeight); shapeDrawer.filledRectangle(scoreBarDrawStartPos[i], offsetY, -drawWidth / 2, scoreBarHeight); - font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).score), + font.draw(shapeDrawer.getBatch(), String.valueOf(teamData.get(i).getScore()), scoreBarDrawStartPos[i] - (drawWidth / 2), totalHeight - (scoreBarHeight / 2) + (font.getLineHeight() / 4), drawWidth, Align.center, false); } diff --git a/core/src/com/cg/zoned/TeamData.java b/core/src/com/cg/zoned/TeamData.java index 85b00fd..92e3640 100644 --- a/core/src/com/cg/zoned/TeamData.java +++ b/core/src/com/cg/zoned/TeamData.java @@ -3,16 +3,27 @@ import com.badlogic.gdx.graphics.Color; public class TeamData { - public Color color; - public int score; - - public TeamData(Color color, int score) { - this.color = color; - this.score = score; - } + private Color color; + private int score; public TeamData(Color color) { this.color = color; this.score = 0; } + + public void incrementScore() { + score++; + } + + public void resetScore() { + score = 0; + } + + public Color getColor() { + return color; + } + + public int getScore() { + return score; + } } diff --git a/core/src/com/cg/zoned/managers/PlayerManager.java b/core/src/com/cg/zoned/managers/PlayerManager.java index 0f638e0..e211c9b 100644 --- a/core/src/com/cg/zoned/managers/PlayerManager.java +++ b/core/src/com/cg/zoned/managers/PlayerManager.java @@ -44,14 +44,14 @@ private void initTeamData() { for (Player player : players) { boolean alreadyExists = false; for (TeamData teamData : this.teamData) { - if (player.color.equals(teamData.color)) { + if (player.color.equals(teamData.getColor())) { alreadyExists = true; break; } } if (!alreadyExists) { - teamData.add(new TeamData(player.color, player.score)); + teamData.add(new TeamData(player.color)); } } } @@ -86,15 +86,18 @@ public void updatePlayerDirections() { } public void incrementScore(Player player) { - player.score++; for (TeamData teamData : this.teamData) { - if (player.color.equals(teamData.color)) { - teamData.score++; + if (player.color.equals(teamData.getColor())) { + teamData.incrementScore(); return; } } } + public void renderPlayerControlPrompt(ShapeDrawer shapeDrawer, float delta) { + controlManager.renderPlayerControlPrompt(shapeDrawer, delta); + } + public Player getPlayer(int index) { return players[index]; } @@ -106,8 +109,4 @@ public Player[] getPlayers() { public Array getTeamData() { return teamData; } - - public void renderPlayerControlPrompt(ShapeDrawer shapeDrawer, float delta) { - controlManager.renderPlayerControlPrompt(shapeDrawer, delta); - } } diff --git a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java index 5bf4076..397315d 100644 --- a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java @@ -125,8 +125,8 @@ private void setUpClientLobbyStage() { //clientLobbyTable.setDebug(true); clientLobbyTable.center(); - Label onlinePlayersTitle = new Label("Connected Players", game.skin, "themed"); - clientLobbyTable.add(onlinePlayersTitle).pad(20); + Label lobbyTitle = new Label("Lobby", game.skin, "themed"); + clientLobbyTable.add(lobbyTitle).pad(20); clientLobbyTable.row(); diff --git a/core/src/com/cg/zoned/screens/GameScreen.java b/core/src/com/cg/zoned/screens/GameScreen.java index 5ea40c5..013c6f8 100644 --- a/core/src/com/cg/zoned/screens/GameScreen.java +++ b/core/src/com/cg/zoned/screens/GameScreen.java @@ -196,11 +196,11 @@ public void render(float delta) { int highscore = 0; for (TeamData teamData : gameManager.playerManager.getTeamData()) { - if (teamData.score > highscore) { - highscore = teamData.score; - targetBgColor.set(teamData.color); + if (teamData.getScore() > highscore) { + highscore = teamData.getScore(); + targetBgColor.set(teamData.getColor()); targetBgColor.a = bgAlpha; - } else if (teamData.score == highscore) { + } else if (teamData.getScore() == highscore) { targetBgColor.set(0, 0, 0, bgAlpha); } } diff --git a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java index 605f660..20b0e3d 100644 --- a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java @@ -112,8 +112,8 @@ private void setUpServerLobbyStage() { serverLobbyTable.center(); //serverLobbyTable.setDebug(true); - Label onlinePlayersTitle = new Label("Connected Players", game.skin, "themed"); - serverLobbyTable.add(onlinePlayersTitle).pad(20f); + Label lobbyTitle = new Label("Lobby", game.skin, "themed"); + serverLobbyTable.add(lobbyTitle).pad(20f); serverLobbyTable.row(); Table scrollTable = new Table(); diff --git a/core/src/com/cg/zoned/screens/VictoryScreen.java b/core/src/com/cg/zoned/screens/VictoryScreen.java index 5b5ad79..7e90aad 100644 --- a/core/src/com/cg/zoned/screens/VictoryScreen.java +++ b/core/src/com/cg/zoned/screens/VictoryScreen.java @@ -117,11 +117,12 @@ private void setUpVictoryUI() { victoryString.append(victoryStr).append("\n"); } - Color[] rankColors = new Color[4]; - rankColors[0] = Color.GOLD; - rankColors[1] = Color.LIGHT_GRAY; - rankColors[2] = Color.BROWN; - rankColors[3] = Color.GRAY; + Color[] rankColors = new Color[]{ + Color.GOLD, + Color.LIGHT_GRAY, + Color.BROWN, + Color.GRAY + }; String[] rankImageLocations = new String[]{ "icons/rank_icons/ic_no1.png", @@ -139,7 +140,7 @@ private void setUpVictoryUI() { float rankLabelMaxWidth = 0; int rankIndex = 0; for (int i = 0; i < victoryStrings.length; i++, rankIndex++) { - if (i > 0 && teamData.get(i - 1).score == teamData.get(i).score) { + if (i > 0 && teamData.get(i - 1).getScore() == teamData.get(i).getScore()) { rankIndex--; } rankLabels[i] = new Label("#" + (rankIndex + 1), game.skin, Constants.FONT_MANAGER.REGULAR.getName(), rankColors[Math.min(rankIndex, 3)]); @@ -195,11 +196,11 @@ private void getVictoryStrings(PlayerManager playerManager, int rows, int cols, DecimalFormat df = new DecimalFormat("#.##"); for (int i = 0; i < teamData.size; i++) { - double capturePercentage = 100 * (teamData.get(i).score / (((double) rows * cols) - wallCount)); + double capturePercentage = 100 * (teamData.get(i).getScore() / (((double) rows * cols) - wallCount)); capturePercentage = Double.parseDouble(df.format(capturePercentage)); - this.victoryStrings[i] = PlayerColorHelper.getStringFromColor(teamData.get(i).color) - + " got a score of " + teamData.get(i).score + " (" + capturePercentage + "%)"; + this.victoryStrings[i] = PlayerColorHelper.getStringFromColor(teamData.get(i).getColor()) + + " got a score of " + teamData.get(i).getScore() + " (" + capturePercentage + "%)"; } } @@ -244,7 +245,7 @@ public void onBackPressed() { private static class TeamDataComparator implements Comparator { @Override public int compare(TeamData t1, TeamData t2) { - return t2.score - t1.score; + return t2.getScore() - t1.getScore(); } } From 36107dd1e888920385e0850e129679581bd6ebb9 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Thu, 3 Sep 2020 21:06:23 +0530 Subject: [PATCH 28/35] CI: Testing fix for release_name Victory Screen UI improvements ongoing --- .github/workflows/release-snapshot.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index 8bb507f..3626132 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -42,7 +42,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload jar release - uses: svenstaro/upload-release-action@v2 + uses: kittaakos/upload-release-action@GH-26 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: desktop/build/libs/*.jar @@ -54,7 +54,7 @@ jobs: body: "Latest bleeding edge version of Zoned. Might be buggy" - name: Upload apk release - uses: svenstaro/upload-release-action@v2 + uses: kittaakos/upload-release-action@GH-26 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: android/build/outputs/apk/debug/*.apk @@ -62,5 +62,4 @@ jobs: tag: v-dev overwrite: true prerelease: true - release_name: "Zoned Developer Build" From e89117ce0541c8240ac94bfdee29a810874e72d3 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Fri, 4 Sep 2020 19:34:59 +0530 Subject: [PATCH 29/35] Improved VictoryScreen, Font code improvements, Removed blending on FPS VictoryScreen is prolly going to get more improvements --- android/assets/icons/ic_libgdx.png | Bin 1876 -> 2347 bytes core/src/com/cg/zoned/Constants.java | 33 +++++--- core/src/com/cg/zoned/MapSelector.java | 2 +- core/src/com/cg/zoned/UITextDisplayer.java | 5 -- .../cg/zoned/managers/AnimationManager.java | 64 ++++++++------ .../cg/zoned/managers/UIButtonManager.java | 17 +++- .../cg/zoned/screens/ClientLobbyScreen.java | 2 +- .../com/cg/zoned/screens/CreditsScreen.java | 4 +- core/src/com/cg/zoned/screens/DevScreen.java | 6 +- core/src/com/cg/zoned/screens/GameScreen.java | 4 +- .../com/cg/zoned/screens/HostJoinScreen.java | 6 +- .../com/cg/zoned/screens/LoadingScreen.java | 21 +++-- .../com/cg/zoned/screens/MainMenuScreen.java | 13 +-- .../cg/zoned/screens/MapStartPosScreen.java | 4 +- .../cg/zoned/screens/PlayerSetUpScreen.java | 4 +- .../cg/zoned/screens/ServerLobbyScreen.java | 4 +- .../com/cg/zoned/screens/SettingsScreen.java | 2 +- .../com/cg/zoned/screens/TutorialScreen.java | 4 +- .../com/cg/zoned/screens/VictoryScreen.java | 80 ++++++++++++------ core/src/com/cg/zoned/ui/FocusableStage.java | 1 + 20 files changed, 169 insertions(+), 107 deletions(-) diff --git a/android/assets/icons/ic_libgdx.png b/android/assets/icons/ic_libgdx.png index eca80590002659553bd368f7508864e046fd8033..bc456e49e183dbbb57178a7d57962ea7e2ca7eaf 100644 GIT binary patch delta 2252 zcmV;-2s8K84yzK7J%0-m000XU0RWnu7ytkO2XskIMF->w1P3+-rb8sx000QMNkl0t%BG)3BV%djPY6?*|3`_hA*G#_7?9Vee|#7S}&V_dB5Ks@7K2i&nM3-%bq(g+3uWNuV0dD z_IV?Ja(p_e_ygtKDp)c z|A$!bXgBg3|jl4^3;m;vG$;P%$S&-j$;rA z!B-?sj<6o3kwNAD{?SvF9ob1ct&c}01hM~aK$PsXK3>_Dy>@^9=x<6RgUZuhy5;iZ ziDaRCvK4>U)zoKeTa8bPf4QN4LO=`hs>dbA{#(srB z2tmLDIX)(Mk|#^sf-I*Osy` z*|N?V`I-5q-rtYM%!ZG)JoomF3;+H$pRlik(8`~kR(5WgXw`d*a|nn*4B{5o>nD6w z+U%;*bFQvFXQ%aX!S{cECzHOgp2s^r{nH|94KHJNf9%?cSOkF(v<_br#UKjJT;~uO zqA1#FeY~0A~tBK~&A&^zpSG?}&H=fe;V_f)H~{ z9`DH4I57}Jkug3 zAs`6E0C?Kj!GN#Gdl-rMgn%F{$Avdt?whV4j_OhUuD|{>@R4~jH?-YT)gPI?J@0x6 zWk-;8JbJuio>>>45IhkCA;kVf#5Nnf6E#9nJ=?fuK#7z-Nl?_JGX<71dpDFY~*Kd69i&_jo|xUpv4raFU*_mDN;7d|JKsT;3i)Y ze^c$65A6uSk~2brKn&3OBWv$ou$`&;LU-)c)dK;yyAb97tEZ_41W{DlH6Pj)0)jvc zIDp@vUlmENcPGelW;XTPVs5CTX9vaHP@kDiooeTHhe0tn)MNIh&$e@1+8F|Z&^&%x z8q*#AYDC+;CFtr%!$+Q~(*JNW->>ziPrI7(-FA&jCql3^2*upc!B#yEGcG?nB?eeIDa`ukc3K|~ z^i_na^gry&{4uQC-RgCEs=TfIOkXYR^C2uDAP7x-Bfzc?D?WgA`)_PFf{aTye}rIZ z5ctZ77@!HF<6e{M&Rm?fS*km8qT^oUzaM;Dx+w$%ff!)DJN#8HSj$Y!`dYDiI!@!E z6|1K+Q?uN>Z{@hWyPk3B#t;w$Vt^J zy(o`|R;<34y?XsTGvkSIDLwpC_R4?%9F-6d1Y&?DB}&z!YR$SF#cfk-*5yR0dX)e2 za!R#+B~h&WG-@Fr2*dyZ&I%sOOwF45-O`~%x%OeCB3G_`sNXFe%1q6gf6R;}fvlJx z>x-oqGE=kFD29L_5CcNc#O!hmHJ9CCVWn2v6BZgloPAyEVglc7)xy?oLPGn-upB4_lj4XY3yBB_T}D zQ}BIXtymYd2i0T7#PoEKe^t!Cyg!mZJyk2#XIiOp)R>r_Tzt9FnQvyDQHX(PdlkuZ=Ox>nQ)=}~a=m`en7Hx9TFXT>0|W#CkP!j% delta 1777 zcmVv9}fi_8zB%2000KzNklfh79Kdlqb?PQ*V~a_YPSC+r9EG)k1X}IJVTZi~n08>AcGzK0l{lcigdLce z#E#QW)3nnr(~gt2-FT>($0#<{U=#sE8cO=)I&qU7#-Qm_5)tRg58sc(iO5a1K zElj`s?n}xK8{=c|tNQJSjc&V=PF)*VT0PmRpY7x`W2$aG_R;=)K-SGio!Z_;I(2<` zY4sE_AO@k0L9vj{%5(F#!uF~tiZQ4=I2W?V)VcY8`6vc~5D)`m(1KDQyqaFi65QJ(%zUv-+MNlXjp4uJ`fUv7s@#;sTh_W_8<^~ zdNBdmI|M^v4*}{88rE7VrzLj#|KX+8Qyb~j^-ldfSvMaQ^O*yLfXRT#z{iupT3jlL z6*nD!_5&c3LA`2RT23{1-h(B+bDx=j!#1VX@M zz+}*(QcjZx4Qo9r2R|l*ot1OikYZR)7$yWlz+?a~JGv-*!YW`x6h3Zrn;=XGgn-F_ z$-vuGAPyQG{4JH(!udMD;qei7YjYa@P49O~Co zq}(t|jc!yrkx>IT<;BE(RY`h1apmSW?QAE};<2LNZy6B+Vn7V~90Mnx8C7-j2`{IA z{iT@C49mK?+^ZP$GYEvh8{Q^D=OQvQb&e4Dld795>(j5j*~_2VkGG5n0Wp9dcBV@C zCsx77&yQ32wbwthmq8!|!~i}aZq)u^75ro0tri9?rvgpuS$RW~2> zfCdq1=akkkkrx(cW!+q~1))|fWV5VDxF!TbKny?>yu6aUwVIIcmU0?XF+m^%#2}hc zU=^P2^tN+&(6B0dUCj&82m&D>1_S~BU*2(um562#2mvtwo{P`_`8TT&y&w>O0%E{) zz;sYYthni?)01ad2@nGigosOAz4=`!r^&2De{}i_?V2&Lw0d$Sow~;A69b_BZ38az z8JQ3e1Y!WDgWact->lC{IgLLKi%19v0xXbWD5j= z7!U=5uu~MC*fUe_vJw#pK|V94&duviJ~KuThyk#Dr*5sCdR*17w&)9=@^84 zUHldTg5V9G8DP6~>MI^MysV2~LLdlyhCmF^{>0#J+~9Ge)phYx2nYf(K(oK#d%V4+ z7*@?bu3d=Idf3Oc3yNX!<$c@N<lNvyc( zupaPgacL=8ah0YHjuAVXsL|=9K?=cUoMpsh01qnJS4Vk#(NoT8!(j{o69O@S;O$#Z z6~kID_vt%rdT_vhODcx7&YrRDz&xTD)@m3-KoE!lA!y_4t`)Xi#0AopYvXhtzLpE)Qjubr0{7H55bpqn^! zNf=39RCV(~JKG7{2guIE_+=rT{9K*8eYeqV!x(}s`!gRZ1C#LxA{qby0I=1+6zmY0 T6&pDB00000NkvXXu0mjf=8-8$ diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 09d4a9a..b0845c5 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -120,26 +120,33 @@ public final class Constants { public enum Direction {UP, LEFT, DOWN, RIGHT} public enum FONT_MANAGER { - LARGE("large-font", 80), - REGULAR("regular-font", 32), - SMALL("small-font", 18), - PLAYER_LABEL("player-label-font-noscale", // Height based on cell size minus a bit of line width as calculated below + LARGE ("large-font", "austere.otf", 80), + REGULAR ("regular-font", "glametrix.otf", 32), + SMALL ("small-font", "bebasneue.otf", 18), + PLAYER_LABEL("player-label-font-noscale", "bebasneue.otf", (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (2 * Constants.MAP_GRID_LINE_WIDTH)))); + // Player label font height is based on cell size minus a bit of line width as calculated above - private String name; - private int size; + private String fontName; + private String fontFileName; + private int fontSize; - FONT_MANAGER(String name, int size) { - this.name = name; - this.size = size; + FONT_MANAGER(String fontName, String fontFileName, int fontSize) { + this.fontName = fontName; + this.fontFileName = fontFileName; + this.fontSize = fontSize; } - public int getSize() { - return size; + public int getFontSize() { + return fontSize; } - public String getName() { - return name; + public String getFontName() { + return fontName; + } + + public String getFontFileName() { + return fontFileName; } } } \ No newline at end of file diff --git a/core/src/com/cg/zoned/MapSelector.java b/core/src/com/cg/zoned/MapSelector.java index 9133c94..c79bcb4 100644 --- a/core/src/com/cg/zoned/MapSelector.java +++ b/core/src/com/cg/zoned/MapSelector.java @@ -142,7 +142,7 @@ private void showExtraParamDialog(final MapExtraParams prompts, final MapEntity int snapValue = prompts.spinnerVars.get(i - 1).snapValue; label = new Label(prompts.spinnerVars.get(i - 1).prompt, skin); - spinners[i - 1] = new Spinner(skin, skin.getFont(Constants.FONT_MANAGER.REGULAR.getName()).getLineHeight(), + spinners[i - 1] = new Spinner(skin, skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight(), 64f * scaleFactor, true); spinners[i - 1].generateValueRange(lowValue, highValue, skin); spinners[i - 1].snapToStep(snapValue - lowValue); diff --git a/core/src/com/cg/zoned/UITextDisplayer.java b/core/src/com/cg/zoned/UITextDisplayer.java index 9645591..318700b 100644 --- a/core/src/com/cg/zoned/UITextDisplayer.java +++ b/core/src/com/cg/zoned/UITextDisplayer.java @@ -2,7 +2,6 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.utils.viewport.Viewport; @@ -21,12 +20,10 @@ public static void displayFPS(Viewport viewport, Batch batch, BitmapFont font, f font.setColor(Color.RED); } - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); batch.begin(); font.draw(batch, "FPS: " + fps, xOffset, viewport.getWorldHeight() - yOffset); batch.end(); - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } public static void displayFPS(Viewport viewport, Batch batch, BitmapFont font) { @@ -42,12 +39,10 @@ public static void displayPing(Viewport viewport, Batch batch, BitmapFont font, font.setColor(Color.RED); } - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); batch.begin(); font.draw(batch, "Ping: " + ping + " ms", xOffset, viewport.getWorldHeight() - font.getLineHeight() - yOffset); batch.end(); - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } public static void displayPing(Viewport viewport, Batch batch, BitmapFont font, int ping) { diff --git a/core/src/com/cg/zoned/managers/AnimationManager.java b/core/src/com/cg/zoned/managers/AnimationManager.java index b9f1a48..d43c7c4 100644 --- a/core/src/com/cg/zoned/managers/AnimationManager.java +++ b/core/src/com/cg/zoned/managers/AnimationManager.java @@ -11,6 +11,8 @@ import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.ParallelAction; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; +import com.badlogic.gdx.scenes.scene2d.ui.Container; +import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.utils.Array; import com.cg.zoned.Zoned; @@ -171,34 +173,48 @@ public void run() { stage.addAction(fadeOutAnimation); } - public void startVictoryAnimation(final Stage stage, Table[] tableRows) { - for (int i = 0; i < tableRows.length; i++) { - tableRows[i].setTransform(true); - tableRows[i].setOrigin(tableRows[i].getPrefWidth() / 2, tableRows[i].getPrefHeight() / 2); - tableRows[i].setScale(0f); - tableRows[i].getColor().a = 0f; - - ParallelAction fadeZoomOutAnimation = new ParallelAction(); - fadeZoomOutAnimation.addAction(Actions.fadeIn((i + 1) * .2f, Interpolation.smooth)); - fadeZoomOutAnimation.addAction(Actions.scaleTo(1f, 1f, (i + 1) * .2f, Interpolation.smooth)); - - if (i == tableRows.length - 1) { - SequenceAction finalFadeZoomOutAnimation = new SequenceAction(); - finalFadeZoomOutAnimation.addAction(fadeZoomOutAnimation); - finalFadeZoomOutAnimation.addAction(Actions.run(new Runnable() { + public void startScoreBoardAnimation(final Stage stage, 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 delta 4014 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 diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index e55b878..a1b07ee 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -120,7 +120,7 @@ public final class Constants { public enum Direction {UP, LEFT, DOWN, RIGHT} public enum FONT_MANAGER { - LARGE ("large-font", "recharge.otf", 70), + LARGE ("large-font", "recharge.otf", 65), REGULAR ("regular-font", "glametrix.otf", 32), SMALL ("small-font", "bebasneue.otf", 18), PLAYER_LABEL("player-label-font-noscale", "bebasneue.otf", diff --git a/core/src/com/cg/zoned/screens/LoadingScreen.java b/core/src/com/cg/zoned/screens/LoadingScreen.java index 40cb9de..a43d467 100644 --- a/core/src/com/cg/zoned/screens/LoadingScreen.java +++ b/core/src/com/cg/zoned/screens/LoadingScreen.java @@ -95,7 +95,7 @@ private void setUpLoadingUI() { table.add(progressBar).growX() .padLeft(100f * game.getScaleFactor()).padRight(100f * game.getScaleFactor()) - .padTop(32f * game.getScaleFactor()); + .padTop(16f * game.getScaleFactor()); stage.addActor(table); } From d801dda4f22f2ea7283b4646e83366fa27b697db Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Sun, 6 Sep 2020 21:48:18 +0530 Subject: [PATCH 32/35] Major code cleanup on controls, preferences, fonts, directions and more --- android/assets/neon-skin/neon-ui.json | 28 ++-- core/src/com/cg/zoned/Assets.java | 30 ++++ core/src/com/cg/zoned/Constants.java | 58 +------- core/src/com/cg/zoned/KryoHelper.java | 3 +- core/src/com/cg/zoned/Map.java | 11 +- core/src/com/cg/zoned/MapSelector.java | 2 +- core/src/com/cg/zoned/Player.java | 3 +- core/src/com/cg/zoned/Preferences.java | 23 +++ .../cg/zoned/buffers/BufferDirections.java | 2 +- .../com/cg/zoned/controls/ControlType.java | 15 ++ .../cg/zoned/controls/ControlTypeEntity.java | 25 ++++ .../zoned/controls/FlingControlManager.java | 30 ++-- .../zoned/controls/PieMenuControlManager.java | 30 ++-- .../com/cg/zoned/managers/ControlManager.java | 46 +++--- .../managers/DirectionBufferManager.java | 2 +- .../zoned/managers/GameConnectionManager.java | 2 +- .../com/cg/zoned/managers/GameManager.java | 4 +- .../com/cg/zoned/managers/PlayerManager.java | 7 +- .../cg/zoned/screens/ClientLobbyScreen.java | 6 +- .../com/cg/zoned/screens/CreditsScreen.java | 12 +- core/src/com/cg/zoned/screens/DevScreen.java | 19 +-- core/src/com/cg/zoned/screens/GameScreen.java | 10 +- .../com/cg/zoned/screens/HostJoinScreen.java | 16 ++- .../com/cg/zoned/screens/LoadingScreen.java | 23 ++- .../com/cg/zoned/screens/MainMenuScreen.java | 11 +- .../cg/zoned/screens/MapStartPosScreen.java | 8 +- .../cg/zoned/screens/PlayerSetUpScreen.java | 16 ++- .../cg/zoned/screens/ServerLobbyScreen.java | 8 +- .../com/cg/zoned/screens/SettingsScreen.java | 133 +++++++++--------- .../com/cg/zoned/screens/TutorialScreen.java | 10 +- .../com/cg/zoned/screens/VictoryScreen.java | 17 ++- 31 files changed, 332 insertions(+), 278 deletions(-) create mode 100644 core/src/com/cg/zoned/Preferences.java create mode 100644 core/src/com/cg/zoned/controls/ControlType.java create mode 100644 core/src/com/cg/zoned/controls/ControlTypeEntity.java diff --git a/android/assets/neon-skin/neon-ui.json b/android/assets/neon-skin/neon-ui.json index e493679..64d10cf 100644 --- a/android/assets/neon-skin/neon-ui.json +++ b/android/assets/neon-skin/neon-ui.json @@ -251,7 +251,7 @@ "checkboxOn": "checkbox-pressed-c", "checkboxOff": "checkbox-c", "checkboxOver": "checkbox-over-c", - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "downFontColor": "text-selected", "checkedFontColor": "text-selected" @@ -260,7 +260,7 @@ "checkboxOn": "radio-pressed-c", "checkboxOff": "radio-c", "checkboxOver": "radio-over-c", - "font": "regular-font", + "font": "regular", "fontColor": "custom-color", "downFontColor": "selected", "checkedFontColor": "text-themed" @@ -275,7 +275,7 @@ }, "com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle": { "default": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "downFontColor": "text-selected", "up": "button-c", @@ -288,7 +288,7 @@ "imageOver": "checkbox-over-c", "imageChecked": "checkbox-pressed-c", "imageCheckedOver": "checkbox-pressed-over-c", - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "downFontColor": "text-selected", "checkedFontColor": "text-selected" @@ -299,7 +299,7 @@ "imageOver": "radio-over-c", "imageChecked": "radio-pressed-c", "imageCheckedOver": "radio-over-c", - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "downFontColor": "text-selected", "checkedFontColor": "text-selected" @@ -307,17 +307,17 @@ }, "com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle": { "default": { - "font": "regular-font", + "font": "regular", "fontColor": "text" }, "themed": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed" } }, "com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle": { "default": { - "font": "regular-font", + "font": "regular", "fontColorSelected": "selected", "fontColorUnselected": "text-themed", "selection": "color", @@ -346,7 +346,7 @@ }, "com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle": { "default": { - "font": "regular-font", + "font": "regular", "background": "select-box-c", "scrollStyle": "default", "listStyle": "default", @@ -381,7 +381,7 @@ }, "com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle": { "default": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "downFontColor": "text-selected", "up": "button-c", @@ -391,7 +391,7 @@ }, "com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle": { "default": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "background": "textfield-c", "focusedBackground": "textfield-selected-c", @@ -399,7 +399,7 @@ "selection": "selected" }, "login": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "background": "textfield-login-c", "focusedBackground": "textfield-login-selected-c", @@ -407,7 +407,7 @@ "selection": "selected" }, "password": { - "font": "regular-font", + "font": "regular", "fontColor": "text-themed", "background": "textfield-password-c", "focusedBackground": "textfield-password-selected-c", @@ -437,7 +437,7 @@ "com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle": { "default": { "background": "window-c", - "titleFont": "regular-font", + "titleFont": "regular", "titleFontColor": "text-themed" } } diff --git a/core/src/com/cg/zoned/Assets.java b/core/src/com/cg/zoned/Assets.java index 9df302b..ee95b9c 100644 --- a/core/src/com/cg/zoned/Assets.java +++ b/core/src/com/cg/zoned/Assets.java @@ -41,4 +41,34 @@ public void setAssetManager(AssetManager assetManager) { public void dispose() { assetManager.dispose(); } + + public enum FontManager { + STYLED_LARGE ("recharge.otf", 65), + STYLED_SMALL ("recharge.otf", 24), + REGULAR ("glametrix.otf", 32), // Default font, required to be named as 'REGULAR' + SMALL ("bebasneue.otf", 18), + PLAYER_LABEL_NOSCALE("bebasneue.otf", + (int) (Map.playerLabelRegionScale * (Constants.CELL_SIZE - (2 * Constants.MAP_GRID_LINE_WIDTH)))); + // Player label font height is based on cell size minus a bit of line width as calculated above + + private String fontFileName; + private int fontSize; + + FontManager(String fontFileName, int fontSize) { + this.fontFileName = fontFileName; + this.fontSize = fontSize; + } + + public int getFontSize() { + return fontSize; + } + + public String getFontName() { + return this.toString().toLowerCase(); + } + + public String getFontFileName() { + return fontFileName; + } + } } diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index a1b07ee..1c31a30 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -95,58 +95,8 @@ public final class Constants { public static final String LOG_TAG = "ZONED"; - // Preferences file name - public static final String ZONED_PREFERENCES = "Zoned_Preferences"; - // Show FPS or not - public static final String FPS_PREFERENCE = "FPS_Preference"; - // 0 = Piemenu control, 1 = Fling control - public static final String CONTROL_PREFERENCE = "Control_Preference"; - // The last used name to be autofilled in the Player name field in the Host join screen - public static final String NAME_PREFERENCE = "Name_Preference"; - // Shows the tutorial prompt the first time the user visits the splitscreen multiplayer screen - public static final String SHOW_TUTORIAL_PREFERENCE = "Show_Tutorial_Preference"; - // Player count in splitscreen multiplayer mode (Developer options) - public static final String SPLITSCREEN_PLAYER_COUNT_PREFERENCE = "Splitscreen_Player_Count_Preference"; - // Splitscreen count in the Map start pos screen (Developer option) - public static final String MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE = "Map_Start_Pos_Splitscreen_Count_Preference"; - // Developer mode unlocked or not - public static final String DEV_MODE_PREFERENCE = "Dev_Mode_Preference"; - // Enable Discord RPC or not - public static final String DISCORD_RPC_PREFERENCE = "Discord_RPC_Preference"; - - public static final int PIE_MENU_CONTROL = 0; - public static final int FLING_CONTROL = 1; - - public enum Direction {UP, LEFT, DOWN, RIGHT} - - public enum FONT_MANAGER { - LARGE ("large-font", "recharge.otf", 65), - REGULAR ("regular-font", "glametrix.otf", 32), - SMALL ("small-font", "bebasneue.otf", 18), - PLAYER_LABEL("player-label-font-noscale", "bebasneue.otf", - (int) (com.cg.zoned.Map.playerLabelRegionScale * (Constants.CELL_SIZE - (2 * Constants.MAP_GRID_LINE_WIDTH)))); - // Player label font height is based on cell size minus a bit of line width as calculated above - - private String fontName; - private String fontFileName; - private int fontSize; - - FONT_MANAGER(String fontName, String fontFileName, int fontSize) { - this.fontName = fontName; - this.fontFileName = fontFileName; - this.fontSize = fontSize; - } - - public int getFontSize() { - return fontSize; - } - - public String getFontName() { - return fontName; - } - - public String getFontFileName() { - return fontFileName; - } - } + // Preferences moved to Preferences.java + // Directions moved to Player.java + // Controls moved to managers/ControlManager.java + // Fonts moved to Assets.java } \ No newline at end of file diff --git a/core/src/com/cg/zoned/KryoHelper.java b/core/src/com/cg/zoned/KryoHelper.java index 409913f..a3ff16e 100644 --- a/core/src/com/cg/zoned/KryoHelper.java +++ b/core/src/com/cg/zoned/KryoHelper.java @@ -1,6 +1,6 @@ package com.cg.zoned; -import com.cg.zoned.Constants.Direction; +import com.cg.zoned.Player.Direction; import com.cg.zoned.buffers.BufferClientConnect; import com.cg.zoned.buffers.BufferDirections; import com.cg.zoned.buffers.BufferGameStart; @@ -12,7 +12,6 @@ import com.esotericsoftware.kryo.Kryo; public class KryoHelper { - public static void registerClasses(Kryo kryo) { kryo.register(BufferServerRejectedConnection.class); kryo.register(BufferPlayerDisconnected.class); diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index 841dd2c..2c8fbbf 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -15,7 +15,6 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; -import com.cg.zoned.Constants.Direction; import com.cg.zoned.managers.PlayerManager; import space.earlygrey.shapedrawer.JoinType; @@ -222,23 +221,23 @@ public void update(PlayerManager playerManager, Player[] players, float delta) { mapColorUpdated = false; - Direction direction = player.direction; - if (direction == Direction.UP && player.position.y < rows - 1 && + Player.Direction direction = player.direction; + if (direction == Player.Direction.UP && player.position.y < rows - 1 && mapGrid[Math.round(player.position.y) + 1][Math.round(player.position.x)].isMovable) { player.moveTo(new Vector2(player.position.x, player.position.y + 1), delta); - } else if (direction == Direction.RIGHT && player.position.x < cols - 1 && + } else if (direction == Player.Direction.RIGHT && player.position.x < cols - 1 && mapGrid[Math.round(player.position.y)][Math.round(player.position.x) + 1].isMovable) { player.moveTo(new Vector2(player.position.x + 1, player.position.y), delta); - } else if (direction == Direction.DOWN && player.position.y > 0 && + } else if (direction == Player.Direction.DOWN && player.position.y > 0 && mapGrid[Math.round(player.position.y) - 1][Math.round(player.position.x)].isMovable) { player.moveTo(new Vector2(player.position.x, player.position.y - 1), delta); - } else if (direction == Direction.LEFT && player.position.x > 0 && + } else if (direction == Player.Direction.LEFT && player.position.x > 0 && mapGrid[Math.round(player.position.y)][Math.round(player.position.x) - 1].isMovable) { player.moveTo(new Vector2(player.position.x - 1, player.position.y), delta); diff --git a/core/src/com/cg/zoned/MapSelector.java b/core/src/com/cg/zoned/MapSelector.java index c79bcb4..d885375 100644 --- a/core/src/com/cg/zoned/MapSelector.java +++ b/core/src/com/cg/zoned/MapSelector.java @@ -142,7 +142,7 @@ private void showExtraParamDialog(final MapExtraParams prompts, final MapEntity int snapValue = prompts.spinnerVars.get(i - 1).snapValue; label = new Label(prompts.spinnerVars.get(i - 1).prompt, skin); - spinners[i - 1] = new Spinner(skin, skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight(), + spinners[i - 1] = new Spinner(skin, skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight(), 64f * scaleFactor, true); spinners[i - 1].generateValueRange(lowValue, highValue, skin); spinners[i - 1].snapToStep(snapValue - lowValue); diff --git a/core/src/com/cg/zoned/Player.java b/core/src/com/cg/zoned/Player.java index 2d30f60..c258eff 100644 --- a/core/src/com/cg/zoned/Player.java +++ b/core/src/com/cg/zoned/Player.java @@ -7,7 +7,6 @@ import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import com.cg.zoned.Constants.Direction; public class Player extends InputAdapter { public Color color; @@ -110,4 +109,6 @@ public boolean keyDown(int keycode) { return false; } + + public enum Direction {UP, LEFT, DOWN, RIGHT} } diff --git a/core/src/com/cg/zoned/Preferences.java b/core/src/com/cg/zoned/Preferences.java new file mode 100644 index 0000000..701035e --- /dev/null +++ b/core/src/com/cg/zoned/Preferences.java @@ -0,0 +1,23 @@ +package com.cg.zoned; + +public class Preferences { + // Preferences file name + public static final String ZONED_PREFERENCES = "Zoned_Preferences"; + + // Show FPS or not + public static final String FPS_PREFERENCE = "FPS_Preference"; + // 0 = Piemenu control, 1 = Fling control + public static final String CONTROL_PREFERENCE = "Control_Preference"; + // The last used name to be autofilled in the Player name field in the Host join screen + public static final String NAME_PREFERENCE = "Name_Preference"; + // Shows the tutorial prompt the first time the user visits the splitscreen multiplayer screen + public static final String SHOW_TUTORIAL_PREFERENCE = "Show_Tutorial_Preference"; + // Player count in splitscreen multiplayer mode (Developer options) + public static final String SPLITSCREEN_PLAYER_COUNT_PREFERENCE = "Splitscreen_Player_Count_Preference"; + // Splitscreen count in the Map start pos screen (Developer option) + public static final String MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE = "Map_Start_Pos_Splitscreen_Count_Preference"; + // Developer mode unlocked or not + public static final String DEV_MODE_PREFERENCE = "Dev_Mode_Preference"; + // Enable Discord RPC or not + public static final String DISCORD_RPC_PREFERENCE = "Discord_RPC_Preference"; +} diff --git a/core/src/com/cg/zoned/buffers/BufferDirections.java b/core/src/com/cg/zoned/buffers/BufferDirections.java index 6421f0f..cef9a11 100644 --- a/core/src/com/cg/zoned/buffers/BufferDirections.java +++ b/core/src/com/cg/zoned/buffers/BufferDirections.java @@ -1,6 +1,6 @@ package com.cg.zoned.buffers; -import com.cg.zoned.Constants.Direction; +import com.cg.zoned.Player.Direction; public class BufferDirections { public String[] playerNames; diff --git a/core/src/com/cg/zoned/controls/ControlType.java b/core/src/com/cg/zoned/controls/ControlType.java new file mode 100644 index 0000000..04c9f53 --- /dev/null +++ b/core/src/com/cg/zoned/controls/ControlType.java @@ -0,0 +1,15 @@ +package com.cg.zoned.controls; + +public class ControlType { + public String controlName; + public String controlOffTexturePath; + public String controlOnTexturePath; + public ControlTypeEntity controlTypeEntity; + + public ControlType(String controlName, String controlOffTexturePath, String controlOnTexturePath, ControlTypeEntity controlTypeEntity) { + this.controlName = controlName; + this.controlOffTexturePath = controlOffTexturePath; + this.controlOnTexturePath = controlOnTexturePath; + this.controlTypeEntity = controlTypeEntity; + } +} diff --git a/core/src/com/cg/zoned/controls/ControlTypeEntity.java b/core/src/com/cg/zoned/controls/ControlTypeEntity.java new file mode 100644 index 0000000..8ff57ca --- /dev/null +++ b/core/src/com/cg/zoned/controls/ControlTypeEntity.java @@ -0,0 +1,25 @@ +package com.cg.zoned.controls; + +import com.badlogic.gdx.InputAdapter; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.utils.Array; +import com.cg.zoned.Player; + +public class ControlTypeEntity extends InputAdapter { + protected Player[] players; + protected boolean isSplitScreen; + protected Stage stage; + protected float scaleFactor; + protected Array usedTextures; + + public ControlTypeEntity() {} + + public void init(Player[] players, boolean isSplitScreen, Stage stage, float scaleFactor, Array usedTextures) { + this.players = players; + this.isSplitScreen = isSplitScreen; + this.stage = stage; + this.scaleFactor = scaleFactor; + this.usedTextures = usedTextures; + } +} diff --git a/core/src/com/cg/zoned/controls/FlingControlManager.java b/core/src/com/cg/zoned/controls/FlingControlManager.java index 0b59696..5b31baa 100644 --- a/core/src/com/cg/zoned/controls/FlingControlManager.java +++ b/core/src/com/cg/zoned/controls/FlingControlManager.java @@ -3,7 +3,6 @@ import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; -import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.scenes.scene2d.Stage; @@ -11,26 +10,21 @@ import com.badlogic.gdx.scenes.scene2d.actions.MoveByAction; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.utils.Array; -import com.cg.zoned.Constants; import com.cg.zoned.GameTouchPoint; import com.cg.zoned.Player; -public class FlingControlManager extends InputAdapter { - private Stage stage; - private Player[] players; - private boolean isSplitScreenMultiplayer; - - private float scaleFactor; +public class FlingControlManager extends ControlTypeEntity { private Texture arrowTexture; private Array clickPoints; - public FlingControlManager(Player[] players, boolean isSplitScreen, Stage stage, float scaleFactor, Array usedTextures) { + public FlingControlManager() { + } + + public void init(Player[] players, boolean isSplitScreen, Stage stage, float scaleFactor, Array usedTextures) { + super.init(players, isSplitScreen, stage, scaleFactor, usedTextures); + this.clickPoints = new Array<>(); - this.players = players; - this.isSplitScreenMultiplayer = isSplitScreen; - this.stage = stage; - this.scaleFactor = scaleFactor; arrowTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_arrow.png")); usedTextures.add(arrowTexture); @@ -40,7 +34,7 @@ public FlingControlManager(Player[] players, boolean isSplitScreen, Stage stage, public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (button == Input.Buttons.LEFT) { int playerIndex = 0; - if (isSplitScreenMultiplayer) { + if (isSplitScreen) { for (int i = 1; i < this.players.length; i++) { if (screenX > ((stage.getWidth() / this.players.length) * i)) { playerIndex++; @@ -117,18 +111,18 @@ public boolean touchUp(int screenX, int screenY, int pointer, int button) { MoveByAction moveAction; if (Math.abs(subPoint.x) > Math.abs(subPoint.y)) { if (subPoint.x > 0) { - player.updatedDirection = Constants.Direction.RIGHT; + player.updatedDirection = Player.Direction.RIGHT; moveAction = Actions.moveBy(moveAnimationDistance, 0f, .2f); } else { - player.updatedDirection = Constants.Direction.LEFT; + player.updatedDirection = Player.Direction.LEFT; moveAction = Actions.moveBy(-moveAnimationDistance, 0f, .2f); } } else { if (subPoint.y > 0) { - player.updatedDirection = Constants.Direction.DOWN; + player.updatedDirection = Player.Direction.DOWN; moveAction = Actions.moveBy(0f, -moveAnimationDistance, .2f); } else { - player.updatedDirection = Constants.Direction.UP; + player.updatedDirection = Player.Direction.UP; moveAction = Actions.moveBy(0f, moveAnimationDistance, .2f); } } diff --git a/core/src/com/cg/zoned/controls/PieMenuControlManager.java b/core/src/com/cg/zoned/controls/PieMenuControlManager.java index 440863e..04cc305 100644 --- a/core/src/com/cg/zoned/controls/PieMenuControlManager.java +++ b/core/src/com/cg/zoned/controls/PieMenuControlManager.java @@ -2,7 +2,6 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; -import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Vector2; @@ -15,33 +14,28 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Scaling; -import com.cg.zoned.Constants; import com.cg.zoned.Player; import com.cg.zoned.ShapeDrawer; import com.payne.games.piemenu.PieMenu; import java.util.Arrays; -public class PieMenuControlManager extends InputAdapter { - private Stage stage; - private Player[] players; - private boolean isSplitScreenMultiplayer; - +public class PieMenuControlManager extends ControlTypeEntity { private int piemenuRadius = 80; - private float scaleFactor; private PieMenu[] menus; private int[] pointers; private Vector2[] coords; private Image[][] arrowImages; - public PieMenuControlManager(Player[] players, boolean isSplitScreen, Stage stage, float scaleFactor, Array usedTextures) { - this.players = players; - this.isSplitScreenMultiplayer = isSplitScreen; - this.stage = stage; + public PieMenuControlManager() { + } + + public void init(Player[] players, boolean isSplitScreen, Stage stage, float scaleFactor, Array usedTextures) { + super.init(players, isSplitScreen, stage, scaleFactor, usedTextures); + this.menus = new PieMenu[players.length]; this.pointers = new int[players.length]; this.coords = new Vector2[players.length]; - this.scaleFactor = scaleFactor; Arrays.fill(pointers, -1); Arrays.fill(coords, new Vector2()); @@ -96,13 +90,13 @@ public void onHighlightChange(int highlightedIndex) { resetArrowColors(arrowImages[finalI]); arrowImages[finalI][highlightedIndex].setColor(Color.BLACK); if (highlightedIndex == 0) { - players[finalI].updatedDirection = Constants.Direction.UP; + players[finalI].updatedDirection = Player.Direction.UP; } else if (highlightedIndex == 1) { - players[finalI].updatedDirection = Constants.Direction.LEFT; + players[finalI].updatedDirection = Player.Direction.LEFT; } else if (highlightedIndex == 2) { - players[finalI].updatedDirection = Constants.Direction.DOWN; + players[finalI].updatedDirection = Player.Direction.DOWN; } else if (highlightedIndex == 3) { - players[finalI].updatedDirection = Constants.Direction.RIGHT; + players[finalI].updatedDirection = Player.Direction.RIGHT; } } }); @@ -128,7 +122,7 @@ private void resetArrowColors(Image[] arrowImages) { public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (button == Input.Buttons.LEFT) { int playerIndex = 0; - if (isSplitScreenMultiplayer) { + if (isSplitScreen) { for (int i = 1; i < this.players.length; i++) { if (screenX > ((stage.getWidth() / this.players.length) * i)) { playerIndex++; diff --git a/core/src/com/cg/zoned/managers/ControlManager.java b/core/src/com/cg/zoned/managers/ControlManager.java index 2d3c3ed..7609210 100644 --- a/core/src/com/cg/zoned/managers/ControlManager.java +++ b/core/src/com/cg/zoned/managers/ControlManager.java @@ -15,15 +15,27 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Scaling; -import com.cg.zoned.Constants; import com.cg.zoned.Player; import com.cg.zoned.ShapeDrawer; +import com.cg.zoned.controls.ControlType; +import com.cg.zoned.controls.ControlTypeEntity; import com.cg.zoned.controls.FlingControlManager; import com.cg.zoned.controls.PieMenuControlManager; public class ControlManager { - private FlingControlManager flingControlManager = null; - private PieMenuControlManager pieMenuControlManager = null; + // Specify at least one control mechanism. Otherwise, it will crash and burn. + public static final ControlType[] CONTROL_TYPES = { + new ControlType("Piemenu", + "icons/control_icons/ic_control_piemenu_off.png", + "icons/control_icons/ic_control_piemenu_on.png", + new PieMenuControlManager()), + new ControlType("Fling", + "icons/control_icons/ic_control_fling_off.png", + "icons/control_icons/ic_control_fling_on.png", + new FlingControlManager()), + }; + + private ControlTypeEntity currentControls = null; private Player[] players; private Stage stage; @@ -35,23 +47,15 @@ public ControlManager(Player[] players, Stage stage) { this.players = players; } - public void setUpControls(int controls, boolean isSplitScreen, float scaleFactor, Array usedTextures) { - if (controls == Constants.PIE_MENU_CONTROL) { - pieMenuControlManager = new PieMenuControlManager(players, isSplitScreen, stage, scaleFactor, usedTextures); - } else if (controls == Constants.FLING_CONTROL) { - flingControlManager = new FlingControlManager(players, isSplitScreen, stage, scaleFactor, usedTextures); - } + public void setUpControls(int controlIndex, boolean isSplitScreen, float scaleFactor, Array usedTextures) { + currentControls = CONTROL_TYPES[controlIndex].controlTypeEntity; + currentControls.init(players, isSplitScreen, stage, scaleFactor, usedTextures); } - public void setUpOverlay(boolean isSplitScreen, int controls, Skin skin, float scaleFactor, Array usedTextures) { - setUpControls(controls, isSplitScreen, scaleFactor, usedTextures); + public void setUpOverlay(boolean isSplitScreen, int controlIndex, Skin skin, float scaleFactor, Array usedTextures) { + setUpControls(controlIndex, isSplitScreen, scaleFactor, usedTextures); - FileHandle controlImagePath = null; - if (controls == Constants.PIE_MENU_CONTROL) { - controlImagePath = Gdx.files.internal("icons/control_icons/ic_control_piemenu_off.png"); - } else if (controls == Constants.FLING_CONTROL) { - controlImagePath = Gdx.files.internal("icons/control_icons/ic_control_fling_off.png"); - } + FileHandle controlImagePath = Gdx.files.internal(CONTROL_TYPES[controlIndex].controlOffTexturePath); Table masterTable = new Table(); masterTable.setFillParent(true); @@ -131,12 +135,6 @@ public void renderPlayerControlPrompt(ShapeDrawer shapeDrawer, float delta) { } public InputAdapter getControls() { - if (pieMenuControlManager != null) { - return pieMenuControlManager; - } else if (flingControlManager != null) { - return flingControlManager; - } else { - return null; - } + return currentControls; } } diff --git a/core/src/com/cg/zoned/managers/DirectionBufferManager.java b/core/src/com/cg/zoned/managers/DirectionBufferManager.java index 1d6643d..05e29e4 100644 --- a/core/src/com/cg/zoned/managers/DirectionBufferManager.java +++ b/core/src/com/cg/zoned/managers/DirectionBufferManager.java @@ -1,6 +1,6 @@ package com.cg.zoned.managers; -import com.cg.zoned.Constants.Direction; +import com.cg.zoned.Player.Direction; import java.util.Arrays; diff --git a/core/src/com/cg/zoned/managers/GameConnectionManager.java b/core/src/com/cg/zoned/managers/GameConnectionManager.java index fc05b51..a872131 100644 --- a/core/src/com/cg/zoned/managers/GameConnectionManager.java +++ b/core/src/com/cg/zoned/managers/GameConnectionManager.java @@ -2,8 +2,8 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; -import com.cg.zoned.Constants.Direction; import com.cg.zoned.Player; +import com.cg.zoned.Player.Direction; import com.cg.zoned.buffers.BufferDirections; import com.cg.zoned.buffers.BufferPlayerDisconnected; import com.cg.zoned.buffers.BufferServerRejectedConnection; diff --git a/core/src/com/cg/zoned/managers/GameManager.java b/core/src/com/cg/zoned/managers/GameManager.java index ccbfc4e..ad201c2 100644 --- a/core/src/com/cg/zoned/managers/GameManager.java +++ b/core/src/com/cg/zoned/managers/GameManager.java @@ -29,9 +29,9 @@ public void setUpConnectionManager(Server server, Client client) { this.gameConnectionManager = new GameConnectionManager(this, server, client); } - public void setUpDirectionAndPlayerBuffer(Player[] players, Stage stage, int controls, Skin skin, float scaleFactor, Array usedTextures) { + public void setUpDirectionAndPlayerBuffer(Player[] players, Stage stage, int controlIndex, Skin skin, float scaleFactor, Array usedTextures) { this.directionBufferManager = new DirectionBufferManager(players.length); - this.playerManager = new PlayerManager(this, players, stage, controls, skin, scaleFactor, usedTextures); + this.playerManager = new PlayerManager(this, players, stage, controlIndex, skin, scaleFactor, usedTextures); } diff --git a/core/src/com/cg/zoned/managers/PlayerManager.java b/core/src/com/cg/zoned/managers/PlayerManager.java index e211c9b..625d910 100644 --- a/core/src/com/cg/zoned/managers/PlayerManager.java +++ b/core/src/com/cg/zoned/managers/PlayerManager.java @@ -5,7 +5,6 @@ import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.utils.Array; -import com.cg.zoned.Constants.Direction; import com.cg.zoned.Player; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TeamData; @@ -19,7 +18,7 @@ public class PlayerManager extends InputMultiplexer { private Array teamData; - public PlayerManager(GameManager gameManager, Player[] players, Stage stage, int controls, Skin skin, float scaleFactor, Array usedTextures) { + public PlayerManager(GameManager gameManager, Player[] players, Stage stage, int controlIndex, Skin skin, float scaleFactor, Array usedTextures) { this.gameManager = gameManager; this.players = players; @@ -34,7 +33,7 @@ public PlayerManager(GameManager gameManager, Player[] players, Stage stage, int } controlManager = new ControlManager(players, stage); - controlManager.setUpOverlay(!gameManager.gameConnectionManager.isActive, controls, skin, scaleFactor, usedTextures); + controlManager.setUpOverlay(!gameManager.gameConnectionManager.isActive, controlIndex, skin, scaleFactor, usedTextures); this.addProcessor(controlManager.getControls()); } @@ -56,7 +55,7 @@ private void initTeamData() { } } - public void setPlayerDirections(Direction[] directions) { + public void setPlayerDirections(Player.Direction[] directions) { for (int i = 0; i < players.length; i++) { players[i].direction = directions[i]; } diff --git a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java index dec7b6e..e25f05e 100644 --- a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java @@ -28,10 +28,12 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Cell; import com.cg.zoned.Constants; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -88,7 +90,7 @@ public ClientLobbyScreen(final Zoned game, Client client, String name) { viewport = new ScreenViewport(); stage = new FocusableStage(viewport); animationManager = new AnimationManager(this.game, this); - font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); startLocations = new Array<>(); this.clientName = name; @@ -100,7 +102,7 @@ public void show() { setUpClientLobbyStage(); setUpMap(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); addPlayer(null, null, null, null, null); connectionManager.start(clientName); diff --git a/core/src/com/cg/zoned/screens/CreditsScreen.java b/core/src/com/cg/zoned/screens/CreditsScreen.java index b512543..8d7fbcb 100644 --- a/core/src/com/cg/zoned/screens/CreditsScreen.java +++ b/core/src/com/cg/zoned/screens/CreditsScreen.java @@ -24,7 +24,9 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Scaling; import com.badlogic.gdx.utils.viewport.ScreenViewport; +import com.cg.zoned.Assets; import com.cg.zoned.Constants; +import com.cg.zoned.Preferences; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -54,7 +56,7 @@ public CreditsScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override @@ -62,7 +64,7 @@ public void show() { setUpStage(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.fadeInStage(stage); } @@ -131,7 +133,7 @@ private void addCreditItem(Table table, FileHandle imageLocation, String title, gameLogoImage.setScaling(Scaling.fit); gameLogoImage.getColor().a = .3f; - final Label titleLabel = new Label(title, game.skin, Constants.FONT_MANAGER.LARGE.getFontName(), Color.GREEN); + final Label titleLabel = new Label(title, game.skin, Assets.FontManager.STYLED_LARGE.getFontName(), Color.GREEN); titleLabel.setAlignment(Align.center); Stack stack = new Stack(); @@ -265,9 +267,9 @@ private void addCreditItem(Table table, String title, final String content) { private void toggleDevMode() { // owo what's this - boolean devModeUnlocked = game.preferences.getBoolean(Constants.DEV_MODE_PREFERENCE, false); + boolean devModeUnlocked = game.preferences.getBoolean(Preferences.DEV_MODE_PREFERENCE, false); devModeUnlocked = !devModeUnlocked; - game.preferences.putBoolean(Constants.DEV_MODE_PREFERENCE, devModeUnlocked); + game.preferences.putBoolean(Preferences.DEV_MODE_PREFERENCE, devModeUnlocked); game.preferences.flush(); Array buttonTexts = new Array<>(); diff --git a/core/src/com/cg/zoned/screens/DevScreen.java b/core/src/com/cg/zoned/screens/DevScreen.java index 77ba8e6..c4ea970 100644 --- a/core/src/com/cg/zoned/screens/DevScreen.java +++ b/core/src/com/cg/zoned/screens/DevScreen.java @@ -14,7 +14,8 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.ScreenViewport; -import com.cg.zoned.Constants; +import com.cg.zoned.Assets; +import com.cg.zoned.Preferences; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -46,7 +47,7 @@ public DevScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override @@ -54,7 +55,7 @@ public void show() { setUpStage(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.fadeInStage(stage); } @@ -74,20 +75,20 @@ private void setUpStage() { screenScrollPane.setOverscroll(false, true); int maxPlayerCount = 100; - int currentPlayerCount = game.preferences.getInteger(Constants.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, 2); + int currentPlayerCount = game.preferences.getInteger(Preferences.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, 2); Label splitscreenPlayerCountLabel = new Label("Splitscreen player count", game.skin); splitscreenPlayerCountSpinner = new Spinner(game.skin, - game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight(), + game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight(), 64f * game.getScaleFactor(), true); splitscreenPlayerCountSpinner.generateValueRange(minPlayerCount, maxPlayerCount, game.skin); splitscreenPlayerCountSpinner.snapToStep(currentPlayerCount - minPlayerCount); int maxSplitScreenCount = 100; - int currentSplitScreenCount = game.preferences.getInteger(Constants.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, 2); + int currentSplitScreenCount = game.preferences.getInteger(Preferences.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, 2); Label mapStartPosSplitscreenCountLabel = new Label("Map start position splitscreen count", game.skin); mapStartPosSplitscreenCountSpinner = new Spinner(game.skin, - game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight(), + game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight(), 64f * game.getScaleFactor(), true); mapStartPosSplitscreenCountSpinner.generateValueRange(minSplitScreenCount, maxSplitScreenCount, game.skin); @@ -148,8 +149,8 @@ public void render(float delta) { } private void saveData() { - game.preferences.putInteger(Constants.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, splitscreenPlayerCountSpinner.getPositionIndex() + minPlayerCount); - game.preferences.putInteger(Constants.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, mapStartPosSplitscreenCountSpinner.getPositionIndex() + minSplitScreenCount); + game.preferences.putInteger(Preferences.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, splitscreenPlayerCountSpinner.getPositionIndex() + minPlayerCount); + game.preferences.putInteger(Preferences.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, mapStartPosSplitscreenCountSpinner.getPositionIndex() + minSplitScreenCount); game.preferences.flush(); } diff --git a/core/src/com/cg/zoned/screens/GameScreen.java b/core/src/com/cg/zoned/screens/GameScreen.java index 7f78550..fbcbc87 100644 --- a/core/src/com/cg/zoned/screens/GameScreen.java +++ b/core/src/com/cg/zoned/screens/GameScreen.java @@ -19,9 +19,11 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Constants; import com.cg.zoned.Map; import com.cg.zoned.Player; +import com.cg.zoned.Preferences; import com.cg.zoned.ScoreBar; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TeamData; @@ -89,7 +91,7 @@ private GameScreen(final Zoned game, MapManager mapManager, Player[] players, Se this.gameManager = new GameManager(this); this.gameManager.setUpConnectionManager(server, client); this.gameManager.setUpDirectionAndPlayerBuffer(players, fullScreenStage, - game.preferences.getInteger(Constants.CONTROL_PREFERENCE, Constants.PIE_MENU_CONTROL), + game.preferences.getInteger(Preferences.CONTROL_PREFERENCE, 0), game.skin, game.getScaleFactor(), usedTextures); this.batch = new SpriteBatch(); @@ -99,7 +101,7 @@ private GameScreen(final Zoned game, MapManager mapManager, Player[] players, Se currentBgColor = new Color(0, 0, 0, bgAlpha); targetBgColor = new Color(0, 0, 0, bgAlpha); - BitmapFont playerLabelFont = game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getFontName()); + BitmapFont playerLabelFont = game.skin.getFont(Assets.FontManager.PLAYER_LABEL_NOSCALE.getFontName()); initViewports(players); map.createPlayerLabelTextures(players, shapeDrawer, playerLabelFont); @@ -123,14 +125,14 @@ private void initViewports(Player[] players) { } } - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override public void show() { setUpInputProcessors(); setUpUI(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); } private void setUpUI() { diff --git a/core/src/com/cg/zoned/screens/HostJoinScreen.java b/core/src/com/cg/zoned/screens/HostJoinScreen.java index 2911368..7db000e 100644 --- a/core/src/com/cg/zoned/screens/HostJoinScreen.java +++ b/core/src/com/cg/zoned/screens/HostJoinScreen.java @@ -22,8 +22,10 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Constants; import com.cg.zoned.KryoHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -60,7 +62,7 @@ public HostJoinScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(this.game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); dialogButtonTexts.add("OK"); } @@ -69,7 +71,7 @@ public HostJoinScreen(final Zoned game) { public void show() { setUpStage(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.fadeInStage(stage); } @@ -87,14 +89,14 @@ private void setUpStage() { Image infoImage = new Image(infoIconTexture); Label infoLabel = new Label("Make sure that all players\nare on the same local network", game.skin); infoLabel.setAlignment(Align.center); - infoTable.add(infoImage).height(game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight()) - .width(game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight()).padRight(20f); + infoTable.add(infoImage).height(game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight()) + .width(game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight()).padRight(20f); infoTable.add(infoLabel).pad(10f); stage.addActor(infoTable); Label playerNameLabel = new Label("Player name: ", game.skin, "themed"); final TextField playerNameField = new TextField("", game.skin); - playerNameField.setText(game.preferences.getString(Constants.NAME_PREFERENCE, null)); + playerNameField.setText(game.preferences.getString(Preferences.NAME_PREFERENCE, null)); playerNameField.setCursorPosition(playerNameField.getText().length()); table.add(playerNameLabel).right(); table.add(playerNameField).width(playerNameField.getPrefWidth() * game.getScaleFactor()).left(); @@ -124,7 +126,7 @@ public void clicked(InputEvent event, float x, float y) { String name = playerNameField.getText().trim(); if (!name.isEmpty()) { - game.preferences.putString(Constants.NAME_PREFERENCE, name); + game.preferences.putString(Preferences.NAME_PREFERENCE, name); game.preferences.flush(); startServerLobby(playerNameField.getText().trim()); @@ -144,7 +146,7 @@ public void clicked(InputEvent event, float x, float y) { String name = playerNameField.getText().trim(); if (!name.isEmpty()) { if (searchingLabel.getColor().a == 0) { - game.preferences.putString(Constants.NAME_PREFERENCE, name); + game.preferences.putString(Preferences.NAME_PREFERENCE, name); game.preferences.flush(); searchingLabel.setText("Searching for servers..."); diff --git a/core/src/com/cg/zoned/screens/LoadingScreen.java b/core/src/com/cg/zoned/screens/LoadingScreen.java index a43d467..3bad707 100644 --- a/core/src/com/cg/zoned/screens/LoadingScreen.java +++ b/core/src/com/cg/zoned/screens/LoadingScreen.java @@ -26,9 +26,11 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.viewport.ScreenViewport; -import com.cg.zoned.Constants; +import com.cg.zoned.Assets; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.Zoned; +import com.cg.zoned.managers.ControlManager; public class LoadingScreen extends ScreenAdapter { final Zoned game; @@ -50,11 +52,22 @@ public LoadingScreen(final Zoned game) { } private void initSetup() { - game.preferences = Gdx.app.getPreferences(Constants.ZONED_PREFERENCES); - if (game.preferences.getBoolean(Constants.DISCORD_RPC_PREFERENCE, true)) { + // Set up preferences + game.preferences = Gdx.app.getPreferences(Preferences.ZONED_PREFERENCES); + + // Set up Discord RPC + if (game.preferences.getBoolean(Preferences.DISCORD_RPC_PREFERENCE, true)) { game.discordRPCManager.initRPC(); } + + // Reset player colors PlayerColorHelper.resetPlayerColorAlpha(); + + // Validate touch controls + if (game.preferences.getInteger(Preferences.CONTROL_PREFERENCE, 0) >= ControlManager.CONTROL_TYPES.length) { + game.preferences.putInteger(Preferences.CONTROL_PREFERENCE, 0); + game.preferences.flush(); + } } @Override @@ -72,7 +85,7 @@ public void show() { assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver)); assetManager.setLoader(BitmapFont.class, ".otf", new FreetypeFontLoader(resolver)); - for (Constants.FONT_MANAGER font : Constants.FONT_MANAGER.values()) { + for (Assets.FontManager font : Assets.FontManager.values()) { generateCustomFont("fonts/" + font.getFontFileName(), font.getFontName(), font.getFontSize()); } } @@ -123,7 +136,7 @@ public void render(float delta) { if (!loadedFonts) { ObjectMap fontMap = new ObjectMap<>(); - for (Constants.FONT_MANAGER font : Constants.FONT_MANAGER.values()) { + for (Assets.FontManager font : Assets.FontManager.values()) { fontMap.put(font.getFontName(), assetManager.get(font.getFontName() + ".otf", BitmapFont.class)); } diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index cdc2ad4..7ab80a5 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -29,8 +29,9 @@ import com.badlogic.gdx.utils.Scaling; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; -import com.cg.zoned.Constants; +import com.cg.zoned.Assets; import com.cg.zoned.GameMode; +import com.cg.zoned.Preferences; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -67,13 +68,13 @@ public MainMenuScreen(final Zoned game) { emitterLeft = new ParticleEffect(); emitterRight = new ParticleEffect(); - font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override public void show() { setUpMainMenu(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.startMainMenuAnimation(mainStage, mainMenuUIButtons); animationManager.setAnimationListener(new AnimationManager.AnimationListener() { @Override @@ -110,7 +111,7 @@ private void setUpMainMenu() { //mainTable.setDebug(true); mainTable.center(); - Label gameTitle = new Label("ZONED", game.skin, Constants.FONT_MANAGER.LARGE.getFontName(), Color.GREEN); + Label gameTitle = new Label("ZONED", game.skin, Assets.FontManager.STYLED_LARGE.getFontName(), Color.GREEN); mainTable.add(gameTitle).pad(10f * game.getScaleFactor()); mainTable.row(); @@ -122,7 +123,7 @@ private void setUpMainMenu() { HoverImageButton settingsButton = uiButtonManager.addSettingsButtonToStage(game.assets.getSettingsButtonTexture()); HoverImageButton creditsButton = uiButtonManager.addCreditsButtonToStage(game.assets.getCreditsButtonTexture()); HoverImageButton devButton = null; - if (game.preferences.getBoolean(Constants.DEV_MODE_PREFERENCE, false)) { + if (game.preferences.getBoolean(Preferences.DEV_MODE_PREFERENCE, false)) { devButton = uiButtonManager.addDevButtonToStage(game.assets.getDevButtonTexture()); devButton.addListener(new ClickListener() { @Override diff --git a/core/src/com/cg/zoned/screens/MapStartPosScreen.java b/core/src/com/cg/zoned/screens/MapStartPosScreen.java index 416c389..e68b33f 100644 --- a/core/src/com/cg/zoned/screens/MapStartPosScreen.java +++ b/core/src/com/cg/zoned/screens/MapStartPosScreen.java @@ -27,11 +27,13 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Cell; import com.cg.zoned.Constants; import com.cg.zoned.GameTouchPoint; import com.cg.zoned.Map; import com.cg.zoned.Player; +import com.cg.zoned.Preferences; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -99,7 +101,7 @@ public MapStartPosScreen(final Zoned game, MapManager mapManager, this.batch = new SpriteBatch(); this.shapeDrawer = new ShapeDrawer(batch, usedTextures); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override @@ -107,13 +109,13 @@ public void show() { setUpMap(); setUpStage(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.fadeInStage(stage); } private void setUpMap() { map = new Map(mapGrid, 0, shapeDrawer); // Wall count is unnecessary in this case so 0 - map.createPlayerLabelTextures(players, shapeDrawer, game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getFontName())); + map.createPlayerLabelTextures(players, shapeDrawer, game.skin.getFont(Assets.FontManager.PLAYER_LABEL_NOSCALE.getFontName())); mapDarkOverlayColor = new Color(0, 0, 0, 0.8f); mapViewports = new ExtendViewport[splitScreenCount]; for (int i = 0; i < players.length; i++) { diff --git a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java index 49fca7b..2e78e7a 100644 --- a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java +++ b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java @@ -21,10 +21,12 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Constants; import com.cg.zoned.MapSelector; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -65,12 +67,12 @@ public PlayerSetUpScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(this.game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); this.batch = new SpriteBatch(); this.shapeDrawer = new ShapeDrawer(batch, usedTextures); - this.playerCount = game.preferences.getInteger(Constants.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, 2); + this.playerCount = game.preferences.getInteger(Preferences.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, 2); this.playerList = new Table(); this.currentBgColors = new Color[this.playerCount]; @@ -85,16 +87,16 @@ public PlayerSetUpScreen(final Zoned game) { public void show() { setUpStage(); setUpUIButtons(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.setAnimationListener(new AnimationManager.AnimationListener() { @Override public void animationEnd(Stage stage) { - boolean showTutorialDialogPrompt = game.preferences.getBoolean(Constants.SHOW_TUTORIAL_PREFERENCE, true); + boolean showTutorialDialogPrompt = game.preferences.getBoolean(Preferences.SHOW_TUTORIAL_PREFERENCE, true); if (showTutorialDialogPrompt) { showTutorialDialog(); - game.preferences.putBoolean(Constants.SHOW_TUTORIAL_PREFERENCE, false); + game.preferences.putBoolean(Preferences.SHOW_TUTORIAL_PREFERENCE, false); game.preferences.flush(); } } @@ -183,7 +185,7 @@ public void buttonPressed(Button button) { mapSelector.setUsedTextureArray(usedTextures); mapSelector.getMapManager().enableExternalMapLogging(true); Spinner mapSpinner = mapSelector.loadMapSelectorSpinner(150 * game.getScaleFactor(), - game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight() * 3); + game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight() * 3); mapSelector.loadExternalMaps(); table.add(mapSpinner).colspan(NO_OF_COLORS + 1).pad(20 * game.getScaleFactor()).expandX(); table.row(); @@ -237,7 +239,7 @@ private void startGame(Array playerColors, MapManager mapManager) { players[i].setControlIndex(i % Constants.PLAYER_CONTROLS.length); } - int startPosSplitScreenCount = game.preferences.getInteger(Constants.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, 2); + int startPosSplitScreenCount = game.preferences.getInteger(Preferences.MAP_START_POS_SPLITSCREEN_COUNT_PREFERENCE, 2); animationManager.fadeOutStage(stage, this, new MapStartPosScreen(game, mapManager, players, startPosSplitScreenCount, false)); } diff --git a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java index 971f70b..1206aa8 100644 --- a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java @@ -28,11 +28,13 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Cell; import com.cg.zoned.Constants; import com.cg.zoned.MapSelector; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -84,7 +86,7 @@ public ServerLobbyScreen(final Zoned game, Server server, String name) { viewport = new ScreenViewport(); stage = new FocusableStage(viewport); animationManager = new AnimationManager(this.game, this); - font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); // TODO: Fix bogus client ip being sent to some clients when a map is changed while a new client was joining @@ -98,7 +100,7 @@ public void show() { setUpServerLobbyStage(); setUpMap(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); playerConnected(null); connectionManager.start(); @@ -129,7 +131,7 @@ private void setUpServerLobbyStage() { mapSelector = new MapSelector(stage, game.getScaleFactor(), game.assets, game.skin); mapSelector.setUsedTextureArray(usedTextures); final Spinner mapSpinner = mapSelector.loadMapSelectorSpinner(150 * game.getScaleFactor(), - game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getFontName()).getLineHeight() * 3); + game.skin.getFont(Assets.FontManager.REGULAR.getFontName()).getLineHeight() * 3); final Table mapSelectorTable = new Table(); mapSelectorTable.add(mapSpinner).pad(10f); diff --git a/core/src/com/cg/zoned/screens/SettingsScreen.java b/core/src/com/cg/zoned/screens/SettingsScreen.java index c2bd60d..783d8c9 100644 --- a/core/src/com/cg/zoned/screens/SettingsScreen.java +++ b/core/src/com/cg/zoned/screens/SettingsScreen.java @@ -21,10 +21,13 @@ import com.badlogic.gdx.utils.Scaling; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; -import com.cg.zoned.Constants; +import com.cg.zoned.Assets; +import com.cg.zoned.Preferences; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; +import com.cg.zoned.controls.ControlType; import com.cg.zoned.managers.AnimationManager; +import com.cg.zoned.managers.ControlManager; import com.cg.zoned.managers.UIButtonManager; import com.cg.zoned.ui.FocusableStage; import com.cg.zoned.ui.HoverCheckBox; @@ -49,7 +52,7 @@ public SettingsScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(this.game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); } @Override @@ -71,82 +74,79 @@ private void setUpStage() { ScrollPane screenScrollPane = new ScrollPane(table); screenScrollPane.setOverscroll(false, true); - Label controlLabel = new Label("Control scheme", game.skin, "themed"); - Texture controlFlingOffTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_control_fling_off.png")); - Texture controlFlingOnTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_control_fling_on.png")); - Texture controlPiemenuOffTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_control_piemenu_off.png")); - Texture controlPiemenuOnTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_control_piemenu_on.png")); - usedTextures.add(controlFlingOffTexture); - usedTextures.add(controlFlingOnTexture); - usedTextures.add(controlPiemenuOffTexture); - usedTextures.add(controlPiemenuOnTexture); - Drawable controlFlingOff = new TextureRegionDrawable(controlFlingOffTexture); - Drawable controlFlingOn = new TextureRegionDrawable(controlFlingOnTexture); - Drawable controlPiemenuOff = new TextureRegionDrawable(controlPiemenuOffTexture); - Drawable controlPiemenuOn = new TextureRegionDrawable(controlPiemenuOnTexture); - final HoverImageButton flingControl = new HoverImageButton(controlFlingOff, controlFlingOn); - final HoverImageButton piemenuControl = new HoverImageButton(controlPiemenuOff, controlPiemenuOn); - final Label flingControlLabel = new Label("Fling", game.skin); - Label piemenuControlLabel = new Label("Piemenu", game.skin); - flingControl.setHoverAlpha(.7f); - piemenuControl.setHoverAlpha(.7f); - flingControl.setClickAlpha(.4f); - piemenuControl.setClickAlpha(.4f); - int currentControl = game.preferences.getInteger(Constants.CONTROL_PREFERENCE, Constants.PIE_MENU_CONTROL); - if (currentControl == Constants.PIE_MENU_CONTROL) { - piemenuControl.setChecked(true); - } else if (currentControl == Constants.FLING_CONTROL) { - flingControl.setChecked(true); - } - flingControl.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - if (piemenuControl.isChecked()) { - game.preferences.putInteger(Constants.CONTROL_PREFERENCE, Constants.FLING_CONTROL); - game.preferences.flush(); - piemenuControl.toggle(); - } else { - flingControl.toggle(); - } + ControlType[] controlTypes = ControlManager.CONTROL_TYPES; + int currentControl = game.preferences.getInteger(Preferences.CONTROL_PREFERENCE, 0); + + Label controlSchemeLabel = new Label("Control scheme", game.skin, "themed"); + table.add(controlSchemeLabel).colspan(controlTypes.length).padBottom(10f); + table.row(); + + final HoverImageButton[] controlButtons = new HoverImageButton[controlTypes.length]; + final Label[] controlLabels = new Label[controlTypes.length]; + for (int i = 0; i < controlTypes.length; i++) { + ControlType controlType = controlTypes[i]; + + Texture controlOffTexture = new Texture(Gdx.files.internal(controlType.controlOffTexturePath)); + Texture controlOnTexture = new Texture(Gdx.files.internal(controlType.controlOnTexturePath)); + usedTextures.add(controlOffTexture); + usedTextures.add(controlOnTexture); + + Drawable controlOff = new TextureRegionDrawable(controlOffTexture); + Drawable controlOn = new TextureRegionDrawable(controlOnTexture); + + controlButtons[i] = new HoverImageButton(controlOff, controlOn); + controlLabels[i] = new Label(controlType.controlName, game.skin); + + controlButtons[i].setHoverAlpha(.7f); + controlButtons[i].setClickAlpha(.4f); + + if (i == currentControl) { + controlButtons[i].setChecked(true); } - }); - piemenuControl.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - if (flingControl.isChecked()) { - game.preferences.putInteger(Constants.CONTROL_PREFERENCE, Constants.PIE_MENU_CONTROL); - game.preferences.flush(); - flingControl.toggle(); - } else { - piemenuControl.toggle(); + + final int controlIndex = i; + controlButtons[i].addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + int currentControl = game.preferences.getInteger(Preferences.CONTROL_PREFERENCE, 0); + if (controlButtons[currentControl].isChecked()) { + game.preferences.putInteger(Preferences.CONTROL_PREFERENCE, controlIndex); + game.preferences.flush(); + controlButtons[currentControl].toggle(); + } else { + controlButtons[controlIndex].toggle(); + } } - } - }); + }); + } - table.add(controlLabel).colspan(2).padBottom(10f); - table.row(); - table.add(piemenuControl).padLeft(5f); - table.add(flingControl).padRight(5f); + for (HoverImageButton controlButton : controlButtons) { + table.add(controlButton).space(5f); + stage.addFocusableActor(controlButton); + } table.row(); - table.add(piemenuControlLabel).padLeft(5f); - table.add(flingControlLabel).padRight(5f); + stage.row(); + for (Label controlLabel : controlLabels) { + table.add(controlLabel).space(5f); + } table.row(); + final HoverCheckBox showFPS = new HoverCheckBox("Show FPS counter", game.skin); showFPS.getImageCell().width(showFPS.getLabel().getPrefHeight()).height(showFPS.getLabel().getPrefHeight()); showFPS.getImage().setScaling(Scaling.fill); - showFPS.setChecked(game.preferences.getBoolean(Constants.FPS_PREFERENCE, false)); + showFPS.setChecked(game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false)); showFPSCounter = showFPS.isChecked(); showFPS.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { - game.preferences.putBoolean(Constants.FPS_PREFERENCE, showFPS.isChecked()); + game.preferences.putBoolean(Preferences.FPS_PREFERENCE, showFPS.isChecked()); game.preferences.flush(); showFPSCounter = showFPS.isChecked(); } }); - table.add(showFPS).colspan(2).padTop(30f); + table.add(showFPS).colspan(controlTypes.length).padTop(30f); table.row(); HoverCheckBox discordRPCSwitch = null; @@ -154,7 +154,7 @@ public void changed(ChangeEvent event, Actor actor) { discordRPCSwitch = new HoverCheckBox("Enable Discord Rich Presence", game.skin); discordRPCSwitch.getImageCell().width(discordRPCSwitch.getLabel().getPrefHeight()).height(discordRPCSwitch.getLabel().getPrefHeight()); discordRPCSwitch.getImage().setScaling(Scaling.fill); - discordRPCSwitch.setChecked(game.preferences.getBoolean(Constants.DISCORD_RPC_PREFERENCE, true)); + discordRPCSwitch.setChecked(game.preferences.getBoolean(Preferences.DISCORD_RPC_PREFERENCE, true)); discordRPCSwitch.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { @@ -166,23 +166,20 @@ public void changed(ChangeEvent event, Actor actor) { game.discordRPCManager.shutdownRPC(); } - game.preferences.putBoolean(Constants.DISCORD_RPC_PREFERENCE, discordRPCSwitch.isChecked()); + game.preferences.putBoolean(Preferences.DISCORD_RPC_PREFERENCE, discordRPCSwitch.isChecked()); game.preferences.flush(); } }); - table.add(discordRPCSwitch).colspan(2).padTop(30f); + table.add(discordRPCSwitch).colspan(controlTypes.length).padTop(30f); } masterTable.add(screenScrollPane).grow(); stage.addActor(masterTable); - stage.addFocusableActor(piemenuControl); - stage.addFocusableActor(flingControl); - stage.row(); - stage.addFocusableActor(showFPS, 2); + stage.addFocusableActor(showFPS, controlTypes.length); if (Gdx.app.getType() == Application.ApplicationType.Desktop) { stage.row(); - stage.addFocusableActor(discordRPCSwitch, 2); + stage.addFocusableActor(discordRPCSwitch, controlTypes.length); } stage.setScrollFocus(screenScrollPane); } diff --git a/core/src/com/cg/zoned/screens/TutorialScreen.java b/core/src/com/cg/zoned/screens/TutorialScreen.java index 0085340..95892c4 100644 --- a/core/src/com/cg/zoned/screens/TutorialScreen.java +++ b/core/src/com/cg/zoned/screens/TutorialScreen.java @@ -27,11 +27,13 @@ import com.badlogic.gdx.utils.viewport.ExtendViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; +import com.cg.zoned.Assets; import com.cg.zoned.Cell; import com.cg.zoned.Constants; import com.cg.zoned.Map; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TutorialItem; import com.cg.zoned.UITextDisplayer; @@ -77,7 +79,7 @@ public TutorialScreen(final Zoned game) { this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); this.batch = new SpriteBatch(); this.shapeDrawer = new ShapeDrawer(batch, usedTextures); @@ -99,10 +101,10 @@ private void initMap() { this.players[0] = new Player(PlayerColorHelper.getColorFromString("GREEN"), "Player"); this.players[0].position = new Vector2(Math.round(this.mapGrid.length / 2f), Math.round(this.mapGrid[0].length / 2f)); this.players[0].setControlIndex(0); - this.playerLabelFont = game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getFontName()); + this.playerLabelFont = game.skin.getFont(Assets.FontManager.PLAYER_LABEL_NOSCALE.getFontName()); this.map.createPlayerLabelTextures(this.players, shapeDrawer, playerLabelFont); this.controlManager = new ControlManager(players, stage); - this.controlManager.setUpControls(game.preferences.getInteger(Constants.CONTROL_PREFERENCE), + this.controlManager.setUpControls(game.preferences.getInteger(Preferences.CONTROL_PREFERENCE, 0), false, game.getScaleFactor(), usedTextures); } @@ -123,7 +125,7 @@ public void show() { setUpStage(); setUpBackButton(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); animationManager.fadeInStage(stage); } diff --git a/core/src/com/cg/zoned/screens/VictoryScreen.java b/core/src/com/cg/zoned/screens/VictoryScreen.java index 0814fa5..5857b2b 100644 --- a/core/src/com/cg/zoned/screens/VictoryScreen.java +++ b/core/src/com/cg/zoned/screens/VictoryScreen.java @@ -25,8 +25,9 @@ import com.badlogic.gdx.utils.StringBuilder; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; -import com.cg.zoned.Constants; +import com.cg.zoned.Assets; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.Preferences; import com.cg.zoned.TeamData; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -69,7 +70,7 @@ public VictoryScreen(final Zoned game, PlayerManager playerManager, int rows, in this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(this.game, this); - this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getFontName()); + this.font = game.skin.getFont(Assets.FontManager.SMALL.getFontName()); getVictoryStrings(playerManager, rows, cols, wallCount); } @@ -77,7 +78,7 @@ public VictoryScreen(final Zoned game, PlayerManager playerManager, int rows, in @Override public void show() { setUpStage(); - showFPSCounter = game.preferences.getBoolean(Constants.FPS_PREFERENCE, false); + showFPSCounter = game.preferences.getBoolean(Preferences.FPS_PREFERENCE, false); trailEffect = new ParticleEffect(); trailEffect.setPosition(0, stage.getHeight() / 2f); @@ -102,7 +103,7 @@ private void setUpStage() { table.setFillParent(true); table.center(); - Label gameOver = new Label("GAME OVER", game.skin, Constants.FONT_MANAGER.LARGE.getFontName(), Color.GREEN); + Label gameOver = new Label("GAME OVER", game.skin, Assets.FontManager.STYLED_LARGE.getFontName(), Color.GREEN); table.add(gameOver); stage.addActor(table); @@ -151,12 +152,10 @@ private void setUpVictoryUI() { if (i > 0 && teamData.get(i - 1).getScore() == teamData.get(i).getScore()) { rankIndex--; } - rankLabels[i] = new Label("#" + (rankIndex + 1), game.skin, Constants.FONT_MANAGER.REGULAR.getFontName(), rankColors[Math.min(rankIndex, 3)]); - victoryLabels[i] = new Label(victoryStrings[i], game.skin, Constants.FONT_MANAGER.REGULAR.getFontName(), rankColors[Math.min(rankIndex, 3)]); + rankLabels[i] = new Label("#" + (rankIndex + 1), game.skin, Assets.FontManager.REGULAR.getFontName(), rankColors[Math.min(rankIndex, 3)]); + victoryLabels[i] = new Label(victoryStrings[i], game.skin, Assets.FontManager.REGULAR.getFontName(), rankColors[Math.min(rankIndex, 3)]); if (rankIndex < rankImageLocations.length) { rankImages[i] = new Image(rankImageTextures[rankIndex]); - } else { - rankImages[i] = null; } if (rankLabels[i].getPrefWidth() > rankLabelMaxWidth) { @@ -164,7 +163,7 @@ private void setUpVictoryUI() { } } - Label scoreBoardTitle = new Label("SCOREBOARD", game.skin); + Label scoreBoardTitle = new Label("SCOREBOARD", game.skin, Assets.FontManager.STYLED_SMALL.getFontName(), Color.WHITE); // Setting background drawable on a container since setting it directly to the label means // I'll have to reset it otherwise other labels will have it as well since it's the same object scoreBoardTitleContainer = new Container<>(scoreBoardTitle); From 258bb8b7661176e5dbb52797c333dd334cff30c3 Mon Sep 17 00:00:00 2001 From: Spikatrix <12792882+Spikatrix@users.noreply.github.com> Date: Wed, 9 Sep 2020 20:59:08 +0530 Subject: [PATCH 33/35] VictoryScreen improvements Was trying out different victory screen layouts and animations in the last couple of days, this looks better than the previous one and has a better code structure --- core/src/com/cg/zoned/Assets.java | 1 + .../cg/zoned/managers/AnimationManager.java | 61 +++--- .../com/cg/zoned/screens/VictoryScreen.java | 179 ++++++++++++------ 3 files changed, 155 insertions(+), 86 deletions(-) diff --git a/core/src/com/cg/zoned/Assets.java b/core/src/com/cg/zoned/Assets.java index ee95b9c..e36715e 100644 --- a/core/src/com/cg/zoned/Assets.java +++ b/core/src/com/cg/zoned/Assets.java @@ -42,6 +42,7 @@ public void dispose() { assetManager.dispose(); } + // TODO: The default font size is way too big (really noticeable on mobile screens) public enum FontManager { STYLED_LARGE ("recharge.otf", 65), STYLED_SMALL ("recharge.otf", 24), diff --git a/core/src/com/cg/zoned/managers/AnimationManager.java b/core/src/com/cg/zoned/managers/AnimationManager.java index d43c7c4..74fd09d 100644 --- a/core/src/com/cg/zoned/managers/AnimationManager.java +++ b/core/src/com/cg/zoned/managers/AnimationManager.java @@ -13,7 +13,6 @@ import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; import com.badlogic.gdx.scenes.scene2d.ui.Container; import com.badlogic.gdx.scenes.scene2d.ui.Label; -import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.utils.Array; import com.cg.zoned.Zoned; @@ -173,43 +172,49 @@ public void run() { stage.addAction(fadeOutAnimation); } - public void startScoreBoardAnimation(final Stage stage, Container