diff --git a/README.md b/README.md index 73ff544..1b26110 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# 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.1-beta](https://img.shields.io/badge/version-0.0.1--beta-orange)](https://github.com/Spikatrix/Zoned/releases/tag/v0.0.1-beta) [![Discord](https://img.shields.io/discord/712603681949745213)](https://discord.gg/MFBkvqw) +# 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 Icon -Zoned is a cross-platform grid based multiplayer strategy game powered by [libGDX][libGDX]. The game is primarily targeted for Android, but it will work just fine on Windows and Linux as well. +Zoned is a cross-platform grid based multiplayer strategy game powered by [libGDX][libGDX]. The game is prima`rily targeted for Android, but it will work just fine on Windows and Linux as well. It is available to download on the [Google Play Store][play_store_page] (Android) as well as on [GitHub][github_release_page] (Windows, Linux and Android) @@ -45,8 +45,6 @@ You can then find the generated binaries at ## Contributing -Zoned is a FOSS game developed by [me](https://github.com/Spikatrix). I'm available on [Discord][discord_invite] if you want to have a chat with me. - Contributions are always welcome. Here are a few ways you can help: @@ -65,5 +63,4 @@ This project is licensed under the [GNU GPLv3 License][project_license] [issue_tracker]: https://github.com/Spikatrix/Zoned/issues [email_feedback]: mailto:cg.devworks@gmail.com?subject=Zoned+Feedback&body=Your+feedback+here [custom_external_map_wiki]: https://github.com/Spikatrix/Zoned/wiki/Custom-External-Maps -[discord_invite]: https://discord.gg/MFBkvqw [project_license]: https://github.com/Spikatrix/Zoned/blob/master/LICENSE diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index c7a713b..1b9612e 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/android/assets/icons/ic_discord.png b/android/assets/icons/ic_discord.png deleted file mode 100644 index db0e70d..0000000 Binary files a/android/assets/icons/ic_discord.png and /dev/null differ diff --git a/android/assets/neon-skin/neon-ui.atlas b/android/assets/neon-skin/neon-ui.atlas index d8c5d81..ebcfe4b 100644 --- a/android/assets/neon-skin/neon-ui.atlas +++ b/android/assets/neon-skin/neon-ui.atlas @@ -196,7 +196,7 @@ scroll-horizontal index: -1 scroll-vertical rotate: false - xy: 393, 39 + xy: 193, 39 size: 27, 44 split: 11, 11, 11, 11 pad: 0, 0, 0, 0 diff --git a/android/assets/particles/radial_particle_emitter.p b/android/assets/particles/radial_particle_emitter.p index 0cc3df8..9b5b4bd 100644 --- a/android/assets/particles/radial_particle_emitter.p +++ b/android/assets/particles/radial_particle_emitter.p @@ -2,16 +2,16 @@ RadialEmitter - Delay - active: false - Duration - -lowMin: 1000.0 -lowMax: 1000.0 +lowMin: 100.0 +lowMax: 100.0 - Count - min: 0 -max: 380 +max: 50 - Emission - -lowMin: 250.0 -lowMax: 250.0 -highMin: 250.0 -highMax: 250.0 +lowMin: 150.0 +lowMax: 150.0 +highMin: 150.0 +highMax: 150.0 relative: false scalingCount: 1 scaling0: 1.0 @@ -20,8 +20,8 @@ timeline0: 0.0 - Life - lowMin: 0.0 lowMax: 0.0 -highMin: 1500.0 -highMax: 1500.0 +highMin: 500.0 +highMax: 500.0 relative: false scalingCount: 1 scaling0: 1.0 @@ -120,22 +120,22 @@ highMin: 1.0 highMax: 1.0 relative: false scalingCount: 6 -scaling0: 0.46067417 -scaling1: 0.25842696 -scaling2: 0.252809 -scaling3: 0.17977528 -scaling4: 0.09550562 +scaling0: 0.20224719 +scaling1: 0.15730338 +scaling2: 0.12280702 +scaling3: 0.07017544 +scaling4: 0.028089888 scaling5: 0.0 timelineCount: 6 timeline0: 0.0 -timeline1: 0.25699747 -timeline2: 0.53435117 -timeline3: 0.77099234 -timeline4: 0.89694655 +timeline1: 0.21198668 +timeline2: 0.5068493 +timeline3: 0.7671233 +timeline4: 0.8945616 timeline5: 1.0 - Options - attached: false -continuous: true +continuous: false aligned: false additive: false behind: false diff --git a/android/build.gradle b/android/build.gradle index 657220b..c92737e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -20,19 +20,30 @@ android { applicationId "com.cg.zoned" minSdkVersion 14 targetSdkVersion 29 - versionCode 1 - versionName "0.0.1-beta" + versionCode 2 + versionName "0.0.2-beta" // 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 // Or for Linux users, use the versionUpdate.sh script } buildTypes { release { - minifyEnabled false // Don't set this to true because it'll result in a lot of classes missing causing Runtime crashes + minifyEnabled false // Don't set this to true because it'll result in a lot of classes missing causing Runtime crashes (Unless you `-keep` them all) shrinkResources false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + applicationVariants.all { variant -> + variant.outputs.all { output -> + if (variant.name == "debug") { + outputFileName = "${appName}-${versionName}-${variant.name}.apk" + } else { + outputFileName = "${appName}-${versionName}.apk" + } + } + } } diff --git a/android/src/com/cg/zoned/AndroidLauncher.java b/android/src/com/cg/zoned/AndroidLauncher.java index 1fb41ed..14fdf77 100644 --- a/android/src/com/cg/zoned/AndroidLauncher.java +++ b/android/src/com/cg/zoned/AndroidLauncher.java @@ -15,6 +15,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!BuildConfig.VERSION_NAME.equals(Constants.GAME_VERSION)) { + // Used as a precaution Toast.makeText(getApplicationContext(), "GAME VERSION MISMATCH (" + BuildConfig.VERSION_NAME + " and " + Constants.GAME_VERSION + ")", Toast.LENGTH_LONG).show(); diff --git a/build.gradle b/build.gradle index a43903b..3eadf0a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ allprojects { version = '1.0' ext { - appName = "zoned" + appName = "Zoned" gdxVersion = '1.9.10' roboVMVersion = '2.3.6' box2DLightsVersion = '1.4' @@ -47,6 +47,8 @@ project(":desktop") { api "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion" api "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" api "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" + + implementation files("../core/libs/discord-rpc.jar") } } @@ -73,6 +75,7 @@ project(":android") { } } +// No HTML support since the game uses Kryonet which isn't supported there /*project(":html") { apply plugin: "gwt" apply plugin: "war" @@ -95,6 +98,9 @@ project(":core") { api "com.esotericsoftware:kryonet:2.22.0-RC1" api "com.github.payne911:PieMenu:$pieMenuVersion" + // Pie menu depends on ShapeDrawer, so that'll get imported as well + + implementation files("libs/discord-rpc.jar") } } diff --git a/core/libs/discord-rpc.jar b/core/libs/discord-rpc.jar new file mode 100644 index 0000000..ef5c4bb Binary files /dev/null and b/core/libs/discord-rpc.jar differ diff --git a/core/src/com/cg/zoned/Assets.java b/core/src/com/cg/zoned/Assets.java new file mode 100644 index 0000000..9df302b --- /dev/null +++ b/core/src/com/cg/zoned/Assets.java @@ -0,0 +1,44 @@ +package com.cg.zoned; + +import com.badlogic.gdx.assets.AssetManager; +import com.badlogic.gdx.graphics.Texture; + +public class Assets { + private AssetManager assetManager; + + public Texture getPlayButtonTexture() { + return assetManager.get("icons/ui_icons/ic_play_sheet.png", Texture.class); + } + + public Texture getBackButtonTexture() { + return assetManager.get("icons/ui_icons/ic_back.png", Texture.class); + } + + public Texture getCreditsButtonTexture() { + return assetManager.get("icons/ui_icons/ic_credits.png", Texture.class); + } + + public Texture getCrossButtonTexture() { + return assetManager.get("icons/ui_icons/ic_cross.png", Texture.class); + } + + public Texture getDevButtonTexture() { + return assetManager.get("icons/ui_icons/ic_dev.png", Texture.class); + } + + public Texture getSettingsButtonTexture() { + return assetManager.get("icons/ui_icons/ic_settings.png", Texture.class); + } + + public Texture getTutorialButtonTexture() { + return assetManager.get("icons/ui_icons/ic_tutorial.png", Texture.class); + } + + public void setAssetManager(AssetManager assetManager) { + this.assetManager = assetManager; + } + + public void dispose() { + assetManager.dispose(); + } +} diff --git a/core/src/com/cg/zoned/Constants.java b/core/src/com/cg/zoned/Constants.java index 2280a7a..1e3bd19 100644 --- a/core/src/com/cg/zoned/Constants.java +++ b/core/src/com/cg/zoned/Constants.java @@ -7,14 +7,22 @@ import java.util.Map; public final class Constants { - public static final String GAME_VERSION = "0.0.1-beta"; + public static final String GAME_VERSION = "0.0.2-beta"; // 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 // Or for Linux users, use the versionUpdate.sh script + /** + * Enables Discord Rich Presence functionality on Windows and Linux + *

