9,8,8,8,8,8,8,8,8,8,8,8,8,8,10,
7,0,0,5,5,6,5,5,5,5,5,5,0,0,7,
diff --git a/client/core/assets/skins/skin.atlas b/client/core/assets/skins/skin.atlas
index 7a083ac..37a9d86 100644
--- a/client/core/assets/skins/skin.atlas
+++ b/client/core/assets/skins/skin.atlas
@@ -6,7 +6,7 @@ filter: Nearest,Nearest
repeat: none
button_checked
rotate: false
- xy: 68, 54
+ xy: 68, 36
size: 16, 16
split: 3, 3, 3, 3
orig: 16, 16
@@ -28,6 +28,14 @@ button_up
orig: 16, 16
offset: 0, 0
index: -1
+label_background
+ rotate: false
+ xy: 68, 54
+ size: 16, 16
+ split: 0, 17, 0, 17
+ orig: 16, 16
+ offset: 0, 0
+ index: -1
placeholder
rotate: false
xy: 68, 108
@@ -53,7 +61,7 @@ progress_bar_fill
index: -1
separator
rotate: false
- xy: 68, 36
+ xy: 68, 18
size: 16, 16
split: 1, 1, 1, 1
orig: 16, 16
diff --git a/client/core/assets/skins/skin.png b/client/core/assets/skins/skin.png
index f97e4cd..edb300d 100644
Binary files a/client/core/assets/skins/skin.png and b/client/core/assets/skins/skin.png differ
diff --git a/client/core/assets/textures/bomberman.atlas b/client/core/assets/textures/bomberman.atlas
index fa51f04..d1c6bac 100644
--- a/client/core/assets/textures/bomberman.atlas
+++ b/client/core/assets/textures/bomberman.atlas
@@ -1,355 +1,446 @@
bomberman.png
-size: 678,54
+size: 211,211
format: RGBA8888
filter: Nearest,Nearest
repeat: none
ArrowFast
rotate: false
- xy: 288, 2
+ xy: 132, 55
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+Bomb
+ rotate: false
+ xy: 132, 3
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 1
+Bomb
+ rotate: false
+ xy: 158, 29
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 2
+Bomb
+ rotate: false
+ xy: 184, 55
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 3
+BombStatic
+ rotate: false
+ xy: 132, 107
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+Boom
+ rotate: false
+ xy: 28, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Box1
rotate: false
- xy: 392, 28
+ xy: 158, 81
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Box2
rotate: false
- xy: 392, 2
+ xy: 184, 107
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+CDR
+ rotate: false
+ xy: 54, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Dynamite
rotate: false
- xy: 314, 2
+ xy: 28, 81
size: 24, 24
orig: 24, 24
offset: 0, 0
- index: 3
+ index: 2
Dynamite
rotate: false
- xy: 366, 28
+ xy: 80, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: 1
Dynamite
rotate: false
- xy: 418, 28
+ xy: 80, 3
size: 24, 24
orig: 24, 24
offset: 0, 0
- index: 2
+ index: 3
DynamiteStatic
rotate: false
- xy: 54, 2
+ xy: 2, 132
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+FastBoom
+ rotate: false
+ xy: 184, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Floor
rotate: false
- xy: 470, 28
+ xy: 158, 55
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+FrozenTint
+ rotate: false
+ xy: 132, 81
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+Fryzjer
+ rotate: false
+ xy: 106, 3
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice
rotate: false
- xy: 444, 2
+ xy: 132, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice1
rotate: false
- xy: 288, 28
+ xy: 54, 107
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice2
rotate: false
- xy: 652, 28
+ xy: 184, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice3
rotate: false
- xy: 132, 2
+ xy: 106, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice4
rotate: false
- xy: 2, 27
+ xy: 2, 184
size: 24, 25
orig: 24, 25
offset: 0, 0
index: -1
Ice5
rotate: false
- xy: 444, 28
+ xy: 132, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice6
rotate: false
- xy: 340, 28
+ xy: 2, 28
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice7
rotate: false
- xy: 522, 28
+ xy: 28, 55
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Ice8
rotate: false
- xy: 470, 2
+ xy: 54, 81
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava
rotate: false
- xy: 28, 28
+ xy: 2, 158
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava1
rotate: false
- xy: 496, 2
+ xy: 80, 107
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava2
rotate: false
- xy: 496, 28
+ xy: 106, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava3
rotate: false
- xy: 522, 2
+ xy: 132, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava4
rotate: false
- xy: 366, 2
+ xy: 106, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava5
rotate: false
- xy: 548, 2
+ xy: 2, 2
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava6
rotate: false
- xy: 574, 28
+ xy: 28, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava7
rotate: false
- xy: 574, 2
+ xy: 54, 55
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Lava8
rotate: false
- xy: 600, 28
+ xy: 80, 81
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: -1
+Nuke
+ rotate: false
+ xy: 80, 55
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 3
+Nuke
+ rotate: false
+ xy: 106, 55
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 2
+Nuke
+ rotate: false
+ xy: 184, 81
+ size: 24, 24
+ orig: 24, 24
+ offset: 0, 0
+ index: 1
+NukeStatic
+ rotate: false
+ xy: 106, 81
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_bbb_idle_back
rotate: false
- xy: 262, 2
+ xy: 80, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_bbb_idle_front
rotate: false
- xy: 600, 2
+ xy: 106, 107
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_bbb_idle_left
rotate: false
- xy: 548, 28
+ xy: 158, 3
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_bbb_idle_right
rotate: false
- xy: 184, 28
+ xy: 54, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_brw_idle_back
rotate: false
- xy: 210, 2
+ xy: 2, 54
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_brw_idle_front
rotate: false
- xy: 210, 28
+ xy: 80, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_brw_idle_left
rotate: false
- xy: 626, 2
+ xy: 132, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_brw_idle_right
rotate: false
- xy: 80, 28
+ xy: 80, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wbw_idle_back
rotate: false
- xy: 28, 2
+ xy: 158, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wbw_idle_front
rotate: false
- xy: 184, 2
+ xy: 28, 107
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wbw_idle_left
rotate: false
- xy: 340, 2
+ xy: 106, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wbw_idle_right
rotate: false
- xy: 54, 28
+ xy: 28, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wrb_idle_back
rotate: false
- xy: 236, 2
+ xy: 158, 107
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wrb_idle_front
rotate: false
- xy: 236, 28
+ xy: 158, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wrb_idle_left
rotate: false
- xy: 262, 28
+ xy: 184, 29
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Player_wrb_idle_right
rotate: false
- xy: 626, 28
+ xy: 28, 3
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Shield
rotate: false
- xy: 418, 2
+ xy: 2, 106
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall1
rotate: false
- xy: 80, 2
+ xy: 158, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall2
rotate: false
- xy: 106, 28
+ xy: 54, 185
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall3
rotate: false
- xy: 106, 2
+ xy: 184, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall4
rotate: false
- xy: 132, 28
+ xy: 28, 133
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall5
rotate: false
- xy: 314, 28
+ xy: 54, 159
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall6
rotate: false
- xy: 158, 28
+ xy: 54, 3
size: 24, 24
orig: 24, 24
offset: 0, 0
index: -1
Wall7
rotate: false
- xy: 158, 2
+ xy: 2, 80
size: 24, 24
orig: 24, 24
offset: 0, 0
diff --git a/client/core/assets/textures/bomberman.png b/client/core/assets/textures/bomberman.png
index 368b873..bee93b6 100644
Binary files a/client/core/assets/textures/bomberman.png and b/client/core/assets/textures/bomberman.png differ
diff --git a/client/core/assets/textures/bomberman_player.atlas b/client/core/assets/textures/bomberman_player.atlas
deleted file mode 100644
index 71b1e09..0000000
--- a/client/core/assets/textures/bomberman_player.atlas
+++ /dev/null
@@ -1,69 +0,0 @@
-
-bomberman_player.png
-size: 216,24
-format: RGBA8888
-filter: Nearest,Nearest
-repeat: none
-moving_back
- rotate: false
- xy: 0, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 1
-moving_back
- rotate: false
- xy: 24, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 2
-moving_front
- rotate: false
- xy: 48, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 1
-moving_front
- rotate: false
- xy: 72, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 2
-moving_side
- rotate: false
- xy: 96, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 1
-moving_side
- rotate: false
- xy: 120, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: 2
-standing_back
- rotate: false
- xy: 144, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: -1
-standing_front
- rotate: false
- xy: 168, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: -1
-standing_side
- rotate: false
- xy: 192, 0
- size: 24, 24
- orig: 24, 24
- offset: 0, 0
- index: -1
diff --git a/client/core/assets/textures/bomberman_player.png b/client/core/assets/textures/bomberman_player.png
deleted file mode 100644
index 8996e52..0000000
Binary files a/client/core/assets/textures/bomberman_player.png and /dev/null differ
diff --git a/client/core/assets/textures/menu_bg.png b/client/core/assets/textures/menu_bg.png
index a00c89d..d0225e5 100644
Binary files a/client/core/assets/textures/menu_bg.png and b/client/core/assets/textures/menu_bg.png differ
diff --git a/client/core/assets/textures/player.png b/client/core/assets/textures/player.png
deleted file mode 100644
index 39e351a..0000000
Binary files a/client/core/assets/textures/player.png and /dev/null differ
diff --git a/client/core/build.gradle b/client/core/build.gradle
index 04124b8..36e4ef7 100644
--- a/client/core/build.gradle
+++ b/client/core/build.gradle
@@ -1,7 +1,7 @@
apply plugin: "java"
apply plugin: 'org.jetbrains.kotlin.jvm'
-sourceCompatibility = 1.8
+sourceCompatibility = 13
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceSets.main.java.srcDirs = [ "src/" ]
diff --git a/client/core/src/com/cyberbot/bomberman/Client.java b/client/core/src/com/cyberbot/bomberman/Client.java
index 8513750..9f00e59 100644
--- a/client/core/src/com/cyberbot/bomberman/Client.java
+++ b/client/core/src/com/cyberbot/bomberman/Client.java
@@ -1,25 +1,18 @@
package com.cyberbot.bomberman;
import com.badlogic.gdx.Game;
-import com.badlogic.gdx.Gdx;
import com.cyberbot.bomberman.controllers.ScreenController;
public class Client extends Game {
-
- public static final float V_WIDTH = 100;
- public static final float V_HEIGHT = 100;
-
- private ScreenController gsm;
+ private ScreenController screenController;
@Override
public void create() {
- final float w = Gdx.graphics.getWidth();
- final float h = Gdx.graphics.getHeight();
-
- gsm = new ScreenController(this);
+ screenController = new ScreenController(this);
}
- public ScreenController getGsm() {
- return gsm;
+ @Override
+ public void dispose() {
+ // TODO: Dispose everything using the ScreenController
}
}
diff --git a/client/core/src/com/cyberbot/bomberman/controllers/InputController.java b/client/core/src/com/cyberbot/bomberman/controllers/InputController.java
index 8427701..c8f120f 100644
--- a/client/core/src/com/cyberbot/bomberman/controllers/InputController.java
+++ b/client/core/src/com/cyberbot/bomberman/controllers/InputController.java
@@ -65,12 +65,4 @@ public void poll() {
actionListeners.forEach(it -> it.onActions(actions));
}
-
- private void handleItem() {
-
- }
-
- private void handleMove() {
-
- }
}
diff --git a/client/core/src/com/cyberbot/bomberman/controllers/NetworkedGameplayController.java b/client/core/src/com/cyberbot/bomberman/controllers/NetworkedGameplayController.java
index 1ff1abf..578c42f 100644
--- a/client/core/src/com/cyberbot/bomberman/controllers/NetworkedGameplayController.java
+++ b/client/core/src/com/cyberbot/bomberman/controllers/NetworkedGameplayController.java
@@ -1,5 +1,6 @@
package com.cyberbot.bomberman.controllers;
+import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.World;
@@ -7,6 +8,7 @@
import com.cyberbot.bomberman.core.controllers.LocalWorldController;
import com.cyberbot.bomberman.core.models.Updatable;
import com.cyberbot.bomberman.core.models.entities.PlayerEntity;
+import com.cyberbot.bomberman.core.models.items.Upgrade;
import com.cyberbot.bomberman.core.models.net.data.PlayerData;
import com.cyberbot.bomberman.core.models.tiles.MapLoadException;
import com.cyberbot.bomberman.core.models.tiles.TileMap;
@@ -15,6 +17,7 @@
import com.cyberbot.bomberman.models.KeyBinds;
import com.cyberbot.bomberman.net.NetService;
import com.cyberbot.bomberman.screens.hud.GameHud;
+import com.cyberbot.bomberman.utils.Atlas;
import java.net.SocketAddress;
import java.util.concurrent.ScheduledExecutorService;
@@ -23,12 +26,20 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import static com.cyberbot.bomberman.core.utils.Constants.SIM_RATE;
-import static com.cyberbot.bomberman.core.utils.Constants.TICK_RATE;
-
+import static com.cyberbot.bomberman.core.utils.Constants.*;
+
+/**
+ * The main orchestrator for a networked gameplay. It schedules input polling and snapshot creation.
+ * The actual world simulation, interpolation, rollback on other world related actions are handled
+ * by a corresponding {@link LocalWorldController}.
+ *
+ * The {@link #update(float)} method can be called with arbitrary period.
+ *
+ * If the next snapshot creation falls in the middle of world simulation
+ * the snapshot thread will wait for the simulation to finish.
+ */
public class NetworkedGameplayController implements Updatable, Drawable, Disposable {
private final TextureController textureController;
- private final InputController inputController;
private final LocalWorldController worldController;
private final TileMap map;
@@ -38,25 +49,26 @@ public class NetworkedGameplayController implements Updatable, Drawable, Disposa
private final ScheduledExecutorService snapshotService;
private final ScheduledExecutorService inputPollService;
- private final World world;
-
private final ReentrantLock worldUpdateLock;
private final Condition worldUpdatedCondition;
- public NetworkedGameplayController(PlayerData player, String mapPath,
+ private final Sprite frozenTint;
+
+ public NetworkedGameplayController(PlayerData localPlayer, String mapPath,
SocketAddress connection, GameHud hud)
throws MapLoadException {
KeyBinds binds = new KeyBinds(); // TODO: Load from preferences
- world = new World(new Vector2(0, 0), false);
+ World world = new World(new Vector2(0, 0), false);
map = TileMapFactory.createTileMap(world, mapPath);
textureController = new TextureController(map);
- worldController = new LocalWorldController(world, map, TICK_RATE, player);
+ // TODO: Maybe allow variable tick rate, sim rate via server's JSON configuration
+ worldController = new LocalWorldController(world, map, TICK_RATE, SIM_RATE, localPlayer);
worldController.addListener(textureController, true);
worldController.addListener(hud, true);
- inputController = new InputController(binds, hud);
+ InputController inputController = new InputController(binds, hud);
inputController.addActionController(worldController);
netService = new NetService(connection, worldController);
@@ -72,6 +84,10 @@ public NetworkedGameplayController(PlayerData player, String mapPath,
inputPollService = new ScheduledThreadPoolExecutor(1);
inputPollService.scheduleAtFixedRate(inputController::poll,
0, 1_000_000 / SIM_RATE, TimeUnit.MICROSECONDS);
+
+ frozenTint = new Sprite(Atlas.getInstance().findRegion("FrozenTint"));
+ frozenTint.setBounds(0, 0, 15 * PPM, 15 * PPM);
+ frozenTint.setSize(15 * PPM, 15 * PPM);
}
@Override
@@ -85,11 +101,19 @@ public void update(float delta) {
}
textureController.update(delta);
+
+ if (worldController.getLocalPlayer().isFrozen()) {
+ frozenTint.setAlpha(worldController.getLocalPlayer().getFreezeTimeLeft() / Upgrade.FREEZER_DURATION);
+ }
}
@Override
public void draw(SpriteBatch batch) {
textureController.draw(batch);
+
+ if (worldController.getLocalPlayer().isFrozen()) {
+ frozenTint.draw(batch);
+ }
}
@Override
@@ -100,22 +124,24 @@ public void dispose() {
inputPollService.shutdown();
}
- public World getWorld() {
- return world;
- }
-
private void createAndSendSnapshot() {
try {
try {
worldUpdateLock.lock();
- worldUpdatedCondition.await();
+ while (worldController.isWorldLocked()) {
+ worldUpdatedCondition.await();
+ }
} finally {
worldUpdateLock.unlock();
}
netService.sendPlayerSnapshot(worldController.createSnapshot());
- } catch (Exception ignored) {
-
+ } catch (Exception e) {
+ // Exceptions thrown in the ScheduledExecutorService are caught
+ // and returned in a Future only when the executor service is stopped.
+ // This is the simplest way to prevent the service from halting and
+ // getting any debugging information from the exceptions
+ e.printStackTrace();
}
}
diff --git a/client/core/src/com/cyberbot/bomberman/controllers/ScreenController.java b/client/core/src/com/cyberbot/bomberman/controllers/ScreenController.java
index 25f8385..25e5bb9 100644
--- a/client/core/src/com/cyberbot/bomberman/controllers/ScreenController.java
+++ b/client/core/src/com/cyberbot/bomberman/controllers/ScreenController.java
@@ -9,6 +9,8 @@
import com.cyberbot.bomberman.net.ControlService;
import com.cyberbot.bomberman.screens.AbstractScreen;
import com.cyberbot.bomberman.screens.GameScreen;
+import com.cyberbot.bomberman.screens.finish.FinishInteraction;
+import com.cyberbot.bomberman.screens.finish.FinishScreen;
import com.cyberbot.bomberman.screens.lobby.LobbyInteraction;
import com.cyberbot.bomberman.screens.lobby.LobbyScreen;
import com.cyberbot.bomberman.screens.login.LoginInteraction;
@@ -20,13 +22,15 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URISyntaxException;
+import java.util.stream.Collectors;
public final class ScreenController implements MenuInteraction, LobbyInteraction,
- LoginInteraction, ClientControlListener {
+ LoginInteraction, FinishInteraction, ClientControlListener {
private final Game game;
private final LobbyScreen lobby;
private final MenuScreen menu;
private final LoginScreen login;
+ private final FinishScreen finish;
private InetSocketAddress serverAddress;
private ControlService controlService;
private final int defaultPort;
@@ -50,6 +54,7 @@ public ScreenController(final Game game, int defaultPort) {
this.menu = new MenuScreen(this);
this.lobby = new LobbyScreen(this);
this.login = new LoginScreen(this);
+ this.finish = new FinishScreen(this);
setScreen(login);
}
@@ -188,9 +193,18 @@ public void onGameStart(@NotNull GameStart payload) {
});
}
+ @Override
+ public void onGameEnd(@NotNull GameEnd payload) {
+ Gdx.app.postRunnable(() -> {
+ setScreen(finish);
+ finish.updateFinish(payload.getLeaderboard().stream().map(Client::getNick).collect(Collectors.toList()));
+ });
+ }
+
@Override
public void onError(@NotNull ErrorResponse payload) {
Gdx.app.log("ControlService", payload.getError());
+ showError(payload.getError());
}
private void showError(String message) {
@@ -205,4 +219,9 @@ private void setScreen(AbstractScreen screen) {
currentScreen = screen;
game.setScreen(screen);
}
+
+ @Override
+ public void leaveFinish() {
+ setScreen(menu);
+ }
}
diff --git a/client/core/src/com/cyberbot/bomberman/controllers/TextureController.java b/client/core/src/com/cyberbot/bomberman/controllers/TextureController.java
index 56a25b6..91c4454 100644
--- a/client/core/src/com/cyberbot/bomberman/controllers/TextureController.java
+++ b/client/core/src/com/cyberbot/bomberman/controllers/TextureController.java
@@ -3,13 +3,12 @@
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.cyberbot.bomberman.core.controllers.WorldChangeListener;
import com.cyberbot.bomberman.core.models.Updatable;
-import com.cyberbot.bomberman.core.models.entities.BombEntity;
import com.cyberbot.bomberman.core.models.entities.Entity;
import com.cyberbot.bomberman.core.models.tiles.Tile;
import com.cyberbot.bomberman.core.models.tiles.TileMap;
import com.cyberbot.bomberman.models.Drawable;
import com.cyberbot.bomberman.sprites.EntitySprite;
-import com.cyberbot.bomberman.sprites.SpriteFactory;
+import com.cyberbot.bomberman.sprites.GraphicsFactory;
import com.cyberbot.bomberman.sprites.TileSprite;
import java.util.ArrayList;
@@ -28,9 +27,9 @@ public final class TextureController implements Drawable, Updatable, WorldChange
public TextureController(TileMap map) {
map.addListener(this);
this.entities = new ArrayList<>();
- this.base = SpriteFactory.createTilesFromMapLayer(map.getBase());
- this.floor = SpriteFactory.createTilesFromMapLayer(map.getFloor());
- this.walls = SpriteFactory.createTilesFromMapLayer(map.getWalls());
+ this.base = GraphicsFactory.createTilesFromMapLayer(map.getBase());
+ this.floor = GraphicsFactory.createTilesFromMapLayer(map.getFloor());
+ this.walls = GraphicsFactory.createTilesFromMapLayer(map.getWalls());
}
@Override
@@ -46,7 +45,6 @@ public void update(float delta) {
entities.forEach(sprite -> sprite.update(delta));
}
-
@Override
public void onWallAdded(Tile tile) {
walls.add(new TileSprite(tile));
@@ -59,13 +57,8 @@ public void onWallRemoved(Tile tile) {
@Override
public void onEntityAdded(Entity entity) {
- EntitySprite> sprite = SpriteFactory.createEntitySprite(entity);
- if (entity instanceof BombEntity) {
- // Add at the begging to draw under the previous entities (ex. players)
- entities.add(0, sprite);
- } else {
- entities.add(sprite);
- }
+ EntitySprite> sprite = GraphicsFactory.createEntitySprite(entity);
+ entities.add(0, sprite);
}
@Override
diff --git a/client/core/src/com/cyberbot/bomberman/models/KeyBinds.java b/client/core/src/com/cyberbot/bomberman/models/KeyBinds.java
index aa008d1..6cc8c96 100644
--- a/client/core/src/com/cyberbot/bomberman/models/KeyBinds.java
+++ b/client/core/src/com/cyberbot/bomberman/models/KeyBinds.java
@@ -2,6 +2,7 @@
import com.badlogic.gdx.Input;
+@SuppressWarnings("CanBeFinal")
public class KeyBinds {
public int up = Input.Keys.W;
public int down = Input.Keys.S;
@@ -10,6 +11,6 @@ public class KeyBinds {
public int useItem = Input.Keys.SPACE;
// Inventory view
- public int switchItemUp = Input.Keys.E;
- public int switchItemDown = Input.Keys.Q;
+ public int switchItemUp = Input.Keys.Q;
+ public int switchItemDown = Input.Keys.E;
}
diff --git a/client/core/src/com/cyberbot/bomberman/net/ClientControlListener.kt b/client/core/src/com/cyberbot/bomberman/net/ClientControlListener.kt
index 90cd7b4..2c380d4 100644
--- a/client/core/src/com/cyberbot/bomberman/net/ClientControlListener.kt
+++ b/client/core/src/com/cyberbot/bomberman/net/ClientControlListener.kt
@@ -21,4 +21,6 @@ interface ClientControlListener {
fun onError(payload: ErrorResponse)
fun onRegisterResponse(payload: ClientRegisterResponse)
+
+ fun onGameEnd(payload: GameEnd)
}
\ No newline at end of file
diff --git a/client/core/src/com/cyberbot/bomberman/net/ControlService.kt b/client/core/src/com/cyberbot/bomberman/net/ControlService.kt
index 8aa25ca..af80d39 100644
--- a/client/core/src/com/cyberbot/bomberman/net/ControlService.kt
+++ b/client/core/src/com/cyberbot/bomberman/net/ControlService.kt
@@ -73,6 +73,7 @@ class ControlService(private val address: SocketAddress) : Runnable {
is LobbyCreateResponse -> listeners.forEach { it.onLobbyCreate(packet) }
is LobbyJoinResponse -> listeners.forEach { it.onLobbyJoin(packet) }
is GameStart -> listeners.forEach { it.onGameStart(packet) }
+ is GameEnd -> listeners.forEach { it.onGameEnd(packet) }
is ErrorResponse -> listeners.forEach { it.onError(packet) }
}
} catch (e: JsonSyntaxException) {
diff --git a/client/core/src/com/cyberbot/bomberman/screens/ScreenState.java b/client/core/src/com/cyberbot/bomberman/screens/ScreenState.java
index 8b190fd..75ca2e7 100644
--- a/client/core/src/com/cyberbot/bomberman/screens/ScreenState.java
+++ b/client/core/src/com/cyberbot/bomberman/screens/ScreenState.java
@@ -4,4 +4,5 @@ public enum ScreenState {
GAME,
MENU,
LOBBY,
+ FINISH,
}
diff --git a/client/core/src/com/cyberbot/bomberman/screens/finish/FinishInteraction.java b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishInteraction.java
new file mode 100644
index 0000000..30869d6
--- /dev/null
+++ b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishInteraction.java
@@ -0,0 +1,5 @@
+package com.cyberbot.bomberman.screens.finish;
+
+public interface FinishInteraction {
+ void leaveFinish();
+}
diff --git a/client/core/src/com/cyberbot/bomberman/screens/finish/FinishLayout.java b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishLayout.java
new file mode 100644
index 0000000..4b91eda
--- /dev/null
+++ b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishLayout.java
@@ -0,0 +1,110 @@
+package com.cyberbot.bomberman.screens.finish;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Align;
+import com.badlogic.gdx.utils.viewport.Viewport;
+import com.cyberbot.bomberman.utils.Atlas;
+
+import java.util.List;
+
+public class FinishLayout extends Stage {
+
+ final Skin skin;
+ private final float spaceHeight = 14;
+
+ private final Label[] playerLabels;
+ private final FinishInteraction delegate;
+
+ private final float worldWidth = getViewport().getWorldWidth();
+ private final float worldHeight = getViewport().getWorldHeight();
+ private final float tableWidth = worldWidth / 3;
+ private final Skin skin2;
+
+ public FinishLayout(Viewport viewport, FinishInteraction delegate) {
+ super(viewport);
+ this.delegate = delegate;
+ this.playerLabels = new Label[4];
+ skin = new Skin(Gdx.files.internal("skins/clean-crispy/skin/clean-crispy-ui.json"));
+
+ FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("skins/8bit_regular.ttf"));
+ FreeTypeFontGenerator.FreeTypeFontParameter fontParams = new FreeTypeFontGenerator.FreeTypeFontParameter();
+ fontParams.size = 20;
+ BitmapFont font = generator.generateFont(fontParams);
+
+ this.skin2 = new Skin(Atlas.getSkinAtlas());
+ skin2.add("default_font", font);
+ skin2.load(Gdx.files.internal("skins/skin.json"));
+ }
+
+ public void createFinishUi() {
+ Table ui = new Table();
+ ui.setDebug(false);
+
+ ui.setPosition((worldWidth - tableWidth) / 2, 1);
+ ui.setWidth(tableWidth);
+ ui.setHeight(worldHeight);
+ addActor(ui);
+
+ Label title = new Label("Leaderboard", skin2);
+ title.setWidth(tableWidth);
+ title.setAlignment(1);
+ title.setFontScale(1.5f);
+ title.setWrap(false);
+ float playerLabelHeight = 6;
+ ui.add(title).width(tableWidth).height(playerLabelHeight).row();
+ ui.add().height(spaceHeight * 2).row();
+
+ for (int i = 0; i < 4; i++) {
+ Label label = new Label("", skin2);
+ label.setWidth(tableWidth);
+ label.setAlignment(Align.left);
+ label.setFontScale(1);
+ label.setWrap(false);
+ playerLabels[i] = label;
+ ui.add(label).width(tableWidth).height(playerLabelHeight).row();
+ ui.add().height(spaceHeight).row();
+ }
+ ui.add().height(spaceHeight).row();
+
+ TextButton leaveFinishButton = new TextButton("Leave", skin2);
+ leaveFinishButton.getLabel().setFontScale(0.85f);
+ setupButton(ui, tableWidth, leaveFinishButton);
+ leaveFinishButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ delegate.leaveFinish();
+ }
+ });
+ }
+
+ private void setupButton(Table table, float tableWidth, TextButton button) {
+ float buttonHeight = 30;
+ table.add(button).width(tableWidth - 10).height(buttonHeight).row();
+ table.add().height(spaceHeight).row();
+ }
+
+ public void updateScoreTable(List scoreTable) {
+ for (int i = 0; i < scoreTable.size(); i++) {
+ playerLabels[i].setText((i + 1) + ". " + scoreTable.get(i));
+ }
+ for (int i = 3; i > scoreTable.size() - 1; i--) {
+ playerLabels[i].setText("");
+ }
+ }
+
+ public void showError(String msg) {
+ Dialog dialog = new Dialog("Error", skin);
+ dialog.text(msg);
+ dialog.setMovable(false);
+ dialog.button("Ok");
+ dialog.key(Input.Keys.ENTER, true);
+ dialog.show(this);
+ }
+}
diff --git a/client/core/src/com/cyberbot/bomberman/screens/finish/FinishScreen.java b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishScreen.java
new file mode 100644
index 0000000..230b982
--- /dev/null
+++ b/client/core/src/com/cyberbot/bomberman/screens/finish/FinishScreen.java
@@ -0,0 +1,87 @@
+package com.cyberbot.bomberman.screens.finish;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.utils.viewport.FitViewport;
+import com.badlogic.gdx.utils.viewport.Viewport;
+import com.cyberbot.bomberman.screens.AbstractScreen;
+
+import java.util.List;
+
+public class FinishScreen extends AbstractScreen {
+ private final OrthographicCamera camera;
+ private final SpriteBatch batch;
+ private final Viewport viewport;
+
+ private final FinishLayout finishLayout;
+
+ public FinishScreen(FinishInteraction delegate) {
+
+ batch = new SpriteBatch();
+ camera = new OrthographicCamera();
+
+ camera.setToOrtho(false, 384, 216);
+ viewport = new FitViewport(384, 216);
+
+ finishLayout = new FinishLayout(viewport, delegate);
+ }
+
+ public void updateFinish(List table) {
+ finishLayout.updateScoreTable(table);
+ }
+
+ @Override
+ public void update(float delta) {
+ camera.update();
+
+ batch.setProjectionMatrix(camera.combined);
+ finishLayout.act(delta);
+ }
+
+ @Override
+ public void showError(String msg) {
+ finishLayout.showError(msg);
+ }
+
+ @Override
+ public void show() {
+ Gdx.input.setInputProcessor(finishLayout);
+ finishLayout.createFinishUi();
+ }
+
+ @Override
+ public void render(float delta) {
+ super.render(delta);
+
+ batch.begin();
+ batch.end();
+ finishLayout.draw();
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ viewport.update(width, height);
+ }
+
+ @Override
+ public void pause() {
+
+ }
+
+ @Override
+ public void resume() {
+
+ }
+
+ @Override
+ public void hide() {
+ finishLayout.clear();
+ }
+
+ @Override
+ public void dispose() {
+ finishLayout.dispose();
+ batch.dispose();
+ }
+}
diff --git a/client/core/src/com/cyberbot/bomberman/screens/hud/GameHud.java b/client/core/src/com/cyberbot/bomberman/screens/hud/GameHud.java
index ff70fd6..8b93ebc 100644
--- a/client/core/src/com/cyberbot/bomberman/screens/hud/GameHud.java
+++ b/client/core/src/com/cyberbot/bomberman/screens/hud/GameHud.java
@@ -127,13 +127,10 @@ public void addToPlayerList(String name, long id) {
playerListView.addPlayer(name, id);
}
- @Override
- public void onEntityAdded(Entity entity) { }
-
@Override
public void onEntityRemoved(Entity entity) {
- if(entity instanceof PlayerEntity && entity.getId() != localPlayerEntity.getId()) {
- playerListView.onPlayerDeath((PlayerEntity) entity);
+ if (entity instanceof PlayerEntity) {
+ playerListView.onPlayerDeath((PlayerEntity) entity); // Cast away to hell
}
}
}
diff --git a/client/core/src/com/cyberbot/bomberman/screens/hud/HealthBar.java b/client/core/src/com/cyberbot/bomberman/screens/hud/HealthBar.java
index c866cf3..ed9b483 100644
--- a/client/core/src/com/cyberbot/bomberman/screens/hud/HealthBar.java
+++ b/client/core/src/com/cyberbot/bomberman/screens/hud/HealthBar.java
@@ -20,9 +20,9 @@ public class HealthBar extends Actor {
private int visiblePlayerHealth;
- private final float HP_PER_SECOND = 100;
- private final int HEALTH_MEDIUM = 40;
- private final int HEALTH_LOW = 10;
+ private static final float HP_PER_SECOND = 100;
+ private static final int HEALTH_MEDIUM = 40;
+ private static final int HEALTH_LOW = 10;
private final LinkedList animationQueue;
private IntAction currentAnimation;
diff --git a/client/core/src/com/cyberbot/bomberman/screens/hud/InventoryButton.java b/client/core/src/com/cyberbot/bomberman/screens/hud/InventoryButton.java
index 12be5a1..c992ae9 100644
--- a/client/core/src/com/cyberbot/bomberman/screens/hud/InventoryButton.java
+++ b/client/core/src/com/cyberbot/bomberman/screens/hud/InventoryButton.java
@@ -1,69 +1,89 @@
package com.cyberbot.bomberman.screens.hud;
+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.Actor;
-import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Align;
import com.cyberbot.bomberman.core.models.items.ItemType;
+import com.cyberbot.bomberman.sprites.GraphicsFactory;
import com.cyberbot.bomberman.utils.Atlas;
public class InventoryButton extends Actor {
- protected ImageButton button;
- protected TextureRegionDrawable region;
ItemType type;
+ private int quantity;
- public InventoryButton(ItemType type) {
+ private final Stack mainWidget;
+ private final Label labelQuantity;
+
+ private final Button button;
+ private final TextureRegionDrawable region;
+
+ public InventoryButton(ItemType type, Skin skin) {
this.type = type;
+ quantity = 0;
region = new TextureRegionDrawable(Atlas.getSkinAtlas().findRegion("placeholder"));
- ImageButton.ImageButtonStyle buttonStyle = new ImageButton.ImageButtonStyle();
- buttonStyle.imageUp = region;
+ Button.ButtonStyle buttonStyle = new Button.ButtonStyle();
buttonStyle.checked = new TextureRegionDrawable(Atlas.getSkinAtlas().findRegion("button_checked"));
+ button = new Button(buttonStyle);
+
+ Label.LabelStyle style = new Label.LabelStyle();
+ style.font = skin.get("default_font", BitmapFont.class);
+ style.fontColor = skin.get("white", Color.class);
+ style.background = new TextureRegionDrawable(Atlas.getSkinAtlas().findRegion("label_background"));
+
+ labelQuantity = new Label(null, style);
+ labelQuantity.setFontScale(0.5f);
+
+ Container