From 36d70848e5b48872e6e6a8789129c9fd4122c22a Mon Sep 17 00:00:00 2001 From: Aehmttw Date: Sun, 22 Sep 2019 22:24:41 -0700 Subject: [PATCH] Tanks v0.7.2 - Added Versus Mode for parties, improved the party player list, and fixed tank health not updating in multiplayer --- src/main/java/lwjglwindow/FontRenderer.java | 40 +- src/main/java/lwjglwindow/LWJGLWindow.java | 14 +- src/main/java/tanks/Drawing.java | 11 + src/main/java/tanks/Game.java | 16 +- src/main/java/tanks/Level.java | 98 +++- src/main/java/tanks/LevelGeneratorVersus.java | 451 ++++++++++++++++++ src/main/java/tanks/Movable.java | 6 +- src/main/java/tanks/bullet/Bullet.java | 3 + src/main/java/tanks/bullet/BulletHealing.java | 4 + ...troyed.java => EventTankUpdateHealth.java} | 22 +- .../java/tanks/gui/screen/ScreenGame.java | 20 +- .../tanks/gui/screen/ScreenInterlevel.java | 12 + .../tanks/gui/screen/ScreenLevelBuilder.java | 23 +- .../tanks/gui/screen/ScreenPartyHost.java | 98 +++- .../tanks/gui/screen/ScreenPartyKick.java | 25 + .../tanks/gui/screen/ScreenPartyLobby.java | 99 +++- src/main/java/tanks/tank/Tank.java | 14 +- 17 files changed, 852 insertions(+), 104 deletions(-) create mode 100755 src/main/java/tanks/LevelGeneratorVersus.java rename src/main/java/tanks/event/{EventTankDestroyed.java => EventTankUpdateHealth.java} (55%) create mode 100644 src/main/java/tanks/gui/screen/ScreenPartyKick.java diff --git a/src/main/java/lwjglwindow/FontRenderer.java b/src/main/java/lwjglwindow/FontRenderer.java index ed2178e2..9f6d9b7b 100755 --- a/src/main/java/lwjglwindow/FontRenderer.java +++ b/src/main/java/lwjglwindow/FontRenderer.java @@ -1,6 +1,8 @@ package lwjglwindow; -public class FontRenderer +import org.lwjgl.opengl.GL11; + +public class FontRenderer { public LWJGLWindow home; String chars; @@ -23,7 +25,7 @@ public FontRenderer(LWJGLWindow h, String fontFile) this.image = fontFile; } - public int drawChar(double x, double y, double sX, double sY, char c) + public int drawChar(double x, double y, double z, double sX, double sY, char c) { int i = this.chars.indexOf(c); @@ -33,12 +35,14 @@ public int drawChar(double x, double y, double sX, double sY, char c) int col = i % 16; int row = i / 16; int width = charSizes[i]; - this.home.drawImage(x, y, sX, sY - 0.0001, col / 16f, row / 16f, (col + width / 8f) / 16f, (row + 1) / 16f, image, true); + this.home.drawImage(x, y, z, sX, sY - 0.0001, col / 16f, row / 16f, (col + width / 8f) / 16f, (row + 1) / 16f, image, true, false); return width; } - public void drawString(double x, double y, double sX, double sY, String s) + public void drawString(double x, double y, double z, double sX, double sY, String s) { + GL11.glEnable(GL11.GL_DEPTH_TEST); + double curX = x; char[] c = s.toCharArray(); @@ -57,7 +61,33 @@ else if (c[i] == '\u00A7') i += 12; } else - curX += (drawChar(curX, y, sX, sY, c[i]) + 1) * sX * 4; + curX += (drawChar(curX, y, z, sX, sY, c[i]) + 1) * sX * 4; + } + + GL11.glDisable(GL11.GL_DEPTH_TEST); + } + + public void drawString(double x, double y, double sX, double sY, String s) + { + double curX = x; + char[] c = s.toCharArray(); + + for (int i = 0; i < c.length; i++) + { + if (c[i] == '\u00C2') + continue; + else if (c[i] == '\u00A7') + { + int r = Integer.parseInt(c[i + 1] + "" + c[i + 2] + "" + c[i + 3]); + int g = Integer.parseInt(c[i + 4] + "" + c[i + 5] + "" + c[i + 6]); + int b = Integer.parseInt(c[i + 7] + "" + c[i + 8] + "" + c[i + 9]); + int a = Integer.parseInt(c[i + 10] + "" + c[i + 11] + "" + c[i + 12]); + this.home.setColor(r, g, b, a); + + i += 12; + } + else + curX += (drawChar(curX, y, 0, sX, sY, c[i]) + 1) * sX * 4; } } diff --git a/src/main/java/lwjglwindow/LWJGLWindow.java b/src/main/java/lwjglwindow/LWJGLWindow.java index 8cd26902..90c88dba 100755 --- a/src/main/java/lwjglwindow/LWJGLWindow.java +++ b/src/main/java/lwjglwindow/LWJGLWindow.java @@ -723,8 +723,13 @@ public void drawImage(double x, double y, double sX, double sY, double u1, doubl glMatrixMode(GL_PROJECTION); glDisable(GL_TEXTURE_2D); } - + public void drawImage(double x, double y, double z, double sX, double sY, double u1, double v1, double u2, double v2, String image, boolean scaled) + { + this.drawImage(x, y, z, sX, sY, u1, v1, u2, v2, image, scaled, true); + } + + public void drawImage(double x, double y, double z, double sX, double sY, double u1, double v1, double u2, double v2, String image, boolean scaled, boolean depthtest) { if (!textures.containsKey(image)) createImage(image); @@ -732,7 +737,8 @@ public void drawImage(double x, double y, double z, double sX, double sY, double glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glEnable(GL_DEPTH_TEST); + if (depthtest) + glEnable(GL_DEPTH_TEST); glFrustum(-absoluteWidth / (absoluteDepth * 2.0), absoluteWidth / (absoluteDepth * 2.0), absoluteHeight / (absoluteDepth * 2.0), -absoluteHeight / (absoluteDepth * 2.0), 1, absoluteDepth * 2); glTranslated(-absoluteWidth / 2, -absoluteHeight / 2, -absoluteDepth); @@ -768,6 +774,8 @@ public void drawImage(double x, double y, double z, double sX, double sY, double glMatrixMode(GL_PROJECTION); glDisable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); + + if (depthtest) + glDisable(GL_DEPTH_TEST); } } \ No newline at end of file diff --git a/src/main/java/tanks/Drawing.java b/src/main/java/tanks/Drawing.java index f41b4ca2..1a7c8ae0 100755 --- a/src/main/java/tanks/Drawing.java +++ b/src/main/java/tanks/Drawing.java @@ -361,6 +361,17 @@ public void drawText(double x, double y, String text) Game.game.window.fontRenderer.drawString(drawX, drawY, this.fontSize, this.fontSize, text); } + public void drawText(double x, double y, double z, String text) + { + double sizeX = Game.game.window.fontRenderer.getStringSizeX(this.fontSize, text) / scale; + double sizeY = Game.game.window.fontRenderer.getStringSizeY(this.fontSize, text) / scale; + + double drawX = (scale * (x + getPlayerOffsetX() - sizeX / 2) + Math.max(0, Panel.windowWidth - this.sizeX * scale) / 2); + double drawY = (scale * (y + getPlayerOffsetY() - sizeY / 2) + Math.max(0, Panel.windowHeight - statsHeight - this.sizeY * scale) / 2); + + Game.game.window.fontRenderer.drawString(drawX, drawY, z, this.fontSize, this.fontSize, text); + } + public void drawInterfaceText(double x, double y, String text) { double sizeX = Game.game.window.fontRenderer.getStringSizeX(this.fontSize, text); diff --git a/src/main/java/tanks/Game.java b/src/main/java/tanks/Game.java index aa786aea..c6d28a5b 100755 --- a/src/main/java/tanks/Game.java +++ b/src/main/java/tanks/Game.java @@ -59,8 +59,8 @@ public class Game public static double[][] tilesDepth = new double[28][18]; - public static final int network_protocol = 4; - public static final String version = "Tanks 0.7.1"; + public static final int network_protocol = 5; + public static final String version = "Tanks 0.7.2"; public static int port = 8080; @@ -146,7 +146,7 @@ public static void initScript() /* 15*/ NetworkEventMap.register(EventCreatePlayer.class); /* 16*/ NetworkEventMap.register(EventCreateTank.class); /* 17*/ NetworkEventMap.register(EventCreateCustomTank.class); - /* 18*/ NetworkEventMap.register(EventTankDestroyed.class); + /* 18*/ NetworkEventMap.register(EventTankUpdateHealth.class); /* 19*/ NetworkEventMap.register(EventShootBullet.class); /* 20*/ NetworkEventMap.register(EventLayMine.class); /* 21*/ NetworkEventMap.register(EventTankTeleport.class); @@ -324,7 +324,9 @@ public static void exit(String name) public static void exitToCrash(Exception e) { - if (ScreenPartyHost.isServer) + e.printStackTrace(); + + if (ScreenPartyHost.isServer && ScreenPartyHost.server != null) ScreenPartyHost.server.close("The party has ended because the host crashed"); if (ScreenPartyLobby.isClient) @@ -337,7 +339,6 @@ public static void exitToCrash(Exception e) belowEffects.clear(); movables.clear(); effects.clear(); - e.printStackTrace(); Game.crashMessage = e.toString(); Game.logger.println(new Date().toString() + " (syserr) the game has crashed! below is a crash report, good luck:"); e.printStackTrace(Game.logger); @@ -406,7 +407,7 @@ public static void loadLevel(File f) public static void loadLevel(File f, ScreenLevelBuilder s) { - Scanner in; + Scanner in = null; try { in = new Scanner(f); @@ -422,6 +423,9 @@ public static void loadLevel(File f, ScreenLevelBuilder s) { Game.exitToCrash(e); } + + if (in != null) + in.close(); } public static void start() diff --git a/src/main/java/tanks/Level.java b/src/main/java/tanks/Level.java index b984b70b..9cfada4c 100755 --- a/src/main/java/tanks/Level.java +++ b/src/main/java/tanks/Level.java @@ -6,7 +6,9 @@ import tanks.gui.Button; import tanks.gui.screen.ScreenGame; import tanks.gui.screen.ScreenLevelBuilder; +import tanks.gui.screen.ScreenParty; import tanks.gui.screen.ScreenPartyHost; +import tanks.network.Server; import tanks.network.ServerHandler; import tanks.obstacle.Obstacle; import tanks.registry.RegistryObstacle; @@ -39,8 +41,16 @@ public class Level public boolean remote = false; public HashMap teamsMap = new HashMap(); + public ArrayList teamsList = new ArrayList(); + public ArrayList availablePlayerSpawns = new ArrayList(); + + public ArrayList playerSpawnsX = new ArrayList(); + public ArrayList playerSpawnsY = new ArrayList(); + public ArrayList playerSpawnsAngle = new ArrayList(); + public ArrayList playerSpawnsTeam = new ArrayList(); + /** * A level string is structured like this: * (parentheses signify required parameters, and square brackets signify optional parameters. @@ -49,7 +59,7 @@ public class Level * {(SizeX),(SizeY),[(Red),(Green),(Blue)],[(RedNoise),(GreenNoise),(BlueNoise)]|[(ObstacleX)-(ObstacleY)]*|[(TankX)-(TankY)-(TankType)-[TankAngle]-[TeamName]]*|[(TeamName)-[FriendlyFire]-[(Red)-(Green)-(Blue)]]*} */ public Level(String level) - { + { this.levelString = level.replaceAll("\u0000", ""); preset = this.levelString.split("\\{")[1].split("}")[0].split("\\|"); @@ -339,32 +349,12 @@ public void run() if (team == Game.enemyTeam) team = Game.playerTeam; - if (ScreenPartyHost.isServer) - { - EventCreatePlayer local = new EventCreatePlayer(Game.clientID, Game.username, x, y, angle, team); - playerEvents.add(local); - Game.eventsOut.add(local); - - synchronized(ScreenPartyHost.server.connections) - { - for (ServerHandler c: ScreenPartyHost.server.connections) - { - if (c.clientID == null) - continue; - - EventCreatePlayer e = new EventCreatePlayer(c.clientID, c.rawUsername, x, y, angle, team); - playerEvents.add(e); - Game.eventsOut.add(e); - } - } - - continue; - } - else if (remote) - continue; + this.playerSpawnsX.add(x); + this.playerSpawnsY.add(y); + this.playerSpawnsAngle.add(angle); + this.playerSpawnsTeam.add(team); - t = new TankPlayer(x, y, angle, Game.clientID); - Game.player = (TankPlayer) t; + continue; } else { @@ -380,6 +370,62 @@ else if (remote) } } + this.availablePlayerSpawns.clear(); + + int playerCount = 1; + if (ScreenPartyHost.isServer && ScreenPartyHost.server != null) + playerCount += ScreenPartyHost.server.connections.size(); + + for (int i = 0; i < playerCount; i++) + { + if (this.availablePlayerSpawns.size() == 0) + { + for (int j = 0; j < this.playerSpawnsTeam.size(); j++) + { + this.availablePlayerSpawns.add(j); + } + } + + int spawn = this.availablePlayerSpawns.remove((int) (Math.random() * this.availablePlayerSpawns.size())); + + double x = this.playerSpawnsX.get(spawn); + double y = this.playerSpawnsY.get(spawn); + double angle = this.playerSpawnsAngle.get(spawn); + Team team = this.playerSpawnsTeam.get(spawn); + + if (ScreenPartyHost.isServer) + { + if (i == 0) + { + EventCreatePlayer local = new EventCreatePlayer(Game.clientID, Game.username, x, y, angle, team); + playerEvents.add(local); + Game.eventsOut.add(local); + } + else + { + synchronized (ScreenPartyHost.server.connections) + { + ServerHandler c = ScreenPartyHost.server.connections.get(i - 1); + + EventCreatePlayer e = new EventCreatePlayer(c.clientID, c.rawUsername, x, y, angle, team); + playerEvents.add(e); + Game.eventsOut.add(e); + } + } + + continue; + } + else if (remote) + continue; + else + { + Tank tank = new TankPlayer(x, y, angle, Game.clientID); + Game.player = (TankPlayer) tank; + tank.team = team; + Game.movables.add(tank); + } + } + for (EventCreatePlayer e: playerEvents) e.execute(); diff --git a/src/main/java/tanks/LevelGeneratorVersus.java b/src/main/java/tanks/LevelGeneratorVersus.java new file mode 100755 index 00000000..7032aaea --- /dev/null +++ b/src/main/java/tanks/LevelGeneratorVersus.java @@ -0,0 +1,451 @@ +package tanks; + +import tanks.gui.screen.ScreenPartyHost; + +import java.util.ArrayList; + +public class LevelGeneratorVersus +{ + public static String generateLevelString() + { + //int type = (int) (Math.random() * 13); + //test ^ + //String name = Game.registryTank.getRandomTank().name; + double size = Game.levelSize; + + int height = (int)(18 * size); + int width = (int)(28 * size); + double amountWalls = 12 * size * size; + double amountTanks = 8 * size * size; + + double random = Math.random(); + int walls = (int) (random * amountWalls + 4); + + int vertical = 2; + int horizontal = 2; + + int r = (int)(Math.random() * 50) + 185; + int g = (int)(Math.random() * 50) + 185; + int b = (int)(Math.random() * 50) + 185; + + boolean bouncy = Math.random() < 0.2; + double bouncyWeight = Math.random() * 0.5 + 0.2; + + boolean shrubs = Math.random() < 0.2; + int shrubCount = (int) (walls + Math.random() * 4 - 2); + + boolean teleporters = Math.random() < 0.2; + int numTeleporters = walls / 5 + 2; + + StringBuilder s = new StringBuilder("{" + width + "," + height + "," + r + "," + g + "," + b + ",20,20,20|"); + + boolean[][] cells = new boolean[width][height]; + double[][] cellWeights = new double[width][height]; + + ArrayList startPointsH = new ArrayList(); + ArrayList startPointsV = new ArrayList(); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + cellWeights[i][j] = 1; + } + } + + for (int i = 0; i < walls; i++) + { + int x = 0; + int y = 0; + int xEnd = 0; + int yEnd = 0; + int l = 1 + (int) Math.max(1, (Math.random() * (Math.min(height, width) - 3))); + + String type = ""; + + if (bouncy && Math.random() < bouncyWeight) + type = "-bouncy"; + else if (Math.random() < 0.5) + type = "-hard"; + else if (Math.random() < 0.25) + type = "-hole"; + + + if (Math.random() * (vertical + horizontal) < horizontal) + { + vertical++; + int rand; + Integer[] sp = null; + + if (Math.random() < 0.25 || startPointsH.isEmpty()) + { + for (int in = 0; in < 50; in++) + { + boolean chosen = false; + + while (!chosen) + { + x = (int) (Math.random() * (width - l)); + y = (int) (Math.random() * (height)); + xEnd = x + l; + yEnd = y; + + double weight = 0; + for (int x1 = x; x1 <= xEnd; x1++) + { + weight += cellWeights[x1][y]; + } + weight /= (xEnd - x + 1); + + if (Math.random() < weight) + chosen = true; + } + + boolean stop = false; + + for (int x1 = x - 2; x1 <= xEnd + 2; x1++) + { + for (int y1 = y - 2; y1 <= yEnd + 2; y1++) + { + if (cells[Math.max(0, Math.min(width-1, x1))][Math.max(0, Math.min(height-1, y1))]) + { + stop = true; + break; + } + } + + if (stop) + break; + } + + if (!stop) + break; + } + } + else + { + rand = (int) (Math.random() * startPointsH.size()); + x = startPointsH.get(rand)[0] + 1; + y = startPointsH.get(rand)[1]; + xEnd = x + l + 1; + yEnd = y; + sp = startPointsH.remove(rand); + + if ((Math.random() < 0.5 && x > 1) || x >= width) + { + xEnd -= l + 2; + x -= l + 2; + } + } + + x = Math.max(x, 0); + xEnd = Math.min(xEnd, width - 1); + + if (sp == null || sp[0] != x || sp[1] != y) + startPointsV.add(new Integer[]{x, y}); + + if (sp == null || sp[0] != xEnd || sp[1] != yEnd) + startPointsV.add(new Integer[]{xEnd, yEnd}); + + boolean started = false; + boolean stopped = false; + + for (int z = x; z <= xEnd; z++) + { + if (!cells[z][y]) + { + if (!started) + { + if (stopped) + { + s.append("-").append(y); + + s.append(type); + + s.append(","); + stopped = false; + } + + s.append(z).append("..."); + started = true; + } + } + else + { + if (started) + { + started = false; + stopped = true; + s.append(z - 1); + } + } + } + + if (started) + { + s.append(xEnd); + } + + if (started || stopped) + { + s.append("-").append(y); + + s.append(type); + + } + + for (int j = x; j <= xEnd; j++) + { + cells[j][y] = true; + } + + for (int j = Math.max(0, x - 5); j <= Math.min(xEnd + 5, width - 1); j++) + { + for (int k = Math.max(0, y - 5); k <= Math.min(yEnd + 5, height - 1); k++) + { + cellWeights[j][k] /= 2; + } + } + } + else + { + horizontal++; + int rand; + Integer[] sp = null; + + if (Math.random() < 0.25 || startPointsV.isEmpty()) + { + for (int in = 0; in < 50; in++) + { + boolean chosen = false; + + while (!chosen) + { + x = (int) (Math.random() * (width)); + y = (int) (Math.random() * (height - l)); + xEnd = x; + yEnd = y + l; + + double weight = 0; + for (int y1 = y; y1 <= yEnd; y1++) + { + weight += cellWeights[x][y1]; + } + weight /= (yEnd - y + 1); + + if (Math.random() < weight) + chosen = true; + } + + boolean stop = false; + + for (int x1 = x - 2; x1 <= xEnd + 2; x1++) + { + for (int y1 = y - 2; y1 <= yEnd + 2; y1++) + { + if (cells[Math.max(0, Math.min(width - 1, x1))][Math.max(0, Math.min(height - 1, y1))]) + { + stop = true; + break; + } + } + + if (stop) + break; + } + + if (!stop) + break; + } + } + else + { + rand = (int) (Math.random() * startPointsV.size()); + x = startPointsV.get(rand)[0]; + y = startPointsV.get(rand)[1] + 1; + xEnd = x; + yEnd = y + l + 1; + sp = startPointsV.remove(rand); + + if ((Math.random() < 0.5 && y > 1) || y >= height) + { + yEnd -= l + 2; + y -= l + 2; + } + } + + y = Math.max(y, 0); + yEnd = Math.min(yEnd, height - 1); + + if (sp == null || sp[0] != x || sp[1] != y) + startPointsH.add(new Integer[]{x, y}); + + if (sp == null || sp[0] != xEnd || sp[1] != yEnd) + startPointsH.add(new Integer[]{xEnd, yEnd}); + + boolean started = false; + boolean stopped = false; + + for (int z = y; z <= yEnd; z++) + { + if (!cells[x][z]) + { + if (!started) + { + if (stopped) + { + s.append(type); + + s.append(","); + stopped = false; + } + + s.append(x).append("-").append(z).append("..."); + started = true; + } + } + else + { + if (started) + { + s.append(z - 1); + started = false; + stopped = true; + } + } + } + + if (started) + { + s.append(yEnd); + } + + if (started || stopped) + { + s.append(type); + } + + for (int j = y; j <= yEnd; j++) + { + cells[x][j] = true; + } + + for (int j = Math.max(0, x - 5); j <= Math.min(xEnd + 5, width - 1); j++) + { + for (int k = Math.max(0, y - 5); k <= Math.min(yEnd + 5, height - 1); k++) + { + cellWeights[j][k] /= 2; + } + } + } + + if (i < walls - 1) + { + if (!s.toString().endsWith(",")) + s.append(","); + } + } + + if (shrubs) + { + for (int j = 0; j < shrubCount; j++) + { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + + for (int i = 0; i < Math.random() * 20 + 4; i++) + { + if (x < width && y < height && x > 0 && y > 0 && !cells[x][y]) + { + cells[x][y] = true; + + if (!s.toString().endsWith(",")) + s.append(","); + + s.append(x).append("-").append(y).append("-shrub"); + } + + double rand = Math.random(); + + if (rand < 0.25) + x++; + else if (rand < 0.5) + x--; + else if (rand < 0.75) + y++; + else + y--; + } + } + } + + if (teleporters) + { + int n = numTeleporters; + while (n > 0) + { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + if (!cells[x][y]) + { + for (int i = Math.max(x - 2, 0); i <= Math.min(x + 2, width - 1); i++) + for (int j = Math.max(y - 2, 0); j <= Math.min(y + 2, height - 1); j++) + cells[i][j] = true; + + if (!s.toString().endsWith(",")) + s.append(","); + + s.append(x).append("-").append(y).append("-teleporter"); + n--; + } + } + } + + s.append("|"); + + int numTanks = ScreenPartyHost.server.connections.size() + 1; + + int x = (int) (Math.random() * (width)); + int y = (int) (Math.random() * (height)); + while (cells[x][y]) + { + x = (int) (Math.random() * (width)); + y = (int) (Math.random() * (height)); + } + for (int i = -2; i <= 2; i++) + for (int j = -2; j <= 2; j++) + cells[Math.max(0, Math.min(width - 1, x+i))][Math.max(0, Math.min(height - 1, y+j))] = true; + + for (int i = 0; i < numTanks; i++) + { + int angle = (int) (Math.random() * 4); + x = (int) (Math.random() * (width)); + y = (int) (Math.random() * (height)); + while (cells[x][y]) + { + x = (int) (Math.random() * (width)); + y = (int) (Math.random() * (height)); + } + for (int a = -1; a <= 1; a++) + for (int j = -2; j <= 1; j++) + cells[Math.max(0, Math.min(width - 1, x+a))][Math.max(0, Math.min(height - 1, y+j))] = true; + + s.append(x).append("-").append(y).append("-"); + s.append("player"); + s.append("-").append(angle); + + if (i == numTanks - 1) + { + s.append("|ally-true}"); + } + else + { + s.append(","); + } + } + + return s.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/tanks/Movable.java b/src/main/java/tanks/Movable.java index f0b4cd82..89edfdab 100755 --- a/src/main/java/tanks/Movable.java +++ b/src/main/java/tanks/Movable.java @@ -15,8 +15,7 @@ public abstract class Movable implements IDrawableForInterface public double vZ = 0; public double cooldown = 0; public boolean destroy = false; - public boolean destroyNextFrame = false; - + public int drawLevel = 3; //public boolean drawBelow = false; //public boolean drawAbove = false; @@ -76,9 +75,6 @@ public void update() this.canHide = false; } - - if (this.destroyNextFrame) - this.destroy = true; } public void setMotionInDirection(double x, double y, double velocity) diff --git a/src/main/java/tanks/bullet/Bullet.java b/src/main/java/tanks/bullet/Bullet.java index 1d614b27..cd277335 100755 --- a/src/main/java/tanks/bullet/Bullet.java +++ b/src/main/java/tanks/bullet/Bullet.java @@ -1,6 +1,7 @@ package tanks.bullet; import tanks.*; +import tanks.event.EventTankUpdateHealth; import tanks.hotbar.ItemBullet; import tanks.obstacle.Obstacle; import tanks.tank.Mine; @@ -112,6 +113,8 @@ public void collidedWithTank(Tank t) t.lives -= this.damage; + Game.eventsOut.add(new EventTankUpdateHealth(t)); + if (t.lives <= 0) { t.flashAnimation = 0; diff --git a/src/main/java/tanks/bullet/BulletHealing.java b/src/main/java/tanks/bullet/BulletHealing.java index 112ece5c..79e57e58 100755 --- a/src/main/java/tanks/bullet/BulletHealing.java +++ b/src/main/java/tanks/bullet/BulletHealing.java @@ -3,6 +3,7 @@ import tanks.*; import tanks.AttributeModifier.Operation; import tanks.event.EventShootBullet; +import tanks.event.EventTankUpdateHealth; import tanks.gui.screen.ScreenGame; import tanks.hotbar.ItemBullet; import tanks.tank.Tank; @@ -72,6 +73,9 @@ public void collidedWithTank(Tank t) this.destroy = true; t.lives = Math.min(t.baseLives + 1, t.lives - this.damage); + + Game.eventsOut.add(new EventTankUpdateHealth(t)); + t.attributes.add(new AttributeModifier("healray", "healray", Operation.add, 1.0)); } diff --git a/src/main/java/tanks/event/EventTankDestroyed.java b/src/main/java/tanks/event/EventTankUpdateHealth.java similarity index 55% rename from src/main/java/tanks/event/EventTankDestroyed.java rename to src/main/java/tanks/event/EventTankUpdateHealth.java index a193691c..22328005 100755 --- a/src/main/java/tanks/event/EventTankDestroyed.java +++ b/src/main/java/tanks/event/EventTankUpdateHealth.java @@ -3,18 +3,20 @@ import io.netty.buffer.ByteBuf; import tanks.tank.Tank; -public class EventTankDestroyed implements INetworkEvent +public class EventTankUpdateHealth implements INetworkEvent { public int tank; + public double health; - public EventTankDestroyed() + public EventTankUpdateHealth() { } - public EventTankDestroyed(Tank t) + public EventTankUpdateHealth(Tank t) { tank = t.networkID; + health = t.lives; } @Override @@ -24,25 +26,23 @@ public void execute() if (t == null) return; - t.destroyNextFrame = true; - t.lives = 0; - - if (!Tank.freeIDs.contains(tank)) - { - Tank.freeIDs.add(tank); - Tank.idMap.remove(tank); - } + if (t.lives > health && health > 0) + t.flashAnimation = 1; + + t.lives = health; } @Override public void write(ByteBuf b) { b.writeInt(this.tank); + b.writeDouble(this.health); } @Override public void read(ByteBuf b) { this.tank = b.readInt(); + this.health = b.readDouble(); } } diff --git a/src/main/java/tanks/gui/screen/ScreenGame.java b/src/main/java/tanks/gui/screen/ScreenGame.java index b97ad1cf..26f5a5cd 100755 --- a/src/main/java/tanks/gui/screen/ScreenGame.java +++ b/src/main/java/tanks/gui/screen/ScreenGame.java @@ -40,6 +40,8 @@ public class ScreenGame extends Screen public boolean ready = false; + public static boolean versus = false; + @SuppressWarnings("unchecked") protected ArrayList[] drawables = (ArrayList[])(new ArrayList[10]); @@ -160,7 +162,14 @@ public void run() playing = false; Game.startTime = 400; paused = false; - Game.reset(); + + if (versus) + { + Game.cleanUp(); + new Level(LevelGeneratorVersus.generateLevelString()).loadLevel(); + } + else + Game.reset(); if (ScreenPartyHost.isServer) { @@ -226,7 +235,7 @@ public void run() } ); - Button quitPartyGame = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 60, 350, 40, "Quit to title", new Runnable() + Button quitPartyGame = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 60, 350, 40, "Back to party", new Runnable() { @Override public void run() @@ -236,6 +245,7 @@ public void run() Game.screen = ScreenPartyHost.activeScreen; ScreenPartyHost.readyPlayers.clear(); Game.eventsOut.add(new EventReturnToLobby()); + versus = false; } } ); @@ -520,7 +530,7 @@ else if (ScreenInterlevel.tutorial) if (!this.shop.isEmpty()) enterShop.update(); - if (Game.autostart && !cancelCountdown) + if ((ScreenPartyHost.isServer || ScreenPartyLobby.isClient || Game.autostart) && !cancelCountdown) Game.startTime -= Panel.frameFrequency; if (!ScreenPartyHost.isServer && !ScreenPartyLobby.isClient) @@ -617,6 +627,8 @@ else if (!aliveTeams.contains(m.team)) if (aliveTeams.size() <= 1) { + versus = false; + ScreenGame.finished = true; Game.bulletLocked = true; @@ -791,7 +803,7 @@ public void draw() if (ScreenPartyHost.isServer && this.cancelCountdown) startNow.draw(); - if (Game.autostart && !cancelCountdown) + if ((ScreenPartyHost.isServer || ScreenPartyLobby.isClient || Game.autostart) && !cancelCountdown) { Drawing.drawing.setColor(127, 127, 127); Drawing.drawing.fillInterfaceRect(Drawing.drawing.interfaceSizeX - 200, Drawing.drawing.interfaceSizeY - 35, 320, 3); diff --git a/src/main/java/tanks/gui/screen/ScreenInterlevel.java b/src/main/java/tanks/gui/screen/ScreenInterlevel.java index 420d646c..8ca3b4ad 100755 --- a/src/main/java/tanks/gui/screen/ScreenInterlevel.java +++ b/src/main/java/tanks/gui/screen/ScreenInterlevel.java @@ -119,6 +119,18 @@ public void run() } ); + Button newLevelVersus = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 90, 350, 40, "Generate a new level", new Runnable() + { + @Override + public void run() + { + Game.cleanUp(); + new Level(LevelGeneratorVersus.generateLevelString()).loadLevel(); + Game.screen = new ScreenGame(); + } + } + ); + Button nextLevel = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 90, 350, 40, "Next level", new Runnable() { @Override diff --git a/src/main/java/tanks/gui/screen/ScreenLevelBuilder.java b/src/main/java/tanks/gui/screen/ScreenLevelBuilder.java index 0233b072..f7ffb8b3 100755 --- a/src/main/java/tanks/gui/screen/ScreenLevelBuilder.java +++ b/src/main/java/tanks/gui/screen/ScreenLevelBuilder.java @@ -611,7 +611,7 @@ public void run() colorVarRed.maxValue = 255 - r; colorVarRed.performValueCheck(); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -637,7 +637,7 @@ public void run() colorVarGreen.maxValue = 255 - g; colorVarGreen.performValueCheck(); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -663,7 +663,7 @@ public void run() colorVarBlue.maxValue = 255 - b; colorVarBlue.performValueCheck(); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -686,7 +686,7 @@ public void run() dr = Integer.parseInt(colorVarRed.inputText); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -708,7 +708,7 @@ public void run() dg = Integer.parseInt(colorVarGreen.inputText); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -730,7 +730,7 @@ public void run() db = Integer.parseInt(colorVarBlue.inputText); - reload(); + reload(true); ((ScreenLevelBuilder)Game.screen).colorMenu = true; } @@ -1062,6 +1062,9 @@ else if (this.mouseTankOrientation == 2) if (currentPlaceable == Placeable.playerTank) { + if (this.playerTeamNum >= this.teams.size()) + this.playerTeamNum = 0; + this.selectTeam.text = "Team: " + this.teams.get(this.playerTeamNum).name; this.selectTeam.update(); this.rotateTankButton.update(); @@ -1676,6 +1679,11 @@ else if (!obstacles[h][i][j + yLength]) } public void reload() + { + reload(false); + } + + public void reload(boolean colorChange) { save(); @@ -1705,7 +1713,7 @@ public void reload() ((Tank) m).drawAge = Game.tank_size; } - if (sX == Game.currentSizeX && sY == Game.currentSizeY) + if (!colorChange && sX == Game.currentSizeX && sY == Game.currentSizeY) { Game.tilesR = r; Game.tilesG = g; @@ -1889,6 +1897,7 @@ else if (this.colorMenu) this.colorVarRed.draw(); this.colorVarGreen.draw(); this.colorVarBlue.draw(); + Drawing.drawing.setColor(0, 0, 0); Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 150, "Background colors"); this.back2.draw(); } diff --git a/src/main/java/tanks/gui/screen/ScreenPartyHost.java b/src/main/java/tanks/gui/screen/ScreenPartyHost.java index 32eec49d..4d06e40c 100755 --- a/src/main/java/tanks/gui/screen/ScreenPartyHost.java +++ b/src/main/java/tanks/gui/screen/ScreenPartyHost.java @@ -1,8 +1,6 @@ package tanks.gui.screen; -import tanks.Drawing; -import tanks.Game; -import tanks.Panel; +import tanks.*; import tanks.event.EventPlayerChat; import tanks.gui.Button; import tanks.gui.ChatBox; @@ -24,6 +22,13 @@ public class ScreenPartyHost extends Screen implements IPartyMenuScreen public static ScreenPartyHost activeScreen; public String ip = ""; + public int usernamePage = 0; + + public static int entries_per_page = 10; + public static int username_spacing = 30; + public static int username_y_offset = -120; + + public static SynchronizedList chat = new SynchronizedList(); public static ChatBox chatbox = new ChatBox(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY - 30, 1380, 40, GLFW.GLFW_KEY_T, @@ -49,7 +54,45 @@ public void run() } , "Generate a random level to play"); - Button crusades = new Button(Drawing.drawing.interfaceSizeX / 2 + 190, Drawing.drawing.interfaceSizeY / 2 - 30, 350, 40, "Crusades", "Crusades are not yet---supported in party mode"); + Button nextUsernamePage = new Button(Drawing.drawing.interfaceSizeX / 2 - 190, + Drawing.drawing.interfaceSizeY / 2 + username_y_offset + username_spacing * (1 + entries_per_page), 300, 30, "Next page", new Runnable() + { + @Override + public void run() + { + usernamePage++; + } + } + ); + + Button previousUsernamePage = new Button(Drawing.drawing.interfaceSizeX / 2 - 190, Drawing.drawing.interfaceSizeY / 2 + username_y_offset, + 300, 30, "Previous page", new Runnable() + { + @Override + public void run() + { + usernamePage--; + } + } + ); + + Button versus = new Button(Drawing.drawing.interfaceSizeX / 2 + 190, Drawing.drawing.interfaceSizeY / 2 - 30, 350, 40, "Versus", new Runnable() + { + @Override + public void run() + { + Game.cleanUp(); + String s = LevelGeneratorVersus.generateLevelString(); + Level l = new Level(s); + l.loadLevel(); + ScreenGame.versus = true; + + Game.screen = new ScreenGame(); + } + } + , "Fight other players in this party---in a randomly generated level"); + + Button crusades = new Button(Drawing.drawing.interfaceSizeX / 2 + 190, Drawing.drawing.interfaceSizeY / 2 + 90, 350, 40, "Crusades", "Crusades are not yet---supported in party mode"); Button myLevels = new Button(Drawing.drawing.interfaceSizeX / 2 + 190, Drawing.drawing.interfaceSizeY / 2 + 30, 350, 40, "My levels", new Runnable() { @@ -59,7 +102,7 @@ public void run() Game.screen = new ScreenPlaySavedLevels(); } } - , "Play levels you have created!"); + , "Play levels you have created"); Button quit = new Button(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 + 300, 350, 40, "End party", new Runnable() { @@ -130,8 +173,18 @@ public void update() newLevel.update(); crusades.update(); myLevels.update(); + versus.update(); quit.update(); + if (server != null && server.connections != null) + { + if (this.usernamePage > 0) + this.previousUsernamePage.update(); + + if ((this.usernamePage + 1) * 10 < server.connections.size()) + this.nextUsernamePage.update(); + } + chatbox.update(); } @@ -140,10 +193,10 @@ public void draw() { this.drawDefaultBackground(); - myLevels.draw(); crusades.draw(); newLevel.draw(); + versus.draw(); quit.draw(); chatbox.draw(); @@ -167,21 +220,36 @@ public void draw() } } - String n = Game.username; - if (Game.enableChatFilter) - n = Game.chatFilter.filterChat(n); + if (server != null && server.connections != null) + { + if (this.usernamePage > 0) + this.previousUsernamePage.draw(); - Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2 - 190, Drawing.drawing.interfaceSizeY / 2 - 120, n); + if ((this.usernamePage + 1) * entries_per_page < server.connections.size()) + this.nextUsernamePage.draw(); + if (this.usernamePage <= 0) + { + String n = Game.username; + if (Game.enableChatFilter) + n = Game.chatFilter.filterChat(n); - if (server != null && server.connections != null) - { - //synchronized(server.connections) + n = "\u00A7000127255255" + n; + + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2 - 190, Drawing.drawing.interfaceSizeY / 2 + username_y_offset, n); + } + + if (server.connections != null) { - for (int i = 0; i < server.connections.size(); i++) + for (int i = this.usernamePage * entries_per_page; i < Math.min(((this.usernamePage + 1) * entries_per_page), server.connections.size()); i++) { if (server.connections.get(i).username != null) - Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2 - 190, Drawing.drawing.interfaceSizeY / 2 + (i + 1) * 30 - 120, server.connections.get(i).username); + { + Drawing.drawing.setColor(0, 0, 0); + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2 - 190, + Drawing.drawing.interfaceSizeY / 2 + (1 + i - this.usernamePage * entries_per_page) * username_spacing + username_y_offset, + server.connections.get(i).username); + } } } } diff --git a/src/main/java/tanks/gui/screen/ScreenPartyKick.java b/src/main/java/tanks/gui/screen/ScreenPartyKick.java new file mode 100644 index 00000000..549fb582 --- /dev/null +++ b/src/main/java/tanks/gui/screen/ScreenPartyKick.java @@ -0,0 +1,25 @@ +package tanks.gui.screen; + +import tanks.network.ServerHandler; + +public class ScreenPartyKick extends Screen implements IPartyMenuScreen +{ + public ServerHandler handler; + + public ScreenPartyKick(ServerHandler h) + { + handler = h; + } + + @Override + public void update() + { + + } + + @Override + public void draw() + { + + } +} diff --git a/src/main/java/tanks/gui/screen/ScreenPartyLobby.java b/src/main/java/tanks/gui/screen/ScreenPartyLobby.java index ec6438f3..ac9229e6 100755 --- a/src/main/java/tanks/gui/screen/ScreenPartyLobby.java +++ b/src/main/java/tanks/gui/screen/ScreenPartyLobby.java @@ -12,6 +12,7 @@ import org.lwjgl.glfw.GLFW; import java.util.ArrayList; +import java.util.UUID; public class ScreenPartyLobby extends Screen { @@ -21,6 +22,13 @@ public class ScreenPartyLobby extends Screen public static ArrayList chat = new ArrayList(); + public int usernamePage = 0; + + public static int entries_per_page = 10; + public static int username_spacing = 30; + public static int username_y_offset = -230; + public static int username_x_offset = 0; + public static ChatBox chatbox = new ChatBox(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY - 30, 1380, 40, GLFW.GLFW_KEY_T, "\u00A7127127127255Click here or press 'T' to send a chat message", new Runnable() { @@ -44,45 +52,98 @@ public void run() } } ); + + Button nextUsernamePage = new Button(Drawing.drawing.interfaceSizeX / 2 + username_x_offset, + Drawing.drawing.interfaceSizeY / 2 + username_y_offset + username_spacing * (1 + entries_per_page), 300, 30, "Next page", new Runnable() + { + @Override + public void run() + { + usernamePage++; + } + } + ); + + Button previousUsernamePage = new Button(Drawing.drawing.interfaceSizeX / 2 + username_x_offset, Drawing.drawing.interfaceSizeY / 2 + username_y_offset, + 300, 30, "Previous page", new Runnable() + { + @Override + public void run() + { + usernamePage--; + } + } + ); @Override public void update() { exit.update(); + + if (this.usernamePage > 0) + this.previousUsernamePage.update(); + + if ((this.usernamePage + 1) * 10 < connections.size()) + this.nextUsernamePage.update(); + chatbox.update(); } @Override - public void draw() + public void draw() { - this.drawDefaultBackground(); + this.drawDefaultBackground(); Drawing.drawing.setColor(0, 0, 0); Drawing.drawing.setInterfaceFontSize(24); - + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 2 - 400, Panel.winlose); - + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 4 - 40, "Players in this party:"); - for (int i = 0; i < connections.size(); i++) + if (connections != null) { - Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2, Drawing.drawing.interfaceSizeY / 4 + i * 30, connections.get(i).username); - } - - long time = System.currentTimeMillis(); - for (int i = 0; i < chat.size(); i++) - { - ChatMessage c = chat.get(i); - if (time - c.time <= 30000 || chatbox.selected) + if (this.usernamePage > 0) + this.previousUsernamePage.draw(); + + if ((this.usernamePage + 1) * entries_per_page < connections.size()) + this.nextUsernamePage.draw(); + + if (connections != null) + { + for (int i = this.usernamePage * entries_per_page; i < Math.min(((this.usernamePage + 1) * entries_per_page), connections.size()); i++) + { + if (connections.get(i).username != null) + { + String n = connections.get(i).username; + if (connections.get(i).clientId.equals(Game.clientID)) + n = "\u00A7000127255255" + n; + else if (i == 0) + n = "\u00A7000200000255" + n; + + Drawing.drawing.setColor(0, 0, 0); + Drawing.drawing.drawInterfaceText(Drawing.drawing.interfaceSizeX / 2 + username_x_offset, + Drawing.drawing.interfaceSizeY / 2 + (1 + i - this.usernamePage * entries_per_page) * username_spacing + username_y_offset, + n); + } + } + } + + long time = System.currentTimeMillis(); + for (int i = 0; i < chat.size(); i++) { - Drawing.drawing.setColor(0, 0, 0); - Drawing.drawing.drawInterfaceText(20, Drawing.drawing.interfaceSizeY - i * 30 - 70, c.message, false); + ChatMessage c = chat.get(i); + if (time - c.time <= 30000 || chatbox.selected) + { + Drawing.drawing.setColor(0, 0, 0); + Drawing.drawing.drawInterfaceText(20, Drawing.drawing.interfaceSizeY - i * 30 - 70, c.message, false); + } } + + + exit.draw(); + chatbox.draw(); } - - - exit.draw(); - chatbox.draw(); } } diff --git a/src/main/java/tanks/tank/Tank.java b/src/main/java/tanks/tank/Tank.java index aa5e79cf..984e1190 100755 --- a/src/main/java/tanks/tank/Tank.java +++ b/src/main/java/tanks/tank/Tank.java @@ -1,7 +1,7 @@ package tanks.tank; import tanks.*; -import tanks.event.EventTankDestroyed; +import tanks.event.EventTankUpdateHealth; import tanks.event.EventTankUpdate; import tanks.obstacle.Obstacle; @@ -255,7 +255,8 @@ public void update() if (!freeIDs.contains(this.networkID)) { if (!this.isRemote) - Game.eventsOut.add(new EventTankDestroyed(this)); + Game.eventsOut.add(new EventTankUpdateHealth(this)); + freeIDs.add(this.networkID); idMap.remove(this.networkID); } @@ -319,6 +320,9 @@ public void update() Game.eventsOut.add(new EventTankUpdate(this)); super.update(); + + if (this.lives <= 0) + this.destroy = true; } @Override @@ -468,7 +472,11 @@ public void draw() public void drawName() { Drawing.drawing.setFontSize(20); - Drawing.drawing.drawText(this.posX, this.posY + 35, this.name); + + if (Game.enable3d) + Drawing.drawing.drawText(this.posX, this.posY + 35, this.size / 2, this.name); + else + Drawing.drawing.drawText(this.posX, this.posY + 35, this.name); } public void drawOutline()