+ * Note: When this is enabled, running multiple instances of the game will crash with a SIGSEGV + */ + public static final boolean ENABLE_DISCORD_RPC = true; + public static final float WORLD_SIZE = 480.0f; - public static final int SERVER_PORT = 22355; // Random port I chose *shrug* + public static final int SERVER_PORT = 22355; // Random port I chose ¯\_(ツ)_/¯ public static final float CELL_SIZE = 25.0f; public static final Color MAP_GRID_COLOR = Color.WHITE; @@ -86,6 +94,7 @@ public final class Constants { public static final float ANDROID_XXXHDPI_FONT_SCALE_FACTOR = 4.0f; public static final String LOG_TAG = "ZONED"; + public static final String ZONED_PREFERENCES = "Zoned_Preferences"; public static final String FPS_PREFERENCE = "FPS_Preference"; public static final String CONTROL_PREFERENCE = "Control_Preference"; @@ -102,7 +111,7 @@ public enum Direction {UP, LEFT, DOWN, RIGHT} public enum FONT_MANAGER { LARGE("large-font", 80), - REGULAR("regular-font", 36), + REGULAR("regular-font", 32), SMALL("small-font", 18), PLAYER_LABEL("player-label-font-noscale", 20); diff --git a/core/src/com/cg/zoned/Map.java b/core/src/com/cg/zoned/Map.java index b2ee8d2..f96e938 100644 --- a/core/src/com/cg/zoned/Map.java +++ b/core/src/com/cg/zoned/Map.java @@ -2,19 +2,25 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.math.Rectangle; 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; -public class Map { +import space.earlygrey.shapedrawer.JoinType; +public class Map { private Cell[][] mapGrid; public int wallCount; @@ -22,11 +28,170 @@ public class Map { public int cols; private int coloredCells = 0; - public Map(Cell[][] mapGrid, int wallCount) { + private boolean mapColorUpdated = false; + + private Rectangle userViewRect = null; + + private FrameBuffer playerLabelFbo = null; + private TextureRegion[] playerLabels = null; + + private FrameBuffer playerFbo = null; + private TextureRegion playerTextureRegion = null; + + private FrameBuffer mapFbo = null; + private TextureRegion mapTextureRegion = null; + + /** + * Creates the map object with features like processing each turn and managing score, rendering + * the grid and more + * + * @param mapGrid Array of {@link Cell}s of the map grid + * @param wallCount Amount of walls in the grid; used for determining winner early in 2 player games + * @param shapeDrawer Used to prepare grid and player textures for rendering + */ + public Map(Cell[][] mapGrid, int wallCount, ShapeDrawer shapeDrawer) { this.rows = mapGrid.length; this.cols = mapGrid[0].length; this.mapGrid = mapGrid; this.wallCount = wallCount; + + userViewRect = new Rectangle(); + + createPlayerTexture(shapeDrawer); + createMapTexture(shapeDrawer); + } + + private void createPlayerTexture(ShapeDrawer shapeDrawer) { + int size = (int) Constants.CELL_SIZE; + + Batch batch = shapeDrawer.getBatch(); + batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0, 0, size, size)); + + if (playerFbo != null) { + playerFbo.dispose(); + } + + playerFbo = new FrameBuffer(Pixmap.Format.RGB565, size, size, false); + playerFbo.begin(); + batch.begin(); + + Gdx.gl.glClearColor(0, 0, 0, 1); + 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); + + batch.end(); + playerFbo.end(); + + playerTextureRegion = new TextureRegion(playerFbo.getColorBufferTexture(), size, size); + playerTextureRegion.flip(false, true); + } + + private 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); + + Batch batch = shapeDrawer.getBatch(); + batch.setProjectionMatrix(new Matrix4().setToOrtho2D( + -Constants.MAP_GRID_LINE_WIDTH / 2, -Constants.MAP_GRID_LINE_WIDTH / 2, width, height)); + + if (mapFbo != null) { + mapFbo.dispose(); + } + + mapFbo = new FrameBuffer(Pixmap.Format.RGB565, width, height, false); + mapFbo.begin(); + batch.begin(); + + Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + drawGrid(shapeDrawer); + + batch.end(); + mapFbo.end(); + + mapTextureRegion = new TextureRegion(mapFbo.getColorBufferTexture(), width, height); + mapTextureRegion.flip(false, true); + } + + public void createPlayerLabelTextures(Player[] players, ShapeDrawer shapeDrawer, BitmapFont playerLabelFont) { + playerLabels = new TextureRegion[players.length]; + + int totalHeight = ((int) playerLabelFont.getLineHeight()) * players.length; + int height = totalHeight / players.length; + int width = (int) (Constants.CELL_SIZE * 3f); + float radius = height / 2f; + + Batch batch = shapeDrawer.getBatch(); + batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0, 0, width, totalHeight)); + + if (playerLabelFbo != null) { + playerLabelFbo.dispose(); + } + + playerLabelFbo = new FrameBuffer(Pixmap.Format.RGB565, width, totalHeight, false); + playerLabelFbo.begin(); + batch.begin(); + + Gdx.gl.glClearColor(0, 0, 0, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + for (int i = 0; i < playerLabels.length; i++) { + int yOffset = i * height; + players[i].color.a = .7f; + + shapeDrawer.setColor(players[i].color); + shapeDrawer.filledRectangle(radius, yOffset, width - (2 * radius), height); + shapeDrawer.sector(radius, yOffset + height - radius, radius, + (float) Math.toRadians(90f), (float) Math.toRadians(180f)); + shapeDrawer.sector(width - radius, yOffset + height - radius, radius, + (float) Math.toRadians(270f), (float) Math.toRadians(180)); + + playerLabelFont.setColor(Color.WHITE); + playerLabelFont.draw(batch, players[i].name, + 0.75f * radius, yOffset + (height / 2f) + (playerLabelFont.getLineHeight() / 4f), + 0, players[i].name.length(), + width - (1.5f * radius), Align.center, false, "..."); + + players[i].color.a = 1f; + } + batch.end(); + playerLabelFbo.end(); + + TextureRegion textureRegion = new TextureRegion(playerLabelFbo.getColorBufferTexture(), width, totalHeight); + for (int i = 0; i < playerLabels.length; i++) { + int yOffset = i * height; + playerLabels[i] = new TextureRegion(textureRegion, 0, yOffset, width, height); + playerLabels[i].flip(false, true); + } + } + + private void drawGrid(ShapeDrawer shapeDrawer) { + shapeDrawer.setColor(Constants.MAP_GRID_COLOR); + + for (int i = 0; i < rows + 1; i++) { + float rowLineY = (i * Constants.CELL_SIZE); + shapeDrawer.line(-Constants.MAP_GRID_LINE_WIDTH / 2, rowLineY, + (cols * Constants.CELL_SIZE) + Constants.MAP_GRID_LINE_WIDTH, rowLineY, Constants.MAP_GRID_LINE_WIDTH); + } + for (int i = 0; i < cols + 1; i++) { + float colLineX = (i * Constants.CELL_SIZE); + shapeDrawer.line(colLineX, -Constants.MAP_GRID_LINE_WIDTH / 2, + colLineX, (rows * Constants.CELL_SIZE) + Constants.MAP_GRID_LINE_WIDTH, Constants.MAP_GRID_LINE_WIDTH); + } + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + float startX = j * Constants.CELL_SIZE; + float startY = i * Constants.CELL_SIZE; + + if (!mapGrid[i][j].isMovable) { + shapeDrawer.filledRectangle(startX, startY, Constants.CELL_SIZE, Constants.CELL_SIZE); + } + } + } } public void update(PlayerManager playerManager, float delta) { @@ -34,7 +199,8 @@ public void update(PlayerManager playerManager, float delta) { } public void update(PlayerManager playerManager, Player[] players, float delta) { - boolean waitForMovementCompletion = false; // Used to synchronize movement of all players + boolean waitForMovementCompletion = false; + // Used to synchronize movement of all players // so that every one of them moves together for (Player player : players) { @@ -51,24 +217,42 @@ public void update(PlayerManager playerManager, Player[] players, float delta) { continue; } + mapColorUpdated = false; // Might need a bit more testing + Direction direction = player.direction; - if (direction == Direction.UP && player.position.y < rows - 1 && mapGrid[Math.round(player.position.y) + 1][Math.round(player.position.x)].isMovable) { + if (direction == 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 && mapGrid[Math.round(player.position.y)][Math.round(player.position.x) + 1].isMovable) { + + } else if (direction == 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 && mapGrid[Math.round(player.position.y) - 1][Math.round(player.position.x)].isMovable) { + + } else if (direction == 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 && mapGrid[Math.round(player.position.y)][Math.round(player.position.x) - 1].isMovable) { + + } else if (direction == 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); + } else { player.dummyMoveTo(new Vector2(1, 0), delta); } } } - if (!waitForMovementCompletion) { // If movement(s) have completed - setMapWeights(players); - setMapColors(playerManager, players); + if (!waitForMovementCompletion) { // If movement(s) are completed + if (!mapColorUpdated) { + mapColorUpdated = true; + + setMapWeights(players); + setMapColors(playerManager, players); + } } } @@ -167,126 +351,80 @@ private void fillSurroundedCells(PlayerManager playerManager, Player[] players) } } - public void render(Player[] players, ShapeRenderer renderer, OrthographicCamera camera, float delta) { - drawColors(renderer, camera, delta); - drawPlayers(players, camera, renderer); - drawGrid(camera, renderer); + private Rectangle calcUserViewRect(OrthographicCamera camera) { + float x = camera.position.x; + float y = camera.position.y; + float width = camera.viewportWidth * camera.zoom; + float height = camera.viewportHeight * camera.zoom; + + userViewRect.set(x - (width / 2) - Constants.CELL_SIZE, y - (height / 2) - Constants.CELL_SIZE, + width + Constants.CELL_SIZE, height + Constants.CELL_SIZE); + + return userViewRect; + } + + public void render(Player[] players, ShapeDrawer shapeDrawer, OrthographicCamera camera, float delta) { + Rectangle userViewRect = calcUserViewRect(camera); + + drawColors(shapeDrawer, userViewRect, delta); + + Batch batch = shapeDrawer.getBatch(); + batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); + + drawGrid(userViewRect, 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, OrthographicCamera camera, ShapeRenderer renderer) { - Gdx.gl.glLineWidth(Constants.PLAYER_CIRCLE_WIDTH); - renderer.set(ShapeRenderer.ShapeType.Line); + private void drawPlayers(Player[] players, Rectangle userViewRect, Batch batch) { for (Player player : players) { - player.render(camera, renderer); + player.render(userViewRect, batch, playerTextureRegion); } - renderer.set(ShapeRenderer.ShapeType.Filled); } - private void drawColors(ShapeRenderer renderer, OrthographicCamera camera, float delta) { - float x = camera.position.x; - float y = camera.position.y; - float width = camera.viewportWidth * camera.zoom; - float height = camera.viewportHeight * camera.zoom; - + private void drawColors(ShapeDrawer shapeDrawer, 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 ((startX >= x - width) && (startX + Constants.CELL_SIZE <= x + width) && - (startY >= y - height) && (startY + Constants.CELL_SIZE <= y + height)) { - if (mapGrid[i][j].cellColor != null) { - renderer.setColor(mapGrid[i][j].cellColor); - renderer.rect(startX, startY, - Constants.CELL_SIZE, 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); + mapGrid[i][j].cellColor.add(0, 0, 0, 2f * delta); - // 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 if (!mapGrid[i][j].isMovable) { - renderer.setColor(Constants.MAP_GRID_COLOR); - renderer.rect(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; } } } } } - private void drawGrid(OrthographicCamera camera, ShapeRenderer renderer) { - float x = camera.position.x; - float y = camera.position.y; - float width = camera.viewportWidth * camera.zoom; - float height = camera.viewportHeight * camera.zoom; - - renderer.setColor(Constants.MAP_GRID_COLOR); - for (int i = 0; i < this.rows + 1; i++) { - if (i * Constants.CELL_SIZE >= y - height && i * Constants.CELL_SIZE <= y + height) { - renderer.rectLine(Math.max(0, x - width), i * Constants.CELL_SIZE, - Math.min(this.cols * Constants.CELL_SIZE, x + width), i * Constants.CELL_SIZE, Constants.MAP_GRID_LINE_WIDTH); - } - } - for (int i = 0; i < this.cols + 1; i++) { - if (i * Constants.CELL_SIZE >= x - width && i * Constants.CELL_SIZE <= x + width) { - renderer.rectLine(i * Constants.CELL_SIZE, Math.max(0, y - height), - i * Constants.CELL_SIZE, Math.min(this.rows * Constants.CELL_SIZE, y + height), Constants.MAP_GRID_LINE_WIDTH); - } - } - } - - public void renderPlayerLabelBg(Player[] players, ShapeRenderer renderer, BitmapFont font) { - for (Player player : players) { - player.color.a = .4f; - renderer.setColor(player.color); - roundedRect(renderer, - (player.position.x * Constants.CELL_SIZE) - Constants.CELL_SIZE, - (player.position.y * Constants.CELL_SIZE) + Constants.CELL_SIZE, - Constants.CELL_SIZE * 3f, - font.getLineHeight(), - font.getLineHeight() / 2); - player.color.a = 1.0f; - } + 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); } - public void drawPlayerLabels(Player[] players, Batch batch, BitmapFont font) { - float yOffset = (Constants.CELL_SIZE * 1.7f); // Not really sure how 1.7f fixes it lol - // TODO: Get it to work with all fonts as well and fix blurry text - // Also, make this and its bg work regardless of camera zoom value - // Furthermore, the grid's white walls block the batch's current blending func - for (Player player : players) { - font.setColor(player.color); - font.draw(batch, player.name, - (player.position.x * Constants.CELL_SIZE) - (3 * Constants.CELL_SIZE / 4), - (player.position.y * Constants.CELL_SIZE) + yOffset, - 0, player.name.length(), - Constants.CELL_SIZE * 3f - (Constants.CELL_SIZE / 2), Align.center, false, "..."); + public void renderPlayerLabels(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 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); + } + } } } - /** - * Draws a rectangle with rounded corners of the given radius. - */ - private void roundedRect(ShapeRenderer renderer, float x, float y, float width, float height, float radius) { - // Central rectangle - renderer.rect(x + radius, y + radius, width - 2 * radius, height - 2 * radius); - - // Four side rectangles, in clockwise order - renderer.rect(x + radius, y, width - 2 * radius, radius); - renderer.rect(x + width - radius, y + radius, radius, height - 2 * radius); - renderer.rect(x + radius, y + height - radius, width - 2 * radius, radius); - renderer.rect(x, y + radius, radius, height - 2 * radius); - - // Four arches, clockwise too - renderer.arc(x + radius, y + radius, radius, 180f, 90f); - renderer.arc(x + width - radius, y + radius, radius, 270f, 90f); - renderer.arc(x + width - radius, y + height - radius, radius, 0f, 90f); - renderer.arc(x + radius, y + height - radius, radius, 90f, 90f); - } - /** * Flood fill the unvisited cells * @@ -364,11 +502,11 @@ private Color fillColorHelper(int x, int y, Color fillColor, FloodFillGridState[ return fillColor; } - public boolean gameComplete(Player[] players) { - if (players.length == 2) { - for (Player player : players) { - // For two player games, end the game when a player has captured more than 50% of the cells - if (100 * (player.score / (((double) this.rows * this.cols) - this.wallCount)) > 50.0) { + 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) { return true; } } @@ -376,6 +514,21 @@ public boolean gameComplete(Player[] players) { return ((this.rows * this.cols) - this.wallCount) == this.coloredCells; } + public void dispose() { + if (playerLabelFbo != null) { + playerLabelFbo.dispose(); + playerLabelFbo = null; + } + if (playerFbo != null) { + playerFbo.dispose(); + playerFbo = null; + } + if (mapFbo != null) { + mapFbo.dispose(); + mapFbo = null; + } + } + /** * Compares only the rgb components of Colors, ignoring its alpha component * diff --git a/core/src/com/cg/zoned/MapSelector.java b/core/src/com/cg/zoned/MapSelector.java index e2ceb94..8a9e4c6 100644 --- a/core/src/com/cg/zoned/MapSelector.java +++ b/core/src/com/cg/zoned/MapSelector.java @@ -33,12 +33,14 @@ public class MapSelector { private FocusableStage stage; private Spinner mapSpinner; + private Assets assets; private Array usedTextures; - public MapSelector(FocusableStage stage, float scaleFactor, Skin skin) { + public MapSelector(FocusableStage stage, float scaleFactor, Assets assets, Skin skin) { this.mapManager = new MapManager(); this.stage = stage; this.skin = skin; + this.assets = assets; this.scaleFactor = scaleFactor; } @@ -80,10 +82,7 @@ private Stack getMapStack(final MapEntity map, Texture mapPreviewTexture) { innerTable.setFillParent(true); innerTable.top().right(); - Texture texture = new Texture(Gdx.files.internal("icons/ui_icons/ic_settings.png")); - if (usedTextures != null) { - usedTextures.add(texture); - } + Texture texture = assets.getSettingsButtonTexture(); HoverImageButton hoverImageButton = new HoverImageButton(new TextureRegionDrawable(texture)); hoverImageButton.getImage().setScaling(Scaling.fit); diff --git a/core/src/com/cg/zoned/Player.java b/core/src/com/cg/zoned/Player.java index 3069f8e..0590176 100644 --- a/core/src/com/cg/zoned/Player.java +++ b/core/src/com/cg/zoned/Player.java @@ -2,9 +2,10 @@ import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.cg.zoned.Constants.Direction; @@ -86,20 +87,12 @@ public void dummyMoveTo(Vector2 targetPosition, float delta) { // Simulate a fak } } - public void render(OrthographicCamera camera, ShapeRenderer renderer) { - float x = camera.position.x; - float y = camera.position.y; - float width = camera.viewportWidth * camera.zoom; - float height = camera.viewportHeight * camera.zoom; - - float startX = (this.position.x * Constants.CELL_SIZE) + (Constants.CELL_SIZE / 2); - float startY = (this.position.y * Constants.CELL_SIZE) + (Constants.CELL_SIZE / 2); - if ((startX >= x - width) && (startX + Constants.CELL_SIZE <= x + width) && - (startY >= y - height) && (startY + Constants.CELL_SIZE <= y + height)) { - renderer.setColor(Constants.PLAYER_CIRCLE_COLOR); - renderer.circle(startX, - startY, - Constants.CELL_SIZE / 3); + public void render(Rectangle userViewRect, Batch batch, TextureRegion playerTexture) { + 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); } } diff --git a/core/src/com/cg/zoned/ScoreBar.java b/core/src/com/cg/zoned/ScoreBar.java index 7fc53a9..8c8ae71 100644 --- a/core/src/com/cg/zoned/ScoreBar.java +++ b/core/src/com/cg/zoned/ScoreBar.java @@ -1,13 +1,10 @@ package com.cg.zoned; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.Viewport; public class ScoreBar { @@ -36,42 +33,43 @@ public void resize(int width, int height) { totalHeight = height; } - public void render(ShapeRenderer renderer, SpriteBatch batch, BitmapFont font, Player[] players, float delta) { + public void render(ShapeDrawer shapeDrawer, BitmapFont font, Array teamData, float delta) { float lerpVal = 3.0f; float currentWidthPos = 0; float offsetY = totalHeight - scoreBarHeight; float totalScore = 0; - for (Player player : players) { - totalScore += player.score; + for (TeamData td : teamData) { + totalScore += td.score; } if (totalScore == 0) { return; } - renderer.begin(ShapeRenderer.ShapeType.Filled); + float shadowHeight = Math.min(scoreBarHeight, 10f); + shapeDrawer.filledRectangle(0, totalHeight, totalWidth, -(shadowHeight + scoreBarHeight), + Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, Color.BLACK, Color.BLACK); - for (int i = 0; i < players.length; i++) { - float barWidth = ((players[i].score / totalScore) * totalWidth); + 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; - renderer.setColor(players[i].color); + shapeDrawer.setColor(teamData.get(i).color); if (i == 0) { // First bar - renderer.rect(currentWidthPos, offsetY, drawWidth, scoreBarHeight); + shapeDrawer.filledRectangle(currentWidthPos, offsetY, drawWidth, scoreBarHeight); scoreBarStartX[i] = currentWidthPos; - } else if (i == players.length - 1) { // Last bar - renderer.rect(totalWidth - drawWidth, offsetY, drawWidth, scoreBarHeight); // Can draw upto drawWidth or totalWidth. Should be the same + } 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) - //renderer.rect(currentWidthPos + (barWidth / 2) - (drawWidth / 2), offsetY, (drawWidth / 2), BAR_HEIGHT); - renderer.rect(currentWidthPos + (barWidth / 2), offsetY, -drawWidth / 2, scoreBarHeight); - renderer.rect(currentWidthPos + (barWidth / 2), offsetY, drawWidth / 2, scoreBarHeight); - //renderer.rect(currentWidthPos + (barWidth / 2) - (drawWidth / 2), offsetY, drawWidth, BAR_HEIGHT); + //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); //TODO: Need to polish this - //TODO: Scorebar for teams scoreBarStartX[i] = currentWidthPos; } scoreBarWidths[i] = drawWidth; @@ -80,24 +78,12 @@ public void render(ShapeRenderer renderer, SpriteBatch batch, BitmapFont font, P currentWidthPos += drawWidth; } - // TODO: Should we fix the line being annoyingly seen even when the scorebar has not been drawn yet? - float shadowHeight = Math.min(scoreBarHeight, 10f); - renderer.rect(0, offsetY - shadowHeight, totalWidth, shadowHeight, Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, Color.BLACK, Color.BLACK); - - renderer.end(); - - Gdx.gl.glDisable(GL20.GL_BLEND); - batch.begin(); for (int i = 0; i < scoreBarWidths.length; i++) { - font.setColor(getGoodTextColor(players[i].color)); - - font.draw(batch, String.valueOf(players[i].score), + 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), scoreBarWidths[i], Align.center, false); } - batch.end(); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } private Color getGoodTextColor(Color bgColor) { diff --git a/core/src/com/cg/zoned/ShapeDrawer.java b/core/src/com/cg/zoned/ShapeDrawer.java new file mode 100644 index 0000000..fbf9dae --- /dev/null +++ b/core/src/com/cg/zoned/ShapeDrawer.java @@ -0,0 +1,24 @@ +package com.cg.zoned; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.utils.Array; + +public class ShapeDrawer extends space.earlygrey.shapedrawer.ShapeDrawer { + public ShapeDrawer(Batch batch, Array usedTextures) { + super(batch, ShapeDrawer.get1x1TextureRegion(usedTextures)); + } + + public static TextureRegion get1x1TextureRegion(Array usedTextures) { + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.WHITE); + pixmap.drawPixel(0, 0); + Texture texture = new Texture(pixmap); + usedTextures.add(texture); + pixmap.dispose(); + return new TextureRegion(texture, 0, 0, 1, 1); + } +} diff --git a/core/src/com/cg/zoned/Zoned.java b/core/src/com/cg/zoned/Zoned.java index d1dd0b4..7aa83fd 100644 --- a/core/src/com/cg/zoned/Zoned.java +++ b/core/src/com/cg/zoned/Zoned.java @@ -6,16 +6,17 @@ import com.badlogic.gdx.Input; import com.badlogic.gdx.Preferences; import com.badlogic.gdx.assets.AssetManager; -import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.utils.GdxRuntimeException; +import com.cg.zoned.managers.DiscordRPCManager; import com.cg.zoned.screens.LoadingScreen; public class Zoned extends Game { public Skin skin; public Preferences preferences; - private AssetManager assetManager; + public Assets assets; + public DiscordRPCManager discordRPCManager; private static float SCALE_FACTOR = 1.0f; @@ -24,7 +25,9 @@ public void create() { Gdx.app.setLogLevel(Gdx.app.LOG_DEBUG); Gdx.input.setCatchKey(Input.Keys.BACK, true); + setUpDiscordRPC(); setScaleFactor(); + assets = new Assets(); this.setScreen(new LoadingScreen(this)); } @@ -55,24 +58,26 @@ public float getScaleFactor() { return SCALE_FACTOR; } - public Texture getPlayButtonTexture() { - // This is here because it's loaded by the assetManager - return assetManager.get("icons/ui_icons/ic_play_sheet.png", Texture.class); - } - @Override public void render() { super.render(); } public void setAssetManager(AssetManager assetManager) { - this.assetManager = assetManager; + assets.setAssetManager(assetManager); + } + + private void setUpDiscordRPC() { + discordRPCManager = new DiscordRPCManager(); + discordRPCManager.initRPC(); } @Override public void dispose() { + discordRPCManager.shutdownRPC(); + try { - assetManager.dispose(); + assets.dispose(); } catch (GdxRuntimeException ignored) { // "Pixmap already disposed!" error // idk why this happens but ok ¯\_(ツ)_/¯ diff --git a/core/src/com/cg/zoned/controls/PieMenuControlManager.java b/core/src/com/cg/zoned/controls/PieMenuControlManager.java index e0ee2d6..440863e 100644 --- a/core/src/com/cg/zoned/controls/PieMenuControlManager.java +++ b/core/src/com/cg/zoned/controls/PieMenuControlManager.java @@ -4,9 +4,7 @@ import com.badlogic.gdx.Input; import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; @@ -19,6 +17,7 @@ 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; @@ -33,6 +32,7 @@ public class PieMenuControlManager extends InputAdapter { 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; @@ -49,17 +49,10 @@ public PieMenuControlManager(Player[] players, boolean isSplitScreen, Stage stag } private void setUpPieMenus(Array usedTextures) { - Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); - pixmap.setColor(1, 1, 1, 1); - pixmap.fill(); - Texture tmpTex = new Texture(pixmap); - usedTextures.add(tmpTex); - pixmap.dispose(); - TextureRegion whitePixel = new TextureRegion(tmpTex); - Texture arrowTexture = new Texture(Gdx.files.internal("icons/control_icons/ic_arrow.png")); usedTextures.add(arrowTexture); final Drawable arrow = new TextureRegionDrawable(arrowTexture); + this.arrowImages = new Image[menus.length][]; for (int i = 0; i < menus.length; i++) { final PieMenu.PieMenuStyle style = new PieMenu.PieMenuStyle(); @@ -69,28 +62,28 @@ private void setUpPieMenus(Array usedTextures) { style.downColor = Color.WHITE; style.sliceColor = players[i].color; // Multiply by scaleFactor? Size kinda gets messed up when doing it - menus[i] = new PieMenu(whitePixel, style, piemenuRadius); + menus[i] = new PieMenu(ShapeDrawer.get1x1TextureRegion(usedTextures), style, piemenuRadius); - final Image[] arrowImages = new Image[]{ + arrowImages[i] = new Image[]{ new Image(arrow), new Image(arrow), new Image(arrow), new Image(arrow), }; - for (int j = 0; j < arrowImages.length; j++) { - arrowImages[j].setOrigin(arrowImages[j].getWidth() / 2, arrowImages[j].getHeight() / 2); - arrowImages[j].setScaling(Scaling.fit); - arrowImages[j].setColor(Color.WHITE); + for (int j = 0; j < arrowImages[i].length; j++) { + arrowImages[i][j].setOrigin(arrowImages[i][j].getWidth() / 2, arrowImages[i][j].getHeight() / 2); + arrowImages[i][j].setScaling(Scaling.fit); + arrowImages[i][j].setColor(Color.WHITE); if (j == 0) { - arrowImages[j].setRotation(-45f); + arrowImages[i][j].setRotation(-45f); } else if (j == 1) { - arrowImages[j].setRotation(45f); + arrowImages[i][j].setRotation(45f); } else if (j == 2) { - arrowImages[j].setRotation(135f); + arrowImages[i][j].setRotation(135f); } else if (j == 3) { - arrowImages[j].setRotation(-135f); + arrowImages[i][j].setRotation(-135f); } - menus[i].addActor(arrowImages[j]); + menus[i].addActor(arrowImages[i][j]); } menus[i].setRotation(45f); @@ -100,10 +93,8 @@ private void setUpPieMenus(Array usedTextures) { menus[i].addListener(new PieMenu.PieMenuCallbacks() { @Override public void onHighlightChange(int highlightedIndex) { - for (Image arrowImage : arrowImages) { - arrowImage.setColor(Color.WHITE); - } - arrowImages[highlightedIndex].setColor(Color.BLACK); + resetArrowColors(arrowImages[finalI]); + arrowImages[finalI][highlightedIndex].setColor(Color.BLACK); if (highlightedIndex == 0) { players[finalI].updatedDirection = Constants.Direction.UP; } else if (highlightedIndex == 1) { @@ -127,6 +118,12 @@ public void changed(ChangeListener.ChangeEvent event, Actor actor) { } } + private void resetArrowColors(Image[] arrowImages) { + for (Image arrowImage : arrowImages) { + arrowImage.setColor(Color.WHITE); + } + } + @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (button == Input.Buttons.LEFT) { @@ -145,7 +142,8 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { stage.addActor(menus[playerIndex]); menus[playerIndex].setPosition(screenX, stage.getHeight() - screenY, Align.center); menus[playerIndex].setVisible(true); - menus[playerIndex].setHighlightedIndex(-1); // Last arrow is still black; Not a bug but a feature lol ;-) + menus[playerIndex].setHighlightedIndex(-1); + resetArrowColors(arrowImages[playerIndex]); coords[playerIndex].x = screenX; coords[playerIndex].y = screenY; pointers[playerIndex] = pointer; diff --git a/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java b/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java index 3172f8d..b47e20c 100644 --- a/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java +++ b/core/src/com/cg/zoned/managers/ClientLobbyConnectionManager.java @@ -116,7 +116,11 @@ public void startGame() { private void emptyBuffers() { playerNames.clear(); - client.removeListener(clientLobbyListener); + try { + client.removeListener(clientLobbyListener); + } catch (IllegalArgumentException ignored) { + // Probably clicked the back button more than once; ignore exception + } clientLobbyListener = null; clientPlayerListener = null; } diff --git a/core/src/com/cg/zoned/managers/ControlManager.java b/core/src/com/cg/zoned/managers/ControlManager.java index fe3f46a..7c4ff1d 100644 --- a/core/src/com/cg/zoned/managers/ControlManager.java +++ b/core/src/com/cg/zoned/managers/ControlManager.java @@ -7,7 +7,6 @@ import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; @@ -18,6 +17,7 @@ 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.FlingControlManager; import com.cg.zoned.controls.PieMenuControlManager; @@ -110,14 +110,13 @@ public void setUpOverlay(boolean isSplitScreen, int controls, Skin skin, float s stage.addActor(masterTable); } - public void renderPlayerControlPrompt(ShapeRenderer renderer, float delta) { - renderer.begin(ShapeRenderer.ShapeType.Filled); + public void renderPlayerControlPrompt(ShapeDrawer shapeDrawer, float delta) { float splitScreenWidth = stage.getWidth() / overlayColors.length; for (int i = 0; i < overlayColors.length; i++) { if (overlayColors[i].a > 0) { - renderer.setColor(overlayColors[i]); - renderer.rect(i * splitScreenWidth, 0, splitScreenWidth, stage.getHeight()); + shapeDrawer.setColor(overlayColors[i]); + shapeDrawer.filledRectangle(i * splitScreenWidth, 0, splitScreenWidth, stage.getHeight()); } if (players[i].updatedDirection == null) { @@ -130,8 +129,6 @@ public void renderPlayerControlPrompt(ShapeRenderer renderer, float delta) { controlTables[i].getColor().a = overlayColors[i].a; } - - renderer.end(); } public InputAdapter getControls() { diff --git a/core/src/com/cg/zoned/managers/DiscordRPCManager.java b/core/src/com/cg/zoned/managers/DiscordRPCManager.java new file mode 100644 index 0000000..0cd7710 --- /dev/null +++ b/core/src/com/cg/zoned/managers/DiscordRPCManager.java @@ -0,0 +1,60 @@ +package com.cg.zoned.managers; + +import com.badlogic.gdx.Application; +import com.badlogic.gdx.Gdx; +import com.cg.zoned.Constants; + +import net.arikia.dev.drpc.DiscordRPC; +import net.arikia.dev.drpc.DiscordRichPresence; + +// Zoned Discord RPC runs only on Desktop (Windows and Linux) +public class DiscordRPCManager { + private final String applicationID = "726680223499812954"; + private DiscordRichPresence richPresence = null; + + public DiscordRPCManager() { + } + + public void initRPC() { + if (Gdx.app.getType() == Application.ApplicationType.Desktop && Constants.ENABLE_DISCORD_RPC) { + if (richPresence == null) { + DiscordRPC.discordInitialize(applicationID, null, false); + richPresence = new DiscordRichPresence.Builder("") + .setBigImage("zoned_logo", "v" + Constants.GAME_VERSION) + .setStartTimestamps(System.currentTimeMillis()) + .build(); + } else { + System.err.println("Ignoring RPC init request as the previous RPC hasn't been shutdown"); + } + } + } + + public void updateRPC(String state) { + if (richPresence != null) { + richPresence.details = null; + richPresence.smallImageKey = richPresence.smallImageText = null; + richPresence.state = state; + DiscordRPC.discordUpdatePresence(richPresence); + } + } + + public void updateRPC(String state, String mapName, int playerCount) { + if (richPresence != null) { + richPresence.details = state; + richPresence.state = "with " + playerCount + " other players"; + richPresence.smallImageText = mapName; + richPresence.smallImageKey = mapName.toLowerCase().replace(' ', '_') + "_map"; + if (richPresence.smallImageText.length() == 1) { // Weird bug with 1 letter text not triggering RPC update + richPresence.smallImageText = " " + richPresence.smallImageText + " "; + } + DiscordRPC.discordUpdatePresence(richPresence); + } + } + + public void shutdownRPC() { + if (richPresence != null) { + DiscordRPC.discordShutdown(); + richPresence = null; + } + } +} diff --git a/core/src/com/cg/zoned/managers/GameConnectionManager.java b/core/src/com/cg/zoned/managers/GameConnectionManager.java index a162957..fc05b51 100644 --- a/core/src/com/cg/zoned/managers/GameConnectionManager.java +++ b/core/src/com/cg/zoned/managers/GameConnectionManager.java @@ -27,7 +27,7 @@ public class GameConnectionManager implements IConnectionHandlers { private Array discardConnections; // Used to store client connections that came in when in-game private int ping; - private Boolean sentResponse; + private boolean sentResponse; // I've put a bunch of Gdx.app.postRunnables in order to properly sync multiple requests diff --git a/core/src/com/cg/zoned/managers/MapManager.java b/core/src/com/cg/zoned/managers/MapManager.java index a4713a3..db5951b 100644 --- a/core/src/com/cg/zoned/managers/MapManager.java +++ b/core/src/com/cg/zoned/managers/MapManager.java @@ -67,17 +67,24 @@ public void run() { public Texture getMapPreview(String mapName) { // Scan for the map preview in the internal directory try { - return new Texture(Gdx.files.internal("icons/map_icons/" + mapName + ".png")); + FileHandle fileHandle = Gdx.files.internal("icons/map_icons/" + mapName + ".png"); + if (fileHandle.exists()) { + return new Texture(fileHandle); + } } catch (GdxRuntimeException ignored) { } // Scan for the map preview in the external directory try { - return new Texture(Gdx.files.external(externalMapDir + "/" + mapName + ".png")); + FileHandle fileHandle = Gdx.files.external(externalMapDir + "/" + mapName + ".png"); + if (fileHandle.exists()) { + return new Texture(fileHandle); + } } catch (GdxRuntimeException | NullPointerException e) { Gdx.app.log(Constants.LOG_TAG, "Failed to load map preview image for '" + mapName + "' (" + e.getMessage() + ")"); - return null; } + + return null; } public Array getMapList() { diff --git a/core/src/com/cg/zoned/managers/PlayerManager.java b/core/src/com/cg/zoned/managers/PlayerManager.java index c100b2b..0f638e0 100644 --- a/core/src/com/cg/zoned/managers/PlayerManager.java +++ b/core/src/com/cg/zoned/managers/PlayerManager.java @@ -2,17 +2,14 @@ import com.badlogic.gdx.InputMultiplexer; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Sort; import com.cg.zoned.Constants.Direction; import com.cg.zoned.Player; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TeamData; -import java.util.Comparator; - public class PlayerManager extends InputMultiplexer { private final GameManager gameManager; @@ -26,9 +23,7 @@ public PlayerManager(GameManager gameManager, Player[] players, Stage stage, int this.gameManager = gameManager; this.players = players; - - this.teamData = new Array<>(); - initTeamColors(); + initTeamData(); if (gameManager.gameConnectionManager.isActive) { // Not split screen; only add first player's inputs this.addProcessor(players[0]); @@ -43,7 +38,9 @@ public PlayerManager(GameManager gameManager, Player[] players, Stage stage, int this.addProcessor(controlManager.getControls()); } - private void initTeamColors() { + private void initTeamData() { + this.teamData = new Array<>(); + for (Player player : players) { boolean alreadyExists = false; for (TeamData teamData : this.teamData) { @@ -107,18 +104,10 @@ public Player[] getPlayers() { } public Array getTeamData() { - new Sort().sort(teamData, new TeamDataComparator()); return teamData; } - public void renderPlayerControlPrompt(ShapeRenderer renderer, float delta) { - controlManager.renderPlayerControlPrompt(renderer, delta); - } - - private static class TeamDataComparator implements Comparator { - @Override - public int compare(TeamData t1, TeamData t2) { - return t2.score - t1.score; - } + public void renderPlayerControlPrompt(ShapeDrawer shapeDrawer, float delta) { + controlManager.renderPlayerControlPrompt(shapeDrawer, delta); } } diff --git a/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java b/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java index 904d0b7..6db54fd 100644 --- a/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java +++ b/core/src/com/cg/zoned/managers/ServerLobbyConnectionManager.java @@ -294,14 +294,17 @@ private int getConnectionIndex(Connection connection) { private void emptyBuffers() { playerConnections.clear(); - server.removeListener(serverLobbyListener); + try { + server.removeListener(serverLobbyListener); + } catch (IllegalArgumentException ignored) { + // Probably clicked the back button more than once; ignore exception + } serverLobbyListener = null; serverPlayerListener = null; } public void closeConnection() { emptyBuffers(); - server.close(); } diff --git a/core/src/com/cg/zoned/managers/UIButtonManager.java b/core/src/com/cg/zoned/managers/UIButtonManager.java index ca9a6ec..d54a23a 100644 --- a/core/src/com/cg/zoned/managers/UIButtonManager.java +++ b/core/src/com/cg/zoned/managers/UIButtonManager.java @@ -41,61 +41,69 @@ public UIButtonManager(Stage stage, float scaleFactor, Array usedTextur } } - public HoverImageButton addBackButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_LEFT, Gdx.files.internal("icons/ui_icons/ic_back.png"), null); + public HoverImageButton addBackButtonToStage(Texture backTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_LEFT, backTexture, null); } - public HoverImageButton addHideButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 90f, Position.TOP_LEFT, Gdx.files.internal("icons/ui_icons/ic_back.png"), null); + public HoverImageButton addHideButtonToStage(Texture backTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 90f, + Position.TOP_LEFT, backTexture, null); } - public HoverImageButton addSettingsButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_RIGHT, Gdx.files.internal("icons/ui_icons/ic_settings.png"), null); + public HoverImageButton addSettingsButtonToStage(Texture settingsTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_RIGHT, settingsTexture, null); } public HoverImageButton addPauseButtonToStage() { - return addButtonToStage(.8f, .65f, .5f, 20f, 0, Position.TOP_CENTER, Gdx.files.internal("icons/ui_icons/ic_pause.png"), null); + return addButtonToStage(.8f, .65f, .5f, 20f, 0, + Position.TOP_CENTER, getTexture(Gdx.files.internal("icons/ui_icons/ic_pause.png")), null); } public HoverImageButton addZoomButtonToStage() { - return addButtonToStage(.8f, .65f, .5f, 20f, 0, Position.TOP_CENTER, Gdx.files.internal("icons/ui_icons/ic_zoom_out.png"), Gdx.files.internal("icons/ui_icons/ic_zoom_in.png")); + return addButtonToStage(.8f, .65f, .5f, 20f, 0, + Position.TOP_CENTER, getTexture(Gdx.files.internal("icons/ui_icons/ic_zoom_out.png")), getTexture(Gdx.files.internal("icons/ui_icons/ic_zoom_in.png"))); } - public HoverImageButton addTutorialButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_RIGHT, Gdx.files.internal("icons/ui_icons/ic_tutorial.png"), null); + public HoverImageButton addTutorialButtonToStage(Texture tutorialTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_RIGHT, tutorialTexture, null); } - public HoverImageButton addDevButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_RIGHT, Gdx.files.internal("icons/ui_icons/ic_dev.png"), null); + public HoverImageButton addDevButtonToStage(Texture devTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_RIGHT, devTexture, null); } - public HoverImageButton addCreditsButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_RIGHT, Gdx.files.internal("icons/ui_icons/ic_credits.png"), null); + public HoverImageButton addCreditsButtonToStage(Texture creditsTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_RIGHT, creditsTexture, null); } - public HoverImageButton addExitButtonToStage() { - return addButtonToStage(1f, .65f, .5f, 24f, 0, Position.TOP_LEFT, Gdx.files.internal("icons/ui_icons/ic_cross.png"), null); + public HoverImageButton addExitButtonToStage(Texture crossTexture) { + return addButtonToStage(1f, .65f, .5f, 24f, 0, + Position.TOP_LEFT, crossTexture, null); + } + + private Texture getTexture(FileHandle fileHandle) { + Texture texture = new Texture(fileHandle); + usedTextures.add(texture); + return texture; } private HoverImageButton addButtonToStage(float normalAlpha, float hoverAlpha, float clickAlpha, float paddingTop, float rotateDegrees, Position position, - FileHandle buttonImageLocation1, - FileHandle buttonImageLocation2) { + Texture texture1, + Texture texture2) { Table table = buttonPositionTables.get(position.ordinal()); HoverImageButton button; - if (buttonImageLocation2 == null) { - Texture buttonImageTexture = new Texture(buttonImageLocation1); - usedTextures.add(buttonImageTexture); - button = new HoverImageButton(new TextureRegionDrawable(buttonImageTexture)); + if (texture2 == null) { + button = new HoverImageButton(new TextureRegionDrawable(texture1)); } else { - Texture buttonImageTexture1 = new Texture(buttonImageLocation1); - Texture buttonImageTexture2 = new Texture(buttonImageLocation2); - usedTextures.add(buttonImageTexture1); - usedTextures.add(buttonImageTexture2); - button = new HoverImageButton(new TextureRegionDrawable(buttonImageTexture1), - new TextureRegionDrawable(buttonImageTexture2)); + button = new HoverImageButton(new TextureRegionDrawable(texture1), new TextureRegionDrawable(texture2)); } float buttonWidth = 64f; diff --git a/core/src/com/cg/zoned/maps/internalmaps/HoloMap.java b/core/src/com/cg/zoned/maps/internalmaps/HoloMap.java index 298d67d..4683103 100644 --- a/core/src/com/cg/zoned/maps/internalmaps/HoloMap.java +++ b/core/src/com/cg/zoned/maps/internalmaps/HoloMap.java @@ -5,7 +5,7 @@ import com.cg.zoned.maps.MapExtraParams; public class HoloMap implements MapEntity { - private String mapGridString = "" + // Stupid auto-code formatter messes up the arrangement, so added this line + private String mapGridString = "" + // Added this line as the auto-code formatter messes up the arrangement "........A##C........\n" + "....#..........#....\n" + "....#..........#....\n" + diff --git a/core/src/com/cg/zoned/maps/internalmaps/RectangleMap.java b/core/src/com/cg/zoned/maps/internalmaps/RectangleMap.java index 1a48dec..f46bada 100644 --- a/core/src/com/cg/zoned/maps/internalmaps/RectangleMap.java +++ b/core/src/com/cg/zoned/maps/internalmaps/RectangleMap.java @@ -6,7 +6,7 @@ import com.cg.zoned.maps.MapExtraParams; public class RectangleMap implements MapEntity { - private String mapGridString = "" + // Stupid auto-code formatter messes up the arrangement, so added this line + private String mapGridString = "" + // Added this line as the auto-code formatter messes up the arrangement "A........C\n" + "..........\n" + "..........\n" + diff --git a/core/src/com/cg/zoned/maps/internalmaps/XMap.java b/core/src/com/cg/zoned/maps/internalmaps/XMap.java index c47e8d7..b21fad8 100644 --- a/core/src/com/cg/zoned/maps/internalmaps/XMap.java +++ b/core/src/com/cg/zoned/maps/internalmaps/XMap.java @@ -5,7 +5,7 @@ import com.cg.zoned.maps.MapExtraParams; public class XMap implements MapEntity { - private String mapGridString = "" + // Stupid auto-code formatter messes up the arrangement, so added this line + private String mapGridString = "" + // Added this line as the auto-code formatter messes up the arrangement "A.............C\n" + ".#...........#.\n" + "..#.........#..\n" + diff --git a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java index cad1200..ec5b6d7 100644 --- a/core/src/com/cg/zoned/screens/ClientLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ClientLobbyScreen.java @@ -10,7 +10,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.Actor; @@ -30,6 +30,7 @@ import com.cg.zoned.Constants; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -62,7 +63,9 @@ public class ClientLobbyScreen extends ScreenAdapter implements ClientLobbyConne private boolean showFPSCounter; private BitmapFont font; - private ShapeRenderer renderer; + private ShapeDrawer shapeDrawer; + private SpriteBatch batch; + private com.cg.zoned.Map map; private MapManager mapManager; private Cell[][] mapGrid; @@ -78,6 +81,7 @@ public class ClientLobbyScreen extends ScreenAdapter implements ClientLobbyConne public ClientLobbyScreen(final Zoned game, Client client, String name) { this.game = game; + game.discordRPCManager.updateRPC("In the Client lobby"); viewport = new ScreenViewport(); stage = new FocusableStage(viewport); @@ -120,12 +124,12 @@ private void setUpClientLobbyStage() { clientLobbyTable.row(); Table scrollTable = new Table(); - ScrollPane playerListScrollPane = new ScrollPane(scrollTable); + ScrollPane playerListScrollPane = new ScrollPane(scrollTable, game.skin); playerListScrollPane.setOverscroll(false, true); playerList = new Table(); scrollTable.add(playerList).expand(); - clientLobbyTable.add(playerListScrollPane).expand(); + clientLobbyTable.add(playerListScrollPane).grow(); clientLobbyTable.row(); mapLabel = new Label("", game.skin); @@ -162,7 +166,7 @@ public void clicked(InputEvent event, float x, float y) { }); clientLobbyTable.add(readyButton).width(200 * game.getScaleFactor()).pad(10 * game.getScaleFactor()); - stage.addFocusableActor(readyButton); + stage.addFocusableActor(readyButton, 2); stage.row(); stage.addActor(clientLobbyTable); @@ -171,8 +175,8 @@ public void clicked(InputEvent event, float x, float y) { private void setUpMap() { this.mapManager = new MapManager(); - this.renderer = new ShapeRenderer(); - this.renderer.setAutoShapeType(true); + this.batch = new SpriteBatch(); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); this.mapViewport = new ExtendViewport(Constants.WORLD_SIZE, Constants.WORLD_SIZE); this.mapDarkOverlayColor = new Color(0, 0, 0, .8f); this.players = new Player[0]; @@ -182,7 +186,7 @@ private void setUpMap() { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -346,7 +350,7 @@ public void mapChanged(String mapName, int[] mapExtraParams) { } this.mapGrid = mapManager.getPreparedMapGrid(); - this.map = new com.cg.zoned.Map(this.mapGrid, 0); + this.map = new com.cg.zoned.Map(this.mapGrid, 0, shapeDrawer); Array startPositions = mapManager.getPreparedStartPositions(); Array startPosNames = mapManager.getPreparedStartPosNames(); for (int j = 0; j < startPositions.size; j++) { @@ -571,17 +575,14 @@ public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); if (map != null) { - focusAndRenderViewport(mapViewport, players[0], delta); + renderMap(delta); } this.viewport.apply(true); - renderer.setProjectionMatrix(this.viewport.getCamera().combined); + batch.setProjectionMatrix(this.viewport.getCamera().combined); drawDarkOverlay(); - Gdx.gl.glDisable(GL20.GL_BLEND); if (showFPSCounter) { UITextDisplayer.displayFPS(viewport, stage.getBatch(), font); @@ -591,15 +592,17 @@ public void render(float delta) { stage.act(delta); } - private void focusAndRenderViewport(Viewport viewport, Player player, float delta) { + private void renderMap(float delta) { + Viewport viewport = mapViewport; + Player player = players[0]; + focusCameraOnPlayer(viewport, player, delta); viewport.apply(); - renderer.setProjectionMatrix(viewport.getCamera().combined); - - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.render(players, renderer, (OrthographicCamera) viewport.getCamera(), delta); - renderer.end(); + batch.setProjectionMatrix(viewport.getCamera().combined); + batch.begin(); + map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + batch.end(); } private void focusCameraOnPlayer(Viewport viewport, Player player, float delta) { @@ -633,19 +636,20 @@ private void updateCamera(Camera camera, int width, int height) { private void drawDarkOverlay() { float height = stage.getViewport().getWorldHeight(); float width = stage.getViewport().getWorldWidth(); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(mapDarkOverlayColor); - renderer.rect(0, 0, width, height); - renderer.end(); + shapeDrawer.setColor(mapDarkOverlayColor); + batch.begin(); + shapeDrawer.filledRectangle(0, 0, width, height); + batch.end(); } @Override public void dispose() { stage.dispose(); - renderer.dispose(); + batch.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } + map.dispose(); } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/CreditsScreen.java b/core/src/com/cg/zoned/screens/CreditsScreen.java index 84eba3f..6593b65 100644 --- a/core/src/com/cg/zoned/screens/CreditsScreen.java +++ b/core/src/com/cg/zoned/screens/CreditsScreen.java @@ -9,6 +9,7 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.ParticleEffect; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Touchable; @@ -30,6 +31,7 @@ import com.cg.zoned.managers.UIButtonManager; import com.cg.zoned.ui.FocusableStage; import com.cg.zoned.ui.HoverImageButton; +import com.cg.zoned.ui.ParticleEffectActor; public class CreditsScreen extends ScreenAdapter implements InputProcessor { final Zoned game; @@ -43,9 +45,11 @@ public class CreditsScreen extends ScreenAdapter implements InputProcessor { private BitmapFont font; private Color linkColor = new Color(.4f, .4f, 1f, 1f); + private ParticleEffect clickParticleEffect = null; public CreditsScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Viewing credits"); this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); @@ -103,12 +107,7 @@ private void setUpStage() { addCreditItem(table, "Feedback", Gdx.files.internal("icons/ic_gmail.png"), "cg.devworks@gmail.com", - "mailto:cg.devworks@gmail.com"); - - addCreditItem(table, - "Hang out with me", - Gdx.files.internal("icons/ic_discord.png"), "Discord", - "https://discord.gg/MFBkvqw"); + "mailto:cg.devworks@gmail.com?subject=Zoned+Feedback"); addCreditItem(table, "Thank You", "for playing"); @@ -124,6 +123,10 @@ private void addCreditItem(Table table, FileHandle imageLocation, String title, Texture gameLogo = new Texture(imageLocation); usedTextures.add(gameLogo); + clickParticleEffect = new ParticleEffect(); + clickParticleEffect.load(Gdx.files.internal("particles/radial_particle_emitter.p"), Gdx.files.internal("particles")); + final ParticleEffectActor particleEffectActor = new ParticleEffectActor(clickParticleEffect); + final Image gameLogoImage = new Image(gameLogo); gameLogoImage.setScaling(Scaling.fit); gameLogoImage.getColor().a = .3f; @@ -132,6 +135,7 @@ private void addCreditItem(Table table, FileHandle imageLocation, String title, titleLabel.setAlignment(Align.center); Stack stack = new Stack(); + stack.add(particleEffectActor); stack.add(gameLogoImage); stack.add(titleLabel); @@ -151,6 +155,8 @@ public void clicked(InputEvent event, float x, float y) { innerTable.setScale(1.2f); innerTable.addAction(Actions.scaleTo(1.0f, 1.0f, .3f, Interpolation.smooth)); + particleEffectActor.start(); + clickCount[0]++; if (clickCount[0] >= 5) { toggleDevMode(); @@ -231,20 +237,28 @@ private void addCreditItem(Table table, String title, final String content) { titleLabel.setAlignment(Align.center); contentLabel.setAlignment(Align.center); - float lastItemExtraPaddingOffset = - ((title.contains("Thank You")) ? (5 / 2f) : (1)); - float lastPadding = ((lastItemExtraPaddingOffset == 1) ? (0) : (titleLabel.getPrefHeight() - (titleLabel.getPrefHeight() / 10))); - // "/ 10" so that the tail of the Discord logo above is not visible - - table.add(titleLabel).growX() - .padTop(stage.getHeight() / 5) - .padLeft(10f) - .padRight(10f); - table.row(); - table.add(contentLabel).growX() - .padBottom((lastItemExtraPaddingOffset * stage.getHeight() / 5) - lastPadding) - .padLeft(10f) - .padRight(10f); + if (title.contains("Thank You")) { // Last item in the credits screen + table.add(titleLabel).growX() + .padTop(stage.getHeight() / 2) + .padLeft(10f) + .padRight(10f); + table.row(); + table.add(contentLabel).growX() + .padBottom((stage.getHeight() / 2) - titleLabel.getHeight()) + .padLeft(10f) + .padRight(10f); + // Hacky line above, but this whole thing is kinda hacky and doesn't work on resize anyway + } else { + table.add(titleLabel).growX() + .padTop(stage.getHeight() / 5) + .padLeft(10f) + .padRight(10f); + table.row(); + table.add(contentLabel).growX() + .padBottom(stage.getHeight() / 5) + .padLeft(10f) + .padRight(10f); + } table.row(); } @@ -265,7 +279,7 @@ private void toggleDevMode() { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -300,6 +314,10 @@ public void dispose() { for (Texture texture : usedTextures) { texture.dispose(); } + if (clickParticleEffect != null) { + clickParticleEffect.dispose(); + clickParticleEffect = null; + } } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/DevScreen.java b/core/src/com/cg/zoned/screens/DevScreen.java index 804afbc..8b41985 100644 --- a/core/src/com/cg/zoned/screens/DevScreen.java +++ b/core/src/com/cg/zoned/screens/DevScreen.java @@ -41,6 +41,7 @@ public class DevScreen extends ScreenAdapter implements InputProcessor { public DevScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Exploring secrets"); this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); @@ -97,11 +98,19 @@ private void setUpStage() { innerTable.add(splitscreenPlayerCountSpinner); innerTable.row(); + stage.addFocusableActor(splitscreenPlayerCountSpinner.getLeftButton()); + stage.addFocusableActor(splitscreenPlayerCountSpinner.getRightButton()); + stage.row(); + innerTable.add(mapStartPosSplitscreenCountLabel).padTop(20f); innerTable.row(); innerTable.add(mapStartPosSplitscreenCountSpinner); - table.add(screenScrollPane).expand(); + stage.addFocusableActor(mapStartPosSplitscreenCountSpinner.getLeftButton()); + stage.addFocusableActor(mapStartPosSplitscreenCountSpinner.getRightButton()); + stage.row(); + + table.add(screenScrollPane).grow(); stage.addActor(table); stage.setScrollFocus(screenScrollPane); @@ -109,7 +118,7 @@ private void setUpStage() { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { diff --git a/core/src/com/cg/zoned/screens/GameScreen.java b/core/src/com/cg/zoned/screens/GameScreen.java index 26bf9eb..ea6f923 100644 --- a/core/src/com/cg/zoned/screens/GameScreen.java +++ b/core/src/com/cg/zoned/screens/GameScreen.java @@ -12,7 +12,6 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; @@ -24,6 +23,7 @@ import com.cg.zoned.Map; import com.cg.zoned.Player; import com.cg.zoned.ScoreBar; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TeamData; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -48,7 +48,8 @@ public class GameScreen extends ScreenAdapter implements InputProcessor { private Map map; private ExtendViewport[] playerViewports; // Two viewports in split-screen mode; else one - private ShapeRenderer renderer; + + private ShapeDrawer shapeDrawer; private SpriteBatch batch; private Color[] dividerLeftColor, dividerRightColor; @@ -60,7 +61,6 @@ public class GameScreen extends ScreenAdapter implements InputProcessor { private boolean showFPSCounter; private ScoreBar scoreBars; private boolean gamePaused = false; - private BitmapFont playerLabelFont; private Color currentBgColor, targetBgColor; private float bgAnimSpeed = 1.8f; @@ -82,6 +82,7 @@ public GameScreen(final Zoned game, MapManager mapManager, Player[] players, Cli private GameScreen(final Zoned game, MapManager mapManager, Player[] players, Server server, Client client) { this.game = game; + game.discordRPCManager.updateRPC("Playing a match", mapManager.getPreparedMap().getName(), players.length - 1); this.fullScreenStage = new FocusableStage(new ScreenViewport()); @@ -91,18 +92,19 @@ private GameScreen(final Zoned game, MapManager mapManager, Player[] players, Se game.preferences.getInteger(Constants.CONTROL_PREFERENCE, Constants.PIE_MENU_CONTROL), game.skin, game.getScaleFactor(), usedTextures); - this.renderer = new ShapeRenderer(); - this.renderer.setAutoShapeType(true); this.batch = new SpriteBatch(); - this.map = new Map(mapManager.getPreparedMapGrid(), mapManager.getWallCount()); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); + this.map = new Map(mapManager.getPreparedMapGrid(), mapManager.getWallCount(), this.shapeDrawer); currentBgColor = new Color(0, 0, 0, bgAlpha); targetBgColor = new Color(0, 0, 0, bgAlpha); - this.playerLabelFont = game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getName()); + BitmapFont playerLabelFont = game.skin.getFont(Constants.FONT_MANAGER.PLAYER_LABEL.getName()); initViewports(players); - this.scoreBars = new ScoreBar(fullScreenStage.getViewport(), players.length, game.getScaleFactor()); + map.createPlayerLabelTextures(players, shapeDrawer, playerLabelFont); + + this.scoreBars = new ScoreBar(fullScreenStage.getViewport(), this.gameManager.playerManager.getTeamData().size, game.getScaleFactor()); } private void initViewports(Player[] players) { @@ -215,45 +217,42 @@ public void render(float delta) { map.update(gameManager.playerManager, delta); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); - - renderer.setProjectionMatrix(fullScreenStage.getViewport().getCamera().combined); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(currentBgColor); - renderer.rect(0, 0, fullScreenStage.getWidth(), fullScreenStage.getHeight()); - renderer.end(); + batch.setProjectionMatrix(fullScreenStage.getCamera().combined); + batch.begin(); + shapeDrawer.setColor(currentBgColor); + shapeDrawer.filledRectangle(0, 0, fullScreenStage.getWidth(), fullScreenStage.getHeight()); + batch.end(); for (int i = 0; i < this.playerViewports.length; i++) { - focusAndRenderViewport(playerViewports[i], gameManager.playerManager.getPlayer(i), delta); + // Render everything in the i-th player viewport + renderMap(i, delta); } fullScreenStage.getViewport().apply(true); - renderer.setProjectionMatrix(fullScreenStage.getCamera().combined); batch.setProjectionMatrix(fullScreenStage.getCamera().combined); + batch.begin(); - if (isSplitscreenMultiplayer()) { // Draw the viewport divider only when playing on the same device + if (isSplitscreenMultiplayer() && playerViewports.length >= 2) { + // Draw the viewport divider only when playing on the same device with at least 2 splitscreens drawViewportDividers(); } if (!gameManager.gameOver) { - gameManager.playerManager.renderPlayerControlPrompt(renderer, delta); + gameManager.playerManager.renderPlayerControlPrompt(shapeDrawer, delta); } - scoreBars.render(renderer, batch, font, gameManager.playerManager.getPlayers(), delta); + scoreBars.render(shapeDrawer, font, gameManager.playerManager.getTeamData(), delta); - if (!gameManager.gameOver && map.gameComplete(gameManager.playerManager.getPlayers())) { + if (!gameManager.gameOver && map.gameComplete(gameManager.playerManager.getTeamData())) { gameManager.directionBufferManager.clearBuffer(); gameManager.playerManager.stopPlayers(true); gameManager.gameOver = true; } - + batch.end(); if (gameManager.gameOver) { fadeOutScreen(delta); } - Gdx.gl.glDisable(GL20.GL_BLEND); - if (showFPSCounter) { UITextDisplayer.displayFPS(fullScreenStage.getViewport(), fullScreenStage.getBatch(), font, UITextDisplayer.padding, scoreBars.scoreBarHeight + UITextDisplayer.padding); } @@ -273,10 +272,10 @@ private void fadeOutScreen(float delta) { fadeOutOverlay.a += delta * 2f * (2f - fadeOutOverlay.a); fadeOutOverlay.a = Math.min(fadeOutOverlay.a, 1f); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(fadeOutOverlay); - renderer.rect(0, 0, fullScreenStage.getWidth(), fullScreenStage.getHeight()); - renderer.end(); + batch.begin(); + shapeDrawer.setColor(fadeOutOverlay); + shapeDrawer.filledRectangle(0, 0, fullScreenStage.getWidth(), fullScreenStage.getHeight()); + batch.end(); if (fadeOutOverlay.a >= 1f && !gameCompleteFadeOutDone) { gameCompleteFadeOutDone = true; @@ -287,7 +286,6 @@ private void fadeOutScreen(float delta) { Gdx.app.postRunnable(new Runnable() { // Hopefully fixes the occasional SIGSEGVs around 1 second after transitioning to VictoryScreen @Override public void run() { - Gdx.gl.glDisable(GL20.GL_BLEND); dispose(); game.setScreen(new VictoryScreen(game, gameManager.playerManager, map.rows, map.cols, map.wallCount)); } @@ -296,46 +294,36 @@ public void run() { } private void drawViewportDividers() { - renderer.begin(ShapeRenderer.ShapeType.Filled); int lineCount = gameManager.playerManager.getPlayers().length - 1; float height = fullScreenStage.getViewport().getWorldHeight(); + float dividerFadeWidth = Math.max(Constants.VIEWPORT_DIVIDER_FADE_WIDTH / (playerViewports.length - 1), 3f); + float dividerSolidWidth = Math.max(Constants.VIEWPORT_DIVIDER_SOLID_WIDTH / (playerViewports.length - 1), 1f); for (int i = 0; i < lineCount; i++) { float startX = (fullScreenStage.getViewport().getWorldWidth() / (float) (lineCount + 1)) * (i + 1); - renderer.rect(startX - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH * 2, height, - dividerLeftColor[i], dividerRightColor[i], dividerRightColor[i], dividerLeftColor[i]); - renderer.rect(startX + Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - Constants.VIEWPORT_DIVIDER_FADE_WIDTH, height, - dividerRightColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerRightColor[i]); - renderer.rect(startX - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - -Constants.VIEWPORT_DIVIDER_FADE_WIDTH, height, - dividerLeftColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerLeftColor[i]); + shapeDrawer.filledRectangle(startX - dividerSolidWidth, 0, + dividerSolidWidth * 2, height, + dividerRightColor[i], dividerLeftColor[i], dividerLeftColor[i], dividerRightColor[i]); + shapeDrawer.filledRectangle(startX + dividerSolidWidth, 0, + dividerFadeWidth, height, + Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerRightColor[i], dividerRightColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR); + shapeDrawer.filledRectangle(startX - dividerSolidWidth, 0, + -dividerFadeWidth, height, + Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerLeftColor[i], dividerLeftColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR); } - renderer.end(); } - private void focusAndRenderViewport(Viewport viewport, Player player, float delta) { - focusCameraOnPlayer(viewport, player, delta); + private void renderMap(int index, float delta) { + Viewport viewport = playerViewports[index]; + Player[] players = gameManager.playerManager.getPlayers(); + + focusCameraOnPlayer(viewport, players[index], delta); viewport.apply(); - renderer.setProjectionMatrix(viewport.getCamera().combined); batch.setProjectionMatrix(viewport.getCamera().combined); - - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.render(gameManager.playerManager.getPlayers(), renderer, (OrthographicCamera) viewport.getCamera(), delta); - map.renderPlayerLabelBg(gameManager.playerManager.getPlayers(), renderer, playerLabelFont); - renderer.end(); - - Gdx.gl.glDisable(GL20.GL_BLEND); - - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); batch.begin(); - map.drawPlayerLabels(gameManager.playerManager.getPlayers(), batch, playerLabelFont); + map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); batch.end(); - - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } private void focusCameraOnPlayer(Viewport viewport, Player player, float delta) { @@ -463,11 +451,11 @@ public void pause() { @Override public void dispose() { fullScreenStage.dispose(); - renderer.dispose(); batch.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } + map.dispose(); } @Override diff --git a/core/src/com/cg/zoned/screens/HostJoinScreen.java b/core/src/com/cg/zoned/screens/HostJoinScreen.java index b8664a8..d747c64 100644 --- a/core/src/com/cg/zoned/screens/HostJoinScreen.java +++ b/core/src/com/cg/zoned/screens/HostJoinScreen.java @@ -52,6 +52,7 @@ public class HostJoinScreen extends ScreenAdapter implements InputProcessor { public HostJoinScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Setting up local multiplayer"); this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); @@ -168,7 +169,7 @@ public void clicked(InputEvent event, float x, float y) { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { diff --git a/core/src/com/cg/zoned/screens/LoadingScreen.java b/core/src/com/cg/zoned/screens/LoadingScreen.java index b114585..b281453 100644 --- a/core/src/com/cg/zoned/screens/LoadingScreen.java +++ b/core/src/com/cg/zoned/screens/LoadingScreen.java @@ -44,6 +44,7 @@ public class LoadingScreen extends ScreenAdapter { public LoadingScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Loading game"); } @Override @@ -114,14 +115,21 @@ public void render(float delta) { finishedLoading = true; if (!loadedFonts) { - ObjectMap fontMap = new ObjectMap(); + ObjectMap fontMap = new ObjectMap<>(); for (Constants.FONT_MANAGER font : Constants.FONT_MANAGER.values()) { fontMap.put(font.getName(), assetManager.get(font.getName() + ".otf", BitmapFont.class)); } SkinLoader.SkinParameter parameter = new SkinLoader.SkinParameter("neon-skin/neon-ui.atlas", fontMap); assetManager.load("neon-skin/neon-ui.json", Skin.class, parameter); - assetManager.load("icons/ui_icons/ic_play_sheet.png", Texture.class); // Big image; noticeable lag on my mobile. So load via assetManager + + assetManager.load("icons/ui_icons/ic_play_sheet.png", Texture.class); // Big image, loading directly will lag on less powerful hardware + assetManager.load("icons/ui_icons/ic_back.png", Texture.class); + assetManager.load("icons/ui_icons/ic_credits.png", Texture.class); + assetManager.load("icons/ui_icons/ic_cross.png", Texture.class); + assetManager.load("icons/ui_icons/ic_dev.png", Texture.class); + assetManager.load("icons/ui_icons/ic_settings.png", Texture.class); + assetManager.load("icons/ui_icons/ic_tutorial.png", Texture.class); loadedFonts = true; finishedLoading = false; diff --git a/core/src/com/cg/zoned/screens/MainMenuScreen.java b/core/src/com/cg/zoned/screens/MainMenuScreen.java index 8b7871f..1e4e41d 100644 --- a/core/src/com/cg/zoned/screens/MainMenuScreen.java +++ b/core/src/com/cg/zoned/screens/MainMenuScreen.java @@ -56,6 +56,7 @@ public class MainMenuScreen extends ScreenAdapter implements InputProcessor { public MainMenuScreen(final Zoned game) { this.game = game; + this.game.discordRPCManager.updateRPC("Main Menu"); viewport = new ScreenViewport(); mainStage = new FocusableStage(viewport); @@ -115,11 +116,11 @@ private void setUpMainMenu() { mainStage.row(); UIButtonManager uiButtonManager = new UIButtonManager(mainStage, game.getScaleFactor(), usedTextures); - HoverImageButton settingsButton = uiButtonManager.addSettingsButtonToStage(); - HoverImageButton creditsButton = uiButtonManager.addCreditsButtonToStage(); + 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)) { - devButton = uiButtonManager.addDevButtonToStage(); + devButton = uiButtonManager.addDevButtonToStage(game.assets.getDevButtonTexture()); devButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -150,7 +151,7 @@ public void clicked(InputEvent event, float x, float y) { mainStage.addFocusableActor(creditsButton); mainStage.addFocusableActor(devButton); - HoverImageButton exitButton = uiButtonManager.addExitButtonToStage(); + HoverImageButton exitButton = uiButtonManager.addExitButtonToStage(game.assets.getCrossButtonTexture()); exitButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -172,7 +173,7 @@ public void clicked(InputEvent event, float x, float y) { } private HoverImageButton setUpAnimatedPlayButton(Table mainTable) { - Texture playSheet = game.getPlayButtonTexture(); // Loaded via the assetManager since it causes a noticeable lag on my phone otherwise + Texture playSheet = game.assets.getPlayButtonTexture(); // Loaded via the assetManager since it causes a noticeable lag on my phone otherwise //usedTextures.add(playSheet); Texture is loaded via the assetManager so that will take care of its disposal int rowCount = 6, colCount = 5; @@ -239,7 +240,7 @@ private void setUpPlayMenu() { }; String[] modeLabelStrings = new String[]{ "Splitscreen\nMultiplayer", - "Local\nMultiplayer\n(WiFi)", + "Local\nNetwork\nMultiplayer", }; final Class[] screenClasses = new Class[]{ PlayerSetUpScreen.class, @@ -325,7 +326,7 @@ public void clicked(InputEvent event, float x, float y) { } UIButtonManager uiButtonManager = new UIButtonManager(playModeStage, game.getScaleFactor(), usedTextures); - HoverImageButton exitButton = uiButtonManager.addHideButtonToStage(); + HoverImageButton exitButton = uiButtonManager.addHideButtonToStage(game.assets.getBackButtonTexture()); exitButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { diff --git a/core/src/com/cg/zoned/screens/MapStartPosScreen.java b/core/src/com/cg/zoned/screens/MapStartPosScreen.java index 77eab05..bd6ef78 100644 --- a/core/src/com/cg/zoned/screens/MapStartPosScreen.java +++ b/core/src/com/cg/zoned/screens/MapStartPosScreen.java @@ -11,13 +11,12 @@ import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Button; -import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; import com.badlogic.gdx.scenes.scene2d.ui.Table; @@ -33,12 +32,14 @@ import com.cg.zoned.GameTouchPoint; import com.cg.zoned.Map; import com.cg.zoned.Player; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; import com.cg.zoned.managers.MapManager; import com.cg.zoned.managers.UIButtonManager; -import com.cg.zoned.ui.CustomButtonGroup; +import com.cg.zoned.ui.ButtonGroup; +import com.cg.zoned.ui.CheckBox; import com.cg.zoned.ui.FocusableStage; import com.cg.zoned.ui.HoverImageButton; @@ -54,7 +55,8 @@ public class MapStartPosScreen extends ScreenAdapter implements InputProcessor { private AnimationManager animationManager; private ScreenViewport viewport; private FocusableStage stage; - private ShapeRenderer renderer; + private ShapeDrawer shapeDrawer; + private SpriteBatch batch; private BitmapFont font; private boolean showFPSCounter; @@ -69,13 +71,14 @@ public class MapStartPosScreen extends ScreenAdapter implements InputProcessor { private boolean firstPlayerOnly; private Player[] players; private CheckBox[][] radioButtons; - private CustomButtonGroup[] customButtonGroup; + private ButtonGroup[] buttonGroup; private Label[] playerLabels; private int playerIndex; public MapStartPosScreen(final Zoned game, MapManager mapManager, Player[] players, int splitScreenCount, boolean firstPlayerOnly) { this.game = game; + game.discordRPCManager.updateRPC("Choosing start positions"); this.mapManager = mapManager; this.mapGrid = mapManager.getPreparedMapGrid(); @@ -93,8 +96,8 @@ public MapStartPosScreen(final Zoned game, MapManager mapManager, this.stage = new FocusableStage(this.viewport); this.animationManager = new AnimationManager(this.game, this); - this.renderer = new ShapeRenderer(); - this.renderer.setAutoShapeType(true); + this.batch = new SpriteBatch(); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); this.font = game.skin.getFont(Constants.FONT_MANAGER.SMALL.getName()); } @@ -109,7 +112,7 @@ public void show() { } private void setUpMap() { - map = new Map(mapGrid, 0); // Wall count is unnecessary in this case so 0 + map = new Map(mapGrid, 0, shapeDrawer); // Wall count is unnecessary in this case so 0 mapDarkOverlayColor = new Color(0, 0, 0, 0.8f); mapViewports = new ExtendViewport[splitScreenCount]; for (int i = 0; i < players.length; i++) { @@ -157,9 +160,10 @@ private void setUpStage() { playerLabels = new Label[splitScreenCount]; radioButtons = new CheckBox[splitScreenCount][]; - customButtonGroup = new CustomButtonGroup[splitScreenCount]; + buttonGroup = new ButtonGroup[splitScreenCount]; for (int i = 0; i < splitScreenCount; i++) { Table table = new Table(); + ScrollPane startPosScrollPane = null; final boolean alignLeft = (i < (splitScreenCount / 2)); if (i < players.length) { @@ -175,13 +179,13 @@ private void setUpStage() { table.row(); Table scrollTable = new Table(); - ScrollPane startPosScrollPane = new ScrollPane(scrollTable); + startPosScrollPane = new ScrollPane(scrollTable); startPosScrollPane.setOverscroll(false, true); radioButtons[i] = new CheckBox[startPositions.size]; - customButtonGroup[i] = new CustomButtonGroup(); - customButtonGroup[i].setMinCheckCount(1); - customButtonGroup[i].setMaxCheckCount(1); + buttonGroup[i] = new ButtonGroup(); + buttonGroup[i].setMinCheckCount(1); + buttonGroup[i].setMaxCheckCount(1); for (int j = 0; j < startPositions.size; j++) { String startPosName; try { @@ -191,7 +195,7 @@ private void setUpStage() { } startPosName += (" (" + (mapGrid.length - startPositions.get(j).y - 1) + ", " + (startPositions.get(j).x) + ")"); - radioButtons[i][j] = new CheckBox(startPosName, game.skin, "radio"); + radioButtons[i][j] = new CheckBox(startPosName, game.skin, "radio", !alignLeft); radioButtons[i][j].getImageCell().width(radioButtons[i][j].getLabel().getPrefHeight()).height(radioButtons[i][j].getLabel().getPrefHeight()); radioButtons[i][j].getImage().setScaling(Scaling.fill); if (alignLeft) { @@ -201,20 +205,20 @@ private void setUpStage() { } scrollTable.row(); - customButtonGroup[i].add(radioButtons[i][j]); + buttonGroup[i].add(radioButtons[i][j]); if (j == i % startPositions.size) { radioButtons[i][j].setChecked(true); } } - table.add(startPosScrollPane); + table.add(startPosScrollPane).grow(); final int finalI = i; - customButtonGroup[i].setOnCheckChangeListener(new CustomButtonGroup.OnCheckChangeListener() { + buttonGroup[i].setOnCheckChangeListener(new ButtonGroup.OnCheckChangeListener() { @Override public void buttonPressed(Button button) { - int startPosIndex = customButtonGroup[finalI].getCheckedIndex(); + int startPosIndex = buttonGroup[finalI].getCheckedIndex(); int index = finalI + playerIndex; if (index >= players.length) { @@ -241,9 +245,17 @@ public void buttonPressed(Button button) { } if (alignLeft) { - masterTable.add(table).expand().uniformX().left().padLeft(20f * game.getScaleFactor()); + masterTable.add(table).expand().uniformX().left() + .padLeft(20f * game.getScaleFactor()).padRight(10f * game.getScaleFactor()); } else { - masterTable.add(table).expand().uniformX().right().padRight(20f * game.getScaleFactor()); + masterTable.add(table).expand().uniformX().right() + .padRight(20f * game.getScaleFactor()).padLeft(10f * game.getScaleFactor()); + + if (startPosScrollPane != null) { + startPosScrollPane.layout(); + startPosScrollPane.setScrollPercentX(1f); // I think this doesn't have width info by now which is why it's kinda buggy? + startPosScrollPane.updateVisualScroll(); + } } } masterTable.row(); @@ -305,7 +317,7 @@ public void touchUp(InputEvent event, float x, float y, int pointer, int button) public void clicked(InputEvent event, float x, float y) { for (int i = 0; i < splitScreenCount; i++) { if (i + playerIndex < players.length) { - players[i + playerIndex].setStartPos(startPositions.get(customButtonGroup[i].getCheckedIndex())); + players[i + playerIndex].setStartPos(startPositions.get(buttonGroup[i].getCheckedIndex())); if (firstPlayerOnly) { break; } @@ -378,7 +390,7 @@ public void clicked(InputEvent event, float x, float y) { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -391,11 +403,11 @@ private void focusAndRenderViewport(Viewport viewport, Player player, Vector2 ve focusCameraOnPlayer(viewport, player, vel, delta); viewport.apply(); - renderer.setProjectionMatrix(viewport.getCamera().combined); + batch.setProjectionMatrix(viewport.getCamera().combined); - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.render(players, renderer, (OrthographicCamera) viewport.getCamera(), delta); - renderer.end(); + batch.begin(); + map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + batch.end(); } private void focusCameraOnPlayer(Viewport viewport, Player player, Vector2 vel, float delta) { @@ -432,33 +444,34 @@ private void updateCamera(Camera camera, int width, int height) { } private void drawViewportDividers() { - renderer.begin(ShapeRenderer.ShapeType.Filled); + batch.begin(); int lineCount = splitScreenCount - 1; - + float dividerFadeWidth = Math.max(Constants.VIEWPORT_DIVIDER_FADE_WIDTH / (mapViewports.length - 1), 3f); + float dividerSolidWidth = Math.max(Constants.VIEWPORT_DIVIDER_SOLID_WIDTH / (mapViewports.length - 1), 1f); float height = stage.getViewport().getWorldHeight(); for (int i = 0; i < lineCount; i++) { float startX = (stage.getViewport().getWorldWidth() / (float) (lineCount + 1)) * (i + 1); - renderer.rect(startX - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH * 2, height, - dividerLeftColor[i], dividerRightColor[i], dividerRightColor[i], dividerLeftColor[i]); - renderer.rect(startX + Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - Constants.VIEWPORT_DIVIDER_FADE_WIDTH, height, - dividerRightColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerRightColor[i]); - renderer.rect(startX - Constants.VIEWPORT_DIVIDER_SOLID_WIDTH, 0, - -Constants.VIEWPORT_DIVIDER_FADE_WIDTH, height, - dividerLeftColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerLeftColor[i]); + shapeDrawer.filledRectangle(startX - dividerSolidWidth, 0, + dividerSolidWidth * 2, height, + dividerRightColor[i], dividerLeftColor[i], dividerLeftColor[i], dividerRightColor[i]); + shapeDrawer.filledRectangle(startX + dividerSolidWidth, 0, + dividerFadeWidth, height, + Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerRightColor[i], dividerRightColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR); + shapeDrawer.filledRectangle(startX - dividerSolidWidth, 0, + -dividerFadeWidth, height, + Constants.VIEWPORT_DIVIDER_FADE_COLOR, dividerLeftColor[i], dividerLeftColor[i], Constants.VIEWPORT_DIVIDER_FADE_COLOR); } - renderer.end(); + batch.end(); } private void drawDarkOverlay() { float height = stage.getViewport().getWorldHeight(); float width = stage.getViewport().getWorldWidth(); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(mapDarkOverlayColor); - renderer.rect(0, 0, width, height); - renderer.end(); + shapeDrawer.setColor(mapDarkOverlayColor); + batch.begin(); + shapeDrawer.filledRectangle(0, 0, width, height); + batch.end(); } @Override @@ -466,8 +479,6 @@ public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); for (int i = 0; i < mapViewports.length; i++) { if (playerIndex + i < players.length) { focusAndRenderViewport(mapViewports[i], players[playerIndex + i], dragOffset[i], delta); @@ -475,13 +486,12 @@ public void render(float delta) { } this.viewport.apply(true); - renderer.setProjectionMatrix(this.viewport.getCamera().combined); + batch.setProjectionMatrix(this.viewport.getCamera().combined); - if (splitScreenCount > 1) { + if (splitScreenCount > 1 && mapViewports.length >= 2) { drawViewportDividers(); } drawDarkOverlay(); - Gdx.gl.glDisable(GL20.GL_BLEND); if (showFPSCounter) { UITextDisplayer.displayFPS(viewport, stage.getBatch(), font); @@ -494,10 +504,11 @@ public void render(float delta) { @Override public void dispose() { stage.dispose(); - renderer.dispose(); + batch.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } + map.dispose(); } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java index dbdb1bd..a329b0f 100644 --- a/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java +++ b/core/src/com/cg/zoned/screens/PlayerSetUpScreen.java @@ -8,11 +8,10 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Button; -import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; @@ -26,12 +25,13 @@ import com.cg.zoned.MapSelector; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; import com.cg.zoned.managers.MapManager; import com.cg.zoned.managers.UIButtonManager; -import com.cg.zoned.ui.CustomButtonGroup; +import com.cg.zoned.ui.ButtonGroup; import com.cg.zoned.ui.FocusableStage; import com.cg.zoned.ui.HoverImageButton; import com.cg.zoned.ui.Spinner; @@ -47,7 +47,9 @@ public class PlayerSetUpScreen extends ScreenAdapter implements InputProcessor { private boolean showFPSCounter; private BitmapFont font; - private ShapeRenderer renderer; + private ShapeDrawer shapeDrawer; + private SpriteBatch batch; + private float bgAlpha = .25f; private float bgAnimSpeed = 1.8f; private Color[] currentBgColors; @@ -58,13 +60,15 @@ public class PlayerSetUpScreen extends ScreenAdapter implements InputProcessor { public PlayerSetUpScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Setting up splitscreen multiplayer"); 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.getName()); - this.renderer = new ShapeRenderer(); + this.batch = new SpriteBatch(); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); this.playerCount = game.preferences.getInteger(Constants.SPLITSCREEN_PLAYER_COUNT_PREFERENCE, 2); this.playerList = new Table(); @@ -100,14 +104,14 @@ public void animationEnd(Stage stage) { private void setUpUIButtons() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { onBackPressed(); } }); - HoverImageButton tutorialButton = uiButtonManager.addTutorialButtonToStage(); + HoverImageButton tutorialButton = uiButtonManager.addTutorialButtonToStage(game.assets.getTutorialButtonTexture()); tutorialButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -135,7 +139,7 @@ private void setUpStage() { Label[] promptLabels = new Label[playerCount]; Button[][] colorButtons = new Button[playerCount][]; - final CustomButtonGroup[] colorButtonGroups = new CustomButtonGroup[playerCount]; + final ButtonGroup[] colorButtonGroups = new ButtonGroup[playerCount]; for (int i = 0; i < playerCount; i++) { Table playerItem = new Table(); playerItem.center(); @@ -143,7 +147,7 @@ private void setUpStage() { playerItem.add(promptLabels[i]); colorButtons[i] = new Button[NO_OF_COLORS]; - colorButtonGroups[i] = new CustomButtonGroup(); + colorButtonGroups[i] = new ButtonGroup(); colorButtonGroups[i].setMinCheckCount(1); colorButtonGroups[i].setMaxCheckCount(1); @@ -158,7 +162,7 @@ private void setUpStage() { } final int finalI = i; - colorButtonGroups[i].setOnCheckChangeListener(new CustomButtonGroup.OnCheckChangeListener() { + colorButtonGroups[i].setOnCheckChangeListener(new ButtonGroup.OnCheckChangeListener() { @Override public void buttonPressed(Button button) { targetBgColors[finalI].set(button.getColor()); @@ -175,7 +179,7 @@ public void buttonPressed(Button button) { table.add(playerList).colspan(NO_OF_COLORS + 1).expandX(); table.row(); - final MapSelector mapSelector = new MapSelector(stage, game.getScaleFactor(), game.skin); + final MapSelector mapSelector = new MapSelector(stage, game.getScaleFactor(), game.assets, game.skin); mapSelector.setUsedTextureArray(usedTextures); Spinner mapSpinner = mapSelector.loadMapSelectorSpinner(150 * game.getScaleFactor(), game.skin.getFont(Constants.FONT_MANAGER.REGULAR.getName()).getLineHeight() * 3); @@ -187,7 +191,7 @@ public void buttonPressed(Button button) { stage.addFocusableActor(mapSelector.getRightButton(), NO_OF_COLORS - 1); stage.row(); - if (playerCount <= 2) { + if (playerCount == 2) { Table infoTable = new Table(); infoTable.center(); Texture infoIconTexture = new Texture(Gdx.files.internal("icons/ui_icons/ic_info.png")); @@ -270,17 +274,14 @@ public void render(float delta) { viewport.apply(true); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); - renderer.setProjectionMatrix(viewport.getCamera().combined); - renderer.begin(ShapeRenderer.ShapeType.Filled); + batch.setProjectionMatrix(viewport.getCamera().combined); + batch.begin(); for (int i = 0; i < currentBgColors.length; i++) { - renderer.setColor(currentBgColors[i]); - renderer.rect(i * stage.getWidth() / currentBgColors.length, 0, + shapeDrawer.setColor(currentBgColors[i]); + shapeDrawer.filledRectangle(i * stage.getWidth() / currentBgColors.length, 0, stage.getWidth() / currentBgColors.length, stage.getHeight()); } - renderer.end(); - Gdx.gl.glDisable(GL20.GL_BLEND); + batch.end(); if (showFPSCounter) { UITextDisplayer.displayFPS(viewport, stage.getBatch(), font); @@ -293,7 +294,7 @@ public void render(float delta) { @Override public void dispose() { stage.dispose(); - renderer.dispose(); + batch.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } diff --git a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java index 3d49f01..b61aab6 100644 --- a/core/src/com/cg/zoned/screens/ServerLobbyScreen.java +++ b/core/src/com/cg/zoned/screens/ServerLobbyScreen.java @@ -10,7 +10,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.Actor; @@ -31,6 +31,7 @@ import com.cg.zoned.MapSelector; import com.cg.zoned.Player; import com.cg.zoned.PlayerColorHelper; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; import com.cg.zoned.managers.AnimationManager; @@ -60,7 +61,9 @@ public class ServerLobbyScreen extends ScreenAdapter implements ServerLobbyConne private boolean showFPSCounter; private BitmapFont font; - private ShapeRenderer renderer; + private ShapeDrawer shapeDrawer; + private SpriteBatch batch; + private com.cg.zoned.Map map; private Cell[][] mapGrid; private ExtendViewport mapViewport; @@ -73,6 +76,7 @@ public class ServerLobbyScreen extends ScreenAdapter implements ServerLobbyConne public ServerLobbyScreen(final Zoned game, Server server, String name) { this.game = game; + game.discordRPCManager.updateRPC("In the Server Lobby"); viewport = new ScreenViewport(); stage = new FocusableStage(viewport); @@ -108,16 +112,16 @@ private void setUpServerLobbyStage() { serverLobbyTable.row(); Table scrollTable = new Table(); - ScrollPane playerListScrollPane = new ScrollPane(scrollTable); + ScrollPane playerListScrollPane = new ScrollPane(scrollTable, game.skin); playerListScrollPane.setOverscroll(false, true); playerList = new Table(); //playerList.setDebug(true); scrollTable.add(playerList).expand(); - serverLobbyTable.add(playerListScrollPane).expand(); + serverLobbyTable.add(playerListScrollPane).grow(); serverLobbyTable.row(); - mapSelector = new MapSelector(stage, game.getScaleFactor(), game.skin); + 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.getName()).getLineHeight() * 3); @@ -142,7 +146,7 @@ public void dialogResult(String buttonText) { mapSelector.loadSelectedMap(); mapButton.setText(mapSelector.getMapManager().getPreparedMap().getName()); mapGrid = mapSelector.getMapManager().getPreparedMapGrid(); - map = new com.cg.zoned.Map(mapGrid, 0); + map = new com.cg.zoned.Map(mapGrid, 0, shapeDrawer); repopulateMapStartPosLocations(); updateMapColor(players[0], players[0].color, 0); @@ -184,8 +188,7 @@ public void clicked(InputEvent event, float x, float y) { serverLobbyTable.add(startButton).width(250 * game.getScaleFactor()).pad(10 * game.getScaleFactor()); stage.addActor(serverLobbyTable); - stage.addFocusableActor(mapSelector.getLeftButton()); - stage.addFocusableActor(mapSelector.getRightButton()); + stage.addFocusableActor(mapButton, 2); stage.row(); stage.addFocusableActor(startButton, 2); stage.row(); @@ -194,12 +197,12 @@ public void clicked(InputEvent event, float x, float y) { private void setUpMap() { mapSelector.loadSelectedMap(); - this.renderer = new ShapeRenderer(); - this.renderer.setAutoShapeType(true); + this.batch = new SpriteBatch(); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); this.mapViewport = new ExtendViewport(Constants.WORLD_SIZE, Constants.WORLD_SIZE); this.mapDarkOverlayColor = new Color(0, 0, 0, .8f); this.mapGrid = mapSelector.getMapManager().getPreparedMapGrid(); - this.map = new com.cg.zoned.Map(this.mapGrid, 0); + this.map = new com.cg.zoned.Map(this.mapGrid, 0, shapeDrawer); this.players = new Player[0]; // This array size is increased in playerConnected // I know I should use Arrays (libGDX's ArrayLists) instead but Map works with regular 'ol arrays for now @@ -207,7 +210,7 @@ private void setUpMap() { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -491,15 +494,12 @@ public void render(float delta) { Gdx.gl.glClearColor(0, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); - focusAndRenderViewport(mapViewport, players[0], delta); + renderMap(delta); this.viewport.apply(true); - renderer.setProjectionMatrix(this.viewport.getCamera().combined); + batch.setProjectionMatrix(this.viewport.getCamera().combined); drawDarkOverlay(); - Gdx.gl.glDisable(GL20.GL_BLEND); if (showFPSCounter) { UITextDisplayer.displayFPS(viewport, stage.getBatch(), font); @@ -509,15 +509,17 @@ public void render(float delta) { stage.act(delta); } - private void focusAndRenderViewport(Viewport viewport, Player player, float delta) { + private void renderMap(float delta) { + Viewport viewport = mapViewport; + Player player = players[0]; + focusCameraOnPlayer(viewport, player, delta); viewport.apply(); - renderer.setProjectionMatrix(viewport.getCamera().combined); - - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.render(players, renderer, (OrthographicCamera) viewport.getCamera(), delta); - renderer.end(); + batch.setProjectionMatrix(viewport.getCamera().combined); + batch.begin(); + map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + batch.end(); } private void focusCameraOnPlayer(Viewport viewport, Player player, float delta) { @@ -551,19 +553,21 @@ private void updateCamera(Camera camera, int width, int height) { private void drawDarkOverlay() { float height = stage.getViewport().getWorldHeight(); float width = stage.getViewport().getWorldWidth(); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(mapDarkOverlayColor); - renderer.rect(0, 0, width, height); - renderer.end(); + + shapeDrawer.setColor(mapDarkOverlayColor); + batch.begin(); + shapeDrawer.filledRectangle(0, 0, width, height); + batch.end(); } @Override public void dispose() { stage.dispose(); - renderer.dispose(); + batch.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } + map.dispose(); } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/SettingsScreen.java b/core/src/com/cg/zoned/screens/SettingsScreen.java index a8d8264..544f398 100644 --- a/core/src/com/cg/zoned/screens/SettingsScreen.java +++ b/core/src/com/cg/zoned/screens/SettingsScreen.java @@ -43,6 +43,7 @@ public class SettingsScreen extends ScreenAdapter implements InputProcessor { public SettingsScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Configuring Settings"); this.viewport = new ScreenViewport(); this.stage = new FocusableStage(this.viewport); @@ -146,7 +147,7 @@ public void changed(ChangeEvent event, Actor actor) { table.add(showFPS).colspan(2).padTop(30f); - masterTable.add(screenScrollPane); + masterTable.add(screenScrollPane).grow(); stage.addActor(masterTable); stage.addFocusableActor(piemenuControl); stage.addFocusableActor(flingControl); @@ -157,7 +158,7 @@ public void changed(ChangeEvent event, Actor actor) { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { diff --git a/core/src/com/cg/zoned/screens/TutorialScreen.java b/core/src/com/cg/zoned/screens/TutorialScreen.java index 0dfcb7f..c3b6dd4 100644 --- a/core/src/com/cg/zoned/screens/TutorialScreen.java +++ b/core/src/com/cg/zoned/screens/TutorialScreen.java @@ -13,7 +13,6 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; @@ -32,6 +31,7 @@ import com.cg.zoned.Constants; import com.cg.zoned.Map; import com.cg.zoned.Player; +import com.cg.zoned.ShapeDrawer; import com.cg.zoned.TutorialItem; import com.cg.zoned.UITextDisplayer; import com.cg.zoned.Zoned; @@ -56,7 +56,7 @@ public class TutorialScreen extends ScreenAdapter implements InputProcessor { private boolean showFPSCounter; private Label dummyLabel; - private ShapeRenderer renderer; + private ShapeDrawer shapeDrawer; private SpriteBatch batch; private Map map; private Cell[][] mapGrid; @@ -71,15 +71,15 @@ public class TutorialScreen extends ScreenAdapter implements InputProcessor { public TutorialScreen(final Zoned game) { this.game = game; + game.discordRPCManager.updateRPC("Playing the Tutorial"); 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.getName()); - this.renderer = new ShapeRenderer(); - this.renderer.setAutoShapeType(true); this.batch = new SpriteBatch(); + this.shapeDrawer = new ShapeDrawer(batch, usedTextures); this.dummyLabel = new Label("DUMMY", game.skin); // Used to set the height of the tutorial table @@ -88,7 +88,7 @@ public TutorialScreen(final Zoned game) { private void initMap() { populateMapGrid(); - this.map = new Map(mapGrid, 0); + this.map = new Map(mapGrid, 0, shapeDrawer); this.mapViewport = new ExtendViewport(Constants.WORLD_SIZE, Constants.WORLD_SIZE); this.mapOverlayColor = new Color(0, 0, 0, .8f); this.mapDarkOverlayColor = new Color(0, 0, 0, .8f); @@ -99,6 +99,7 @@ private void initMap() { 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()); + this.map.createPlayerLabelTextures(this.players, shapeDrawer, playerLabelFont); this.controlManager = new ControlManager(players, stage); this.controlManager.setUpControls(game.preferences.getInteger(Constants.CONTROL_PREFERENCE), false, game.getScaleFactor(), usedTextures); @@ -133,7 +134,7 @@ private void setUpStage() { tutorialTable.left().bottom().pad(10f); Table innerTable = new Table(); - ScrollPane scrollPane = new ScrollPane(innerTable); + final ScrollPane scrollPane = new ScrollPane(innerTable); scrollPane.setOverscroll(false, false); final Label mainLabel = new Label("Welcome to the tutorial!", game.skin, "themed"); @@ -209,6 +210,14 @@ public void clicked(InputEvent event, float x, float y) { return; } + if (!scrollPane.isRightEdge()) { + scrollPane.scrollTo(scrollPane.getScrollX() + scrollPane.getWidth(), 0, + scrollPane.getWidth(), scrollPane.getHeight()); + return; + } else { + scrollPane.scrollTo(0, 0, scrollPane.getWidth(), scrollPane.getHeight()); + } + tutorialTable.addAction(Actions.sequence( Actions.fadeOut(.2f, Interpolation.fastSlow), Actions.run(new Runnable() { @@ -274,7 +283,7 @@ private void togglePlayerInterable(boolean playerInteractable) { private void setUpBackButton() { UIButtonManager uiButtonManager = new UIButtonManager(stage, game.getScaleFactor(), usedTextures); - HoverImageButton backButton = uiButtonManager.addBackButtonToStage(); + HoverImageButton backButton = uiButtonManager.addBackButtonToStage(game.assets.getBackButtonTexture()); backButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { @@ -307,36 +316,17 @@ public void render(float delta) { players[0].direction = players[0].updatedDirection; map.update(null, players, delta); - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); - focusAndRenderViewport(mapViewport, players[0], delta); - - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.renderPlayerLabelBg(players, renderer, playerLabelFont); - renderer.end(); - - Gdx.gl.glDisable(GL20.GL_BLEND); - - batch.setProjectionMatrix(mapViewport.getCamera().combined); - batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); - batch.begin(); - map.drawPlayerLabels(players, batch, playerLabelFont); - batch.end(); - - Gdx.gl.glEnable(GL20.GL_BLEND); - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); + renderMap(delta); this.viewport.apply(true); - renderer.setProjectionMatrix(this.viewport.getCamera().combined); + batch.setProjectionMatrix(this.viewport.getCamera().combined); drawDarkOverlay(delta); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.rect(0, (dummyLabel.getPrefHeight() * 2) + 20f, stage.getWidth(), 8f, - Color.WHITE, Color.WHITE, - Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR); - renderer.end(); - Gdx.gl.glDisable(GL20.GL_BLEND); + batch.begin(); + shapeDrawer.filledRectangle(0, (dummyLabel.getPrefHeight() * 2) + 20f, stage.getWidth(), 8f, + Constants.VIEWPORT_DIVIDER_FADE_COLOR, Constants.VIEWPORT_DIVIDER_FADE_COLOR, Color.WHITE, Color.WHITE); + batch.end(); if (showFPSCounter) { UITextDisplayer.displayFPS(viewport, stage.getBatch(), font); @@ -346,15 +336,17 @@ public void render(float delta) { stage.draw(); } - private void focusAndRenderViewport(Viewport viewport, Player player, float delta) { + private void renderMap(float delta) { + Viewport viewport = mapViewport; + Player player = players[0]; + focusCameraOnPlayer(viewport, player, delta); viewport.apply(); - renderer.setProjectionMatrix(viewport.getCamera().combined); - - renderer.begin(ShapeRenderer.ShapeType.Filled); - map.render(players, renderer, (OrthographicCamera) viewport.getCamera(), delta); - renderer.end(); + batch.setProjectionMatrix(viewport.getCamera().combined); + batch.begin(); + map.render(players, shapeDrawer, (OrthographicCamera) viewport.getCamera(), delta); + batch.end(); } private void focusCameraOnPlayer(Viewport viewport, Player player, float delta) { @@ -379,20 +371,20 @@ private void drawDarkOverlay(float delta) { float height = stage.getViewport().getWorldHeight(); float width = stage.getViewport().getWorldWidth(); - renderer.begin(ShapeRenderer.ShapeType.Filled); - renderer.setColor(mapOverlayColor); - renderer.rect(0, 0, width, height); - renderer.end(); + batch.begin(); + shapeDrawer.setColor(mapOverlayColor); + shapeDrawer.filledRectangle(0, 0, width, height); + batch.end(); } @Override public void dispose() { stage.dispose(); batch.dispose(); - renderer.dispose(); for (Texture texture : usedTextures) { texture.dispose(); } + map.dispose(); } private void onBackPressed() { diff --git a/core/src/com/cg/zoned/screens/VictoryScreen.java b/core/src/com/cg/zoned/screens/VictoryScreen.java index aa7815a..5b5ad79 100644 --- a/core/src/com/cg/zoned/screens/VictoryScreen.java +++ b/core/src/com/cg/zoned/screens/VictoryScreen.java @@ -18,6 +18,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Sort; import com.badlogic.gdx.utils.StringBuilder; import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.Viewport; @@ -31,6 +32,7 @@ import com.cg.zoned.ui.FocusableStage; import java.text.DecimalFormat; +import java.util.Comparator; public class VictoryScreen extends ScreenAdapter implements InputProcessor { final Zoned game; @@ -52,6 +54,7 @@ public class VictoryScreen extends ScreenAdapter implements InputProcessor { public VictoryScreen(final Zoned game, PlayerManager playerManager, int rows, int cols, int wallCount) { this.game = game; + game.discordRPCManager.updateRPC("Post match"); this.usedTextures = new Array<>(); @@ -187,6 +190,7 @@ public void clicked(InputEvent event, float x, float y) { private void getVictoryStrings(PlayerManager playerManager, int rows, int cols, int wallCount) { teamData = playerManager.getTeamData(); + new Sort().sort(teamData, new TeamDataComparator()); this.victoryStrings = new String[teamData.size]; DecimalFormat df = new DecimalFormat("#.##"); @@ -237,6 +241,13 @@ public void onBackPressed() { animationManager.fadeOutStage(stage, this, new MainMenuScreen(game)); } + private static class TeamDataComparator implements Comparator { + @Override + public int compare(TeamData t1, TeamData t2) { + return t2.score - t1.score; + } + } + @Override public boolean keyDown(int keycode) { if (keycode == Input.Keys.BACK || keycode == Input.Keys.ESCAPE) { diff --git a/core/src/com/cg/zoned/ui/CustomButtonGroup.java b/core/src/com/cg/zoned/ui/ButtonGroup.java similarity index 86% rename from core/src/com/cg/zoned/ui/CustomButtonGroup.java rename to core/src/com/cg/zoned/ui/ButtonGroup.java index 9dbf72a..7f69610 100644 --- a/core/src/com/cg/zoned/ui/CustomButtonGroup.java +++ b/core/src/com/cg/zoned/ui/ButtonGroup.java @@ -1,9 +1,8 @@ package com.cg.zoned.ui; import com.badlogic.gdx.scenes.scene2d.ui.Button; -import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup; -public class CustomButtonGroup extends ButtonGroup { +public class ButtonGroup extends com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup { private OnCheckChangeListener onCheckChangeListener = null; @Override diff --git a/core/src/com/cg/zoned/ui/CheckBox.java b/core/src/com/cg/zoned/ui/CheckBox.java new file mode 100644 index 0000000..8099356 --- /dev/null +++ b/core/src/com/cg/zoned/ui/CheckBox.java @@ -0,0 +1,128 @@ +package com.cg.zoned.ui; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.scenes.scene2d.ui.Cell; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Scaling; + +/** + * A checkbox is a button that contains an image indicating the checked or unchecked state and a label. + * + * @author Nathan Sweet + *

