package slimpleslickgame; import java.util.concurrent.ConcurrentHashMap; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; import org.newdawn.slick.geom.Vector2f; import org.newdawn.slick.state.BasicGameState; import org.newdawn.slick.state.StateBasedGame; import util.EventProtocol; import client.ByteMonitor; import client.Client; import client.GameStatsEvents; public class Game extends BasicGameState { public static final int ID = 2; private GameContainer gc; private ByteMonitor bm; private ConcurrentHashMap<Byte, GameInstance> instances; private GameStatsEvents gse; private Vector2f boardSize; private boolean gameStarted; private boolean gameOver; private byte winnerID; public void addGSM(GameStatsEvents gse, ByteMonitor byteMonitor) { this.bm = byteMonitor; this.gse = gse; } @Override public void init(GameContainer gc, StateBasedGame arg1) throws SlickException { this.gc = gc; this.boardSize = new Vector2f(gc.getWidth() / 4, gc.getHeight()); instances = new ConcurrentHashMap<Byte, GameInstance>(); gameStarted = false; gameOver = false; } @Override public void render(GameContainer gc, StateBasedGame arg1, Graphics g) throws SlickException { if (gameStarted) { if (gameOver) { g.drawString("Player " + winnerID + " WINS!", (Client.WIDTH / 2) - 50, (Client.HEIGHT / 2) + 100); g.drawString("GAME IS OVER, PRESS ENTER TO EXIT", (Client.WIDTH / 2) - 150, (Client.HEIGHT / 2) + 200); } else { for (GameInstance gi : instances.values()) { gi.render(g); } } } else { int th = g.getFont().getLineHeight(); int tw = 100; int buttonSize = 50; // Game Info g.drawRect((Client.WIDTH / 2) + tw - buttonSize, (Client.HEIGHT / 3) - 2 * buttonSize - 6, 3 * tw, 2 * tw + buttonSize + 6); g.drawString("Protect home from invaders " + "\n-HP decrease on enemy passing by" + "\n-Freeze on enemy collision" + "\n\nSending creeps:" + "\n-1 key 1 creep "+Stats.CREEP_PRICE_1 +" credits" + "\n-2 key 5 creeps "+Stats.CREEP_PRICE_5+" credits" + "\n-3 key 10 creeps "+Stats.CREEP_PRICE_10+" credits" + "\n\nUpgrading ship cost 750 credits:" + "\n-Fire rate increase" + "\n-Income increase", (Client.WIDTH / 2) + tw - buttonSize + 6, (Client.HEIGHT / 3) - 2 * buttonSize); // Controller rectangle g.drawRect((Client.WIDTH / 2) - 4 * tw - 6, (Client.HEIGHT / 3) - 2 * buttonSize - 6, 4 * tw + 30, 2 * tw + buttonSize + 6); // 1 key g.drawRect((Client.WIDTH / 2) - 4 * tw, (Client.HEIGHT / 3) - 2 * buttonSize + 6, buttonSize, buttonSize); g.drawString("1", ((Client.WIDTH + buttonSize / 3) / 2) - 4 * tw, ((Client.HEIGHT + buttonSize / 2) / 3) - 2 * buttonSize + 6); // 2 key g.drawRect((Client.WIDTH / 2) - 4 * tw + buttonSize + 6, (Client.HEIGHT / 3) - 2 * buttonSize + 6, buttonSize, buttonSize); g.drawString("2", ((Client.WIDTH + buttonSize / 3) / 2) - 4 * tw + buttonSize + 6, ((Client.HEIGHT + buttonSize / 2) / 3) - 2 * buttonSize + 6); // 3 key g.drawRect((Client.WIDTH / 2) - 4 * tw + 2 * (buttonSize + 6), (Client.HEIGHT / 3) - 2 * buttonSize + 6, buttonSize, buttonSize); g.drawString("3", ((Client.WIDTH + buttonSize / 3) / 2) - 4 * tw + 2 * (buttonSize + 6), ((Client.HEIGHT + buttonSize / 2) / 3) - 2 * buttonSize + 6); // 123 description g.drawString("Send creeps to \nother players", (Client.WIDTH / 2) - 4 * tw, (Client.HEIGHT / 3) - buttonSize + 6); // Z key g.drawRect((Client.WIDTH / 2) - 4 * tw, (Client.HEIGHT / 3) + buttonSize + 6, buttonSize, buttonSize); g.drawString("Z", ((Client.WIDTH + buttonSize / 2) / 2) - 4 * tw, ((Client.HEIGHT + buttonSize / 2) / 3) + buttonSize + 6); g.drawString("Upgrade \nship", (Client.WIDTH / 2) - 4 * tw, (Client.HEIGHT / 3) + 2 * buttonSize + 6); // Space g.drawRect((Client.WIDTH / 2) - 4 * tw + buttonSize + 35, (Client.HEIGHT / 3) + buttonSize + 6, 3 * buttonSize, buttonSize); g.drawString("Shoot", (Client.WIDTH / 2) - 4 * tw + buttonSize + 35, (Client.HEIGHT / 3) + 2 * buttonSize + 6); // Left arrow g.drawRect((Client.WIDTH / 2) - 3 * tw + 3 * buttonSize + 6, (Client.HEIGHT / 3) + buttonSize + 6, buttonSize, buttonSize); g.drawString("Left", ((Client.WIDTH + buttonSize / 3) / 2) - 3 * tw + 3 * buttonSize + 6, ((Client.HEIGHT + buttonSize / 2) / 3) + buttonSize + 6); // Keys up/down g.drawRect((Client.WIDTH / 2) - 3 * tw + 4 * buttonSize + 2 * 6, (Client.HEIGHT / 3), buttonSize, buttonSize); g.drawRect((Client.WIDTH / 2) - 3 * tw + 4 * buttonSize + 2 * 6, (Client.HEIGHT / 3) + buttonSize + 6, buttonSize, buttonSize); // Right arrow g.drawRect((Client.WIDTH / 2) - 3 * tw + 5 * buttonSize + 3 * 6, (Client.HEIGHT / 3) + buttonSize + 6, buttonSize, buttonSize); g.drawString("Right", (Client.WIDTH / 2) - 3 * tw + 5 * buttonSize + 3 * 6 + 3, ((Client.HEIGHT + buttonSize / 2) / 3) + buttonSize + 6); // Arrow description g.drawString("Navigate ship", (Client.WIDTH / 2) - 3 * tw + 3 * buttonSize + 6, (Client.HEIGHT / 3) + 2 * buttonSize + 6); // START GAME g.drawString("PRESS ENTER TO START GAME\nPlayers in game: " + instances.size(), (Client.WIDTH / 2) - tw, (2 * Client.HEIGHT / 3) - th - buttonSize); } } @Override public void update(GameContainer gc, StateBasedGame arg1, int delta) throws SlickException { if (gameStarted) { if (gameOver) { if (gc.getInput().isKeyPressed(Input.KEY_ENTER)) { System.exit(0); } } else { int totalP = 0; int deadP = 0; for (GameInstance gi : instances.values()) { if (gi.isPlayerDead()) { deadP++; } else { winnerID = gi.getPlayerId(); } totalP++; } gameOver = (deadP >= (totalP - 1)); for (GameInstance gi : instances.values()) { gi.update(delta); } } } else { if (gc.getInput().isKeyPressed(Input.KEY_ENTER)) { byte[] bytes = new byte[] { EventProtocol.GAME_STARTED }; bm.putArrayToServer(bytes, (byte) -1); } } } @Override public int getID() { return ID; } public void startGame() { gameStarted = true; } public void addOpponentPlayer(byte playerId) { addPlayer(new OpponentPlayer(playerId, this.gse)); } public void addLocalPlayer(byte playerId) { addPlayer(new LocalPlayer(gc, bm, gse, playerId)); } private void addPlayer(Player player) { GameInstance gs = new GameInstance(player, this.boardSize); instances.put(player.id, gs); } /** * Closes the connection held by the bytemonitorn. */ public void onClose() { if (this.bm.isOpen()) this.bm.closeConnection(); } public void removePlayer(byte playerId) { // TODO: remove stuff inside instance? try { instances.remove(playerId); } catch (Exception e) { // TODO: end game } } public boolean isStarted() { return gameStarted; } }