import java.awt.*; import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentHashMap; public class GameState { private static final int WIDTH = 800, HEIGHT = 600; private static final int BUNNY_SIZE = 40, CAR_WIDTH = 80, CAR_HEIGHT = 40; private static final int LANE_HEIGHT = 60, GRASS_HEIGHT = 80, NUM_LANES = 5; private static final int HOUSE_Y = 50, HOUSE_SIZE = 60; private Map<String, Player> players = new ConcurrentHashMap<>(); private List<Car> cars = new ArrayList<>(); private boolean gameOver = false; private String winner = null; private int score = 0; private int level = 1; public void startGame(boolean isSinglePlayer) { players.clear(); cars.clear(); gameOver = false; winner = null; score = 0; level = 1; players.put("PLAYER1", new Player(200, HEIGHT - BUNNY_SIZE - 10, Color.RED)); if (!isSinglePlayer) { players.put("PLAYER2", new Player(600, HEIGHT - BUNNY_SIZE - 10, Color.BLUE)); } initializeCars(); } private void initializeCars() { Random rand = new Random(); for (int i = 0; i < NUM_LANES; i++) { int y = HOUSE_Y + HOUSE_SIZE + i * (LANE_HEIGHT + GRASS_HEIGHT) + (LANE_HEIGHT - CAR_HEIGHT) / 2; int speed = (rand.nextInt(3) + 2) * (rand.nextBoolean() ? 1 : -1); cars.add(new Car(rand.nextInt(WIDTH), y, speed)); } } public void update() { moveCars(); checkCollisions(); checkWinCondition(); updateScore(); } private void moveCars() { for (Car car : cars) { car.move(); if (car.getX() > WIDTH) car.setX(-CAR_WIDTH); if (car.getX() < -CAR_WIDTH) car.setX(WIDTH); } } private void checkCollisions() { for (Player player : players.values()) { for (Car car : cars) { if (car.checkCollision(player.getX(), player.getY(), BUNNY_SIZE)) { player.reset(); score = Math.max(0, score - 50); } } } } private void checkWinCondition() { for (Map.Entry<String, Player> entry : players.entrySet()) { Player player = entry.getValue(); if (player.getY() <= HOUSE_Y + HOUSE_SIZE) { gameOver = true; winner = entry.getKey(); break; } } } private void updateScore() { score++; if (score % 1000 == 0) { level++; for (Car car : cars) { car.increaseSpeed(); } } } public void movePlayer(String playerId, String direction) { Player player = players.get(playerId); if (player != null) { switch (direction) { case "UP" -> player.moveUp(); case "DOWN" -> player.moveDown(); case "LEFT" -> player.moveLeft(); case "RIGHT" -> player.moveRight(); } } } public void render(Graphics g) { drawBackground(g); drawHouses(g); drawCars(g); drawPlayers(g); drawScore(g); if (gameOver) { drawGameOver(g); } } private void drawBackground(Graphics g) { g.setColor(Color.GREEN); g.fillRect(0, 0, WIDTH, HEIGHT); g.setColor(Color.GRAY); for (int i = 0; i < NUM_LANES; i++) { int laneY = HOUSE_Y + HOUSE_SIZE + i * (LANE_HEIGHT + GRASS_HEIGHT); g.fillRect(0, laneY, WIDTH, LANE_HEIGHT); } } private void drawHouses(Graphics g) { g.setColor(Color.ORANGE); int houseWidth = WIDTH / NUM_LANES; for (int i = 0; i < NUM_LANES; i++) { g.fillRect(i * houseWidth, HOUSE_Y, houseWidth - 10, HOUSE_SIZE); } } private void drawPlayers(Graphics g) { for (Player player : players.values()) { player.draw(g); } } private void drawCars(Graphics g) { for (Car car : cars) { car.draw(g); } } private void drawScore(Graphics g) { g.setColor(Color.BLACK); g.setFont(new Font("Arial", Font.BOLD, 20)); g.drawString("Score: " + score, 10, 25); g.drawString("Level: " + level, WIDTH - 100, 25); } private void drawGameOver(Graphics g) { g.setColor(new Color(0, 0, 0, 150)); g.fillRect(0, 0, WIDTH, HEIGHT); g.setColor(Color.WHITE); g.setFont(new Font("Arial", Font.BOLD, 40)); g.drawString("Game Over!", WIDTH / 2 - 100, HEIGHT / 2 - 20); g.setFont(new Font("Arial", Font.BOLD, 30)); g.drawString(winner + " wins!", WIDTH / 2 - 70, HEIGHT / 2 + 20); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Player> entry : players.entrySet()) { Player p = entry.getValue(); sb.append(entry.getKey()).append(":").append(p.getX()).append(",").append(p.getY()).append(";"); } for (Car car : cars) { sb.append("CAR:").append(car.getX()).append(",").append(car.getY()).append(",").append(car.getSpeed()).append(";"); } sb.append("GAME:").append(gameOver).append(",").append(winner).append(",").append(score).append(",").append(level); return sb.toString(); } public void fromString(String state) { String[] parts = state.split(";"); players.clear(); cars.clear(); for (String part : parts) { String[] data = part.split(":"); switch (data[0]) { case "PLAYER1", "PLAYER2" -> { String[] coords = data[1].split(","); players.put(data[0], new Player(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), data[0].equals("PLAYER1") ? Color.RED : Color.BLUE)); } case "CAR" -> { String[] coords = data[1].split(","); cars.add(new Car(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2]))); } case "GAME" -> { String[] gameData = data[1].split(","); gameOver = Boolean.parseBoolean(gameData[0]); winner = gameData[1].equals("null") ? null : gameData[1]; score = Integer.parseInt(gameData[2]); level = Integer.parseInt(gameData[3]); } } } } private static class Player { private int x, y; private Color color; public Player(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } public void moveUp() { y = Math.max(HOUSE_Y + HOUSE_SIZE, y - 5); } public void moveDown() { y = Math.min(HEIGHT - BUNNY_SIZE, y + 5); } public void moveLeft() { x = Math.max(0, x - 5); } public void moveRight() { x = Math.min(WIDTH - BUNNY_SIZE, x + 5); } public void reset() { x = color == Color.RED ? 200 : 600; y = HEIGHT - BUNNY_SIZE - 10; } public int getX() { return x; } public int getY() { return y; } public void draw(Graphics g) { g.setColor(color); g.fillOval(x, y, BUNNY_SIZE, BUNNY_SIZE); } } }