package gltronic.tronio.business; import java.io.IOException; import java.util.ArrayList; import java.util.Random; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.socket.WebSocketSession; import gltronic.tronio.model.Game; import gltronic.tronio.model.Player; import gltronic.tronio.model.Wall; @Service public class GameManager implements IGameManager { @Autowired Game game; @Override public void login(WebSocketSession session) throws InterruptedException, IOException { if (game.getSessions().containsKey(session.getId())) { SocketUtils.sendMessage(session, "error", "cant login twice"); return; } Player player = initPlayer(new Player()); game.getSessions().put(session.getId(), session); game.getPlayers().put(session.getId(), player); System.out.println("[GAME] Player " + session.getId() + " logged in | status: " + player.getX() + " " + player.getY() + " " + player.getColor()); SocketUtils.sendObject(session, "login", new ObjectMapper().writeValueAsString(player)); SocketUtils.sendObject(session, "gameSettings", new ObjectMapper().writeValueAsString(game.getSettings())); SocketUtils.sendObject(session, "gameUpdate", new ObjectMapper().writeValueAsString(game.getPlayers().values())); } @Override public void leave(WebSocketSession session) throws InterruptedException, IOException { game.getSessions().remove(session.getId()); game.getPlayers().remove(session.getId()); } @Override public void updatePlayer(WebSocketSession session, Player player) throws InterruptedException, IOException { Player playerToUpdate = game.getPlayers().get(session.getId()); playerToUpdate.setAngle(player.getAngle()); playerToUpdate.setTargetAngle(player.getTargetAngle()); } @Override @Scheduled(fixedDelay = 1000 / 60) public void step() throws InterruptedException, IOException { // CHECK OUT OF BORDERS & COLISIONS game.getPlayers().forEach((id, player) -> { // OUT OF BORDERS if (player.getX() - game.getSettings().getPlayerSize() < 0 || player.getX() + game.getSettings().getPlayerSize() > game.getSettings().getArenaSize() || player.getY() - game.getSettings().getPlayerSize() < 0 || player.getY() + game.getSettings().getPlayerSize() > game.getSettings().getArenaSize()) { System.out.println("[GAME] border"); killPlayer(id); return; } // COLLISIONS game.getPlayers().forEach((id2, player2) -> { for (var i = 0; i < player2.getWalls().size() - 2; i++) { Wall wallA = player2.getWalls().get(i); Wall wallB = player2.getWalls().get(i + 1); if (isCloseToWall(wallA.getX(), wallA.getY(), wallB.getX(), wallB.getY(), player.getX(), player.getY(), game.getSettings().getPlayerSize())) { System.out.println("[GAME] close to wall"); if (this.isCrossingLine(wallA.getX(), wallA.getY(), wallB.getX(), wallB.getY(), player.getX(), player.getY(), game.getSettings().getPlayerSize())) { System.out.println("[GAME] touch da wall"); killPlayer(id); return; } } } }); }); // ADD WALLS & MOVE PLAYER game.getPlayers().forEach((id, player) -> { // WALL player.setLastWall(player.getLastWall() + 1); if (player.getLastWall() > game.getSettings().getWallUpdate()) { player.getWalls().add(new Wall(player.getX(), player.getY())); player.setLastWall(0); } // MOVE player.setX(player.getX() + game.getSettings().getPlayerSpeed() * Math.cos(player.getAngle())); player.setY(player.getY() + game.getSettings().getPlayerSpeed() * Math.sin(player.getAngle())); }); SocketUtils.broadcast(game, "gameUpdate", new ObjectMapper().writeValueAsString(game.getPlayers().values())); } private void killPlayer(String id) { Player player = game.getPlayers().get(id); initPlayer(player); System.out.println("[GAME] Player " + id + " is dead | status: " + player.getX() + " " + player.getY() + " " + player.getColor()); try { SocketUtils.sendObject(game.getSessions().get(id), "gamePlayerDead", new ObjectMapper().writeValueAsString(player)); } catch (JsonProcessingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private boolean isCloseToWall (double xa, double ya, double xb, double yb, double xc, double yc, double radius) { var xar = Math.min(xa, xb) - radius; var yar = Math.min(ya, yb) - radius; var xbr = Math.max(xa, xb) + radius; var ybr = Math.max(ya, yb) + radius; return ((xc >= xar && xc <= xbr) && (yc >= yar && yc <= ybr)); } private boolean isCrossingLine (double xa, double ya, double xb, double yb, double xc, double yc, double radius) { var a = xc - xa; var b = xb - xa; var c = yc - ya; var d = yb - ya; var result = (a * d - b * c) / Math.sqrt(Math.pow(xa - xb, 2) + Math.pow(ya - yb, 2)); return result < radius; } private Player initPlayer(Player player) { Random rand = new Random(); double x = game.getSettings().getArenaSize() * (0.25 + Math.random() * 0.5); double y = game.getSettings().getArenaSize() * (0.25 + Math.random() * 0.5); // player.setAngle(0); // player.setTargetAngle(0); player.setLastWall(0); player.setWalls(new ArrayList()); player.setColor(String.format("#%06x", rand.nextInt(0xffffff + 1))); player.setX(x); player.setY(y); return player; } }