+ * Slightly modified from the official implementation by Nathan Sweet. + * Has a reversed parameter for RTL implementation rather than LTR + */ +public class CheckBox extends TextButton { + private Image image; + private Cell imageCell; + private com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle style; + + public CheckBox(String text, Skin skin, boolean reversed) { + this(text, skin.get(com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle.class), reversed); + } + + public CheckBox(String text, Skin skin, String styleName, boolean reversed) { + this(text, skin.get(styleName, com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle.class), reversed); + } + + public CheckBox(String text, com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle style, boolean reversed) { + super(text, style); + clearChildren(); + Label label = getLabel(); + image = new Image(style.checkboxOff, Scaling.none); + if (!reversed) { + imageCell = add(image); + add(label); + label.setAlignment(Align.left); + } else { + add(label); + imageCell = add(image); + label.setAlignment(Align.right); + } + setSize(getPrefWidth(), getPrefHeight()); + } + + /** + * Returns the checkbox's style. Modifying the returned style may not have an effect until {@link #setStyle(ButtonStyle)} is + * called. + */ + public com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle getStyle() { + return style; + } + + public void setStyle(ButtonStyle style) { + if (!(style instanceof com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle)) + throw new IllegalArgumentException("style must be a CheckBoxStyle."); + super.setStyle(style); + this.style = (com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle) style; + } + + public void draw(Batch batch, float parentAlpha) { + Drawable checkbox = null; + if (isDisabled()) { + if (isChecked() && style.checkboxOnDisabled != null) + checkbox = style.checkboxOnDisabled; + else + checkbox = style.checkboxOffDisabled; + } + if (checkbox == null) { + boolean over = isOver() && !isDisabled(); + if (isChecked() && style.checkboxOn != null) + checkbox = over && style.checkboxOnOver != null ? style.checkboxOnOver : style.checkboxOn; + else if (over && style.checkboxOver != null) + checkbox = style.checkboxOver; + else + checkbox = style.checkboxOff; + } + image.setDrawable(checkbox); + super.draw(batch, parentAlpha); + } + + public Image getImage() { + return image; + } + + public Cell getImageCell() { + return imageCell; + } + + /** + * The style for a select box, see {@link com.badlogic.gdx.scenes.scene2d.ui.CheckBox}. + * + * @author Nathan Sweet + */ + static public class CheckBoxStyle extends TextButtonStyle { + public Drawable checkboxOn, checkboxOff; + /** + * Optional. + */ + public Drawable checkboxOnOver, checkboxOver, checkboxOnDisabled, checkboxOffDisabled; + + public CheckBoxStyle() { + } + + public CheckBoxStyle(Drawable checkboxOff, Drawable checkboxOn, BitmapFont font, Color fontColor) { + this.checkboxOff = checkboxOff; + this.checkboxOn = checkboxOn; + this.font = font; + this.fontColor = fontColor; + } + + public CheckBoxStyle(com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle style) { + super(style); + this.checkboxOff = style.checkboxOff; + this.checkboxOn = style.checkboxOn; + this.checkboxOver = style.checkboxOver; + this.checkboxOffDisabled = style.checkboxOffDisabled; + this.checkboxOnDisabled = style.checkboxOnDisabled; + } + } +} diff --git a/core/src/com/cg/zoned/ui/FocusableStage.java b/core/src/com/cg/zoned/ui/FocusableStage.java index 6e6e66b..39f785b 100644 --- a/core/src/com/cg/zoned/ui/FocusableStage.java +++ b/core/src/com/cg/zoned/ui/FocusableStage.java @@ -2,6 +2,9 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.EventListener; @@ -14,6 +17,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextField; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.Viewport; @@ -47,7 +51,7 @@ public class FocusableStage extends Stage { * The same Actor object is stored colspan times so as to satisfy the grid arrangement properly * A null value in the array indicates a row in the actor arrangement */ - private Array focusableActorArray = new Array(); + private Array focusableActorArray = new Array<>(); /** * Holds the currently focused actor @@ -64,6 +68,11 @@ public class FocusableStage extends Stage { */ private Dialog dialog; + /** + * The Texture used in the background of a dialog when it is active + */ + private Texture dialogBackgroundTexture = null; + /** * Master switch for enabling keyboard based focus management * When this is false, it will behave like a regular Stage @@ -77,6 +86,23 @@ public class FocusableStage extends Stage { */ public FocusableStage(Viewport viewport) { super(viewport); + + createDialogBGTexture(); + } + + /** + * Creates the dialog background texture + */ + private void createDialogBGTexture() { + if (dialogBackgroundTexture != null) { + dialogBackgroundTexture.dispose(); + } + + Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA4444); + pixmap.setColor(new Color(0, 0, 0, .8f)); + pixmap.drawPixel(0, 0); + dialogBackgroundTexture = new Texture(pixmap); + pixmap.dispose(); } /** @@ -184,12 +210,12 @@ private void defocus(Actor actor) { /** * Shows an dialog with focus properties on its buttons * - * @param msg The message to display - * @param buttonTexts Texts for each button in the dialog + * @param msg The message to display + * @param buttonTexts Texts for each button in the dialog * @param useVerticalButtonList Determines whether the dialog buttons are arranged horizontally or vertically - * @param scaleFactor The game's scaleFactor to scale up/down dialog button width - * @param dialogResultListener Interface for beaming back the selected dialog option - * @param skin The skin to use for the dialog + * @param scaleFactor The game's scaleFactor to scale up/down dialog button width + * @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, @@ -206,7 +232,7 @@ public void showDialog(Table contentTable, Array buttonTexts, private void showDialog(Actor content, Array buttonTexts, boolean useVerticalButtonList, float scaleFactor, final DialogResultListener dialogResultListener, Skin skin) { - final Array backupCurrentActorArray = new Array(this.focusableActorArray); + final Array backupCurrentActorArray = new Array<>(this.focusableActorArray); final Actor backupFocusedActor = this.currentFocusedActor; final Dialog previousDialog = dialog; @@ -250,6 +276,7 @@ protected void result(Object object) { } } + 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)); @@ -590,6 +617,12 @@ public void addTouchFocus(EventListener listener, Actor listenerActor, Actor tar super.addTouchFocus(listener, listenerActor, target, pointer, button); } + @Override + public void dispose() { + dialogBackgroundTexture.dispose(); + super.dispose(); + } + public interface DialogResultListener { void dialogResult(String buttonText); } diff --git a/core/src/com/cg/zoned/ui/ParticleEffectActor.java b/core/src/com/cg/zoned/ui/ParticleEffectActor.java new file mode 100644 index 0000000..76b78a8 --- /dev/null +++ b/core/src/com/cg/zoned/ui/ParticleEffectActor.java @@ -0,0 +1,34 @@ +package com.cg.zoned.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.ParticleEffect; +import com.badlogic.gdx.scenes.scene2d.Actor; + +public class ParticleEffectActor extends Actor { + private ParticleEffect particleEffect; + + public ParticleEffectActor(ParticleEffect particleEffect) { + super(); + this.particleEffect = particleEffect; + } + + @Override + public void draw(Batch batch, float parentAlpha) { + particleEffect.draw(batch); + } + + @Override + public void act(float delta) { + super.act(delta); + particleEffect.setPosition(getWidth() / 2, getHeight() / 2); + particleEffect.update(delta); + } + + public void start() { + particleEffect.start(); + } + + public void allowCompletion() { + particleEffect.allowCompletion(); + } +} diff --git a/desktop/build.gradle b/desktop/build.gradle index 0597401..2ac780f 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -5,9 +5,11 @@ sourceSets.main.java.srcDirs = [ "src/" ] project.ext.mainClassName = "com.cg.zoned.desktop.DesktopLauncher" project.ext.assetsDir = new File("../android/assets") -project.setVersion("0.0.1-beta") +project.setProperty("archivesBaseName", appName) +project.setVersion("0.0.2-beta") // 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 // Or for Linux users, use the versionUpdate.sh script task run(dependsOn: classes, type: JavaExec) { diff --git a/versionUpdate.sh b/versionUpdate.sh index 1e518ef..05560ba 100755 --- a/versionUpdate.sh +++ b/versionUpdate.sh @@ -19,6 +19,13 @@ if [ "$proceed" == "Y" ]; then do sed -i -e "s/$oldVersionName/$newVersionName/g" "$filename" done + + echo "Warning: Versions in the README file aren't updated. Do it manually" + + 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 else echo "Alright, aborted" fi