/
victor_t
/
rogue
Обзор
Документация
Войти
/
victor_t
/
rogue
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
Безопасность
master
src/presentation/Presentation.java
529 строк
19 KB
Victor
add: project source code
07 июл 2026, 07:15
07 июл 2026, 07:15
0ff2a00
Код
Авторство
О чём код?
package presentation; import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.graphics.TextGraphics; import com.googlecode.lanterna.input.KeyStroke; import com.googlecode.lanterna.input.KeyType; import com.googlecode.lanterna.screen.Screen; import com.googlecode.lanterna.screen.TerminalScreen; import com.googlecode.lanterna.terminal.DefaultTerminalFactory; import com.googlecode.lanterna.terminal.Terminal; import datalayer.data.SaveManager; import datalayer.data.dto.RunStatistics; import domain.CharacterAndEnemies.EnemyType; import domain.CharacterAndEnemies.Player; import domain.GameSession; import domain.Items.*; import domain.Levels.*; import domain.Position; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; public class Presentation { private GameSession gameSession = null; private final Terminal terminal; private final Screen screen; private TextGraphics tg; private RunStatistics statistics; private List<Integer> visitedRooms; private boolean[][] currentlyVisible; private boolean renderIsMap = true; private ItemType chooseTypeItem = null; private static final String leftTopBound = "╔"; private static final String leftBotBound = "╚"; private static final String rightTopBound = "╗"; private static final String rightBotBound = "╝"; private static final String verticalBound = "║"; private static final String horizontalBound = "═"; private static final String exit = "╬"; private static final String way = "░"; private static final String room = "."; private static final String treasureUnicode = "✦"; private static final String foodUnicode = "♥"; private static final String scrollUnicode = "⌗"; private static final String weaponUnicode = "†"; private static final String elixirUnicode = "∇"; public Presentation() throws IOException { // создаем объект настройки терминала DefaultTerminalFactory factory = new DefaultTerminalFactory(); // устанавливаем размер терминала (ширина x высота) factory.setInitialTerminalSize(new TerminalSize(100, 40)); // 100x40 символов terminal = factory.createTerminal(); screen = new TerminalScreen(terminal); currentlyVisible = new boolean[Block.getHeight() * 3][Block.getWidth() * 3]; } public void setGameSession(GameSession gameSession) { this.gameSession = gameSession; } public void setStatistics(RunStatistics statistics) { this.statistics = statistics; } public void loadToSession() { SaveManager.loadToSession(gameSession); } public void start() throws IOException { screen.startScreen(); clear(); terminal.setCursorVisible(false); tg = screen.newTextGraphics(); } public void initializeVisitedMap(boolean mode) { visitedRooms = new ArrayList<>(); if (!mode) gameSession.initializeMapVisited(); Integer startIndex = VisitedManager.getPlayerRoomIndex(gameSession, false); if (startIndex != null) { visitedRooms.add(startIndex); VisitedManager.addVisitedRoomToMap(gameSession, gameSession.getMapVisited(), startIndex); } } public void end() throws IOException { screen.stopScreen(); terminal.setCursorVisible(true); terminal.close(); } public void clear() { screen.clear(); } public boolean handleKey(KeyStroke keyStroke) throws Exception { if (keyStroke.getKeyType() == KeyType.Character) { char ch = keyStroke.getCharacter(); if (renderIsMap) { switch (Character.toLowerCase(ch)) { case 'a', 'w', 'd', 's', 'ф', 'ц', 'в', 'ы' -> { if (!gameSession.getPlayer().move(gameSession, ch, 1)) statistics.cellsTraversed++; gameSession.incrementTime(); List<Elixir> elixirs = gameSession.getPlayer().getElixirs(); if (elixirs != null) { List<Elixir> deleteElixir = new ArrayList<>(); for (Elixir elixir: elixirs) { if (elixir.getFinalTime() <= gameSession.getTime()) { deleteElixir.add(elixir); } } for (Elixir elixir: deleteElixir) gameSession.getPlayer().removeElixir(elixir); } } case 'q', 'й' -> { if (gameSession.toTheNextLevel()) { statistics.levelReached = gameSession.getCurrentLevel().getLevel(); clear(); initializeVisitedMap(false); } } case 'h', 'р' -> { renderIsMap = false; chooseTypeItem = ItemType.WEAPON; renderBackpack(gameSession, ItemType.WEAPON); } case 'j', 'о' -> { renderIsMap = false; chooseTypeItem = ItemType.FOOD; renderBackpack(gameSession, ItemType.FOOD); } case 'k', 'л' -> { renderIsMap = false; chooseTypeItem = ItemType.ELIXIR; renderBackpack(gameSession, ItemType.ELIXIR); } case 'e', 'у' -> { renderIsMap = false; chooseTypeItem = ItemType.SCROLL; renderBackpack(gameSession, ItemType.SCROLL); } } } else { switch (Character.toLowerCase(ch)) { case '0' -> { if (chooseTypeItem == ItemType.WEAPON) { gameSession.getPlayer().setCurrentWeapon(null); renderIsMap = true; chooseTypeItem = null; } } case '1', '2', '3', '4', '5', '6', '7', '8', '9' -> { gameSession.getPlayer().useItem(gameSession, chooseTypeItem, ch); renderIsMap = true; chooseTypeItem = null; } } } if (renderIsMap) { gameSession.moveEnemies(); renderGame(); } } else if (keyStroke.getKeyType() == KeyType.Escape) { if (!renderIsMap) { renderGame(); renderIsMap = true; chooseTypeItem = null; } else { return false; } } return gameSession.getPlayer().isAlive(); } public void renderGame() throws Exception { try { clear(); Character[][] map = gameSession.getCurrentLevel().getGeneration().toMap(); Integer indexRoom = VisitedManager.getPlayerRoomIndex(gameSession, false); VisitedManager.addVisitedPlaceToMap(gameSession, gameSession.getMapVisited(), visitedRooms, indexRoom, currentlyVisible); VisitedManager.removeInnerVisitedRooms(gameSession, gameSession.getMapVisited(), visitedRooms, indexRoom); renderMap(map); renderUI(); screen.refresh(); } catch (Exception e) { System.out.println("ОШИБКА В renderGame: " + e.getMessage()); e.printStackTrace(); throw e; } } private void renderMap(Character[][] map) { Character voids = GenerationType.VOID.getValue(); Character bounds = GenerationType.BOUNDS.getValue(); Character exits = GenerationType.EXIT.getValue(); Character ways = GenerationType.WAY.getValue(); Character rooms = GenerationType.ROOM.getValue(); Character zombie = EnemyType.ZOMBIE.getValue(); Character vampire = EnemyType.VAMPIRE.getValue(); Character ogre = EnemyType.OGRE.getValue(); Character ghost = EnemyType.GHOST.getValue(); Character snake = EnemyType.SNAKE_MAGE.getValue(); Character treasure = ItemType.TREASURE.getValue(); Character food = ItemType.FOOD.getValue(); Character elixir = ItemType.ELIXIR.getValue(); Character scroll = ItemType.SCROLL.getValue(); Character weapon = ItemType.WEAPON.getValue(); TextColor boundsColor = GenerationType.BOUNDS.getColor(); TextColor exitColor = GenerationType.EXIT.getColor(); TextColor wayColor = GenerationType.WAY.getColor(); TextColor roomColor = GenerationType.ROOM.getColor(); TextColor voidColor = GenerationType.VOID.getColor(); Player player = gameSession.getPlayer(); EndLevel endLevel = gameSession.getCurrentLevel().getGeneration().getEndLevel(); boolean[][] mapVisited = gameSession.getMapVisited(); for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { if (mapVisited[i][j] || currentlyVisible[i][j]) { if (map[i][j] == bounds) { tg.setForegroundColor(boundsColor); if (i > 0 && j > 0 && map[i - 1][j] == voids && map[i][j - 1] == voids) tg.putString(j, i, leftTopBound); else if (i < map.length - 1 && j > 0 && map[i + 1][j] == voids && map[i][j - 1] == voids) tg.putString(j, i, leftBotBound); else if (i > 0 && j < map[i].length - 1 && map[i - 1][j] == voids && map[i][j + 1] == voids) tg.putString(j, i, rightTopBound); else if (i < map.length - 1 && j < map[i].length - 1 && map[i + 1][j] == voids && map[i][j + 1] == voids) tg.putString(j, i, rightBotBound); else if ((i < map.length - 1 && map[i + 1][j] == bounds) || (i > 0 && map[i - 1][j] == bounds)) tg.putString(j, i, verticalBound); else if ((j > 0 && map[i][j - 1] == bounds) || (j < map[i].length - 1 && map[i][j + 1] == bounds)) tg.putString(j, i, horizontalBound); } else if (map[i][j] == exits) { tg.setForegroundColor(exitColor); tg.putString(j, i, exit); } else if (map[i][j] == ways) { tg.setForegroundColor(wayColor); tg.putString(j, i, way); } else if (map[i][j] == voids) { tg.setForegroundColor(voidColor); tg.putString(j, i, voids.toString()); } else if (map[i][j] == rooms) { tg.setForegroundColor(roomColor); tg.putString(j, i, room); } else if (map[i][j] == EndLevel.getValue()) { tg.setForegroundColor(EndLevel.getColor()); tg.putString(j, i, EndLevel.getValueString()); } else if (map[i][j] == zombie) { tg.setForegroundColor(EnemyType.ZOMBIE.getColor()); tg.putString(j, i, zombie.toString()); } else if (map[i][j] == vampire) { tg.setForegroundColor(EnemyType.VAMPIRE.getColor()); tg.putString(j, i, vampire.toString()); } else if (map[i][j] == ogre) { tg.setForegroundColor(EnemyType.OGRE.getColor()); tg.putString(j, i, ogre.toString()); } else if (map[i][j] == ghost) { tg.setForegroundColor(EnemyType.GHOST.getColor()); tg.putString(j, i, ghost.toString()); } else if (map[i][j] == snake) { tg.setForegroundColor(EnemyType.SNAKE_MAGE.getColor()); tg.putString(j, i, snake.toString()); } else if (map[i][j] == treasure) { tg.setForegroundColor(ItemType.TREASURE.getColor()); tg.putString(j, i, treasureUnicode); } else if (map[i][j] == food) { tg.setForegroundColor(ItemType.FOOD.getColor()); tg.putString(j, i, foodUnicode); } else if (map[i][j] == elixir) { tg.setForegroundColor(ItemType.ELIXIR.getColor()); tg.putString(j, i, elixirUnicode); } else if (map[i][j] == scroll) { tg.setForegroundColor(ItemType.SCROLL.getColor()); tg.putString(j, i, scrollUnicode); } else if (map[i][j] == weapon) { tg.setForegroundColor(ItemType.WEAPON.getColor()); tg.putString(j, i, weaponUnicode); } else if (map[i][j] == Player.getValue()) { if (Position.equal(player.getPosition(), endLevel.getPosition())) { tg.setBackgroundColor(EndLevel.getColor()); tg.setForegroundColor(TextColor.ANSI.BLACK); } else tg.setForegroundColor(Player.getColor()); tg.putString(j, i, Player.getValue().toString()); tg.setBackgroundColor(TextColor.ANSI.BLACK); } else { tg.setForegroundColor(TextColor.ANSI.DEFAULT); tg.putString(j, i, String.valueOf(map[i][j])); } } } } } private void renderUI() { int mapHeight = gameSession.getCurrentLevel().getGeneration().toMap().length; int uiStartY = mapHeight + 1; // Начинаем ниже карты tg.setForegroundColor(TextColor.ANSI.CYAN); tg.setBackgroundColor(TextColor.ANSI.BLACK); String[] status = new String[] { String.format("HP: %d/%d", gameSession.getPlayer().getHealth(), gameSession.getPlayer().getMaxHealth()), String.format("Agility: %d", gameSession.getPlayer().getAgility()), String.format("Strength: %d", gameSession.getPlayer().getStrength()), String.format("Level: %d", gameSession.getCurrentLevel().getLevel()), String.format("Money: %d", gameSession.getPlayer().getBackpack().getTreasures()) }; TextColor[] colors = new TextColor[] { TextColor.Factory.fromString("#FF4040"), TextColor.Factory.fromString("#1FAE6B"), TextColor.Factory.fromString("#FF4500"), TextColor.Factory.fromString("#FFF0F5"), TextColor.Factory.fromString("#FFD700") }; int lengthString = 0; for (int i = 0; i < status.length; i++) { tg.setForegroundColor(colors[i]); tg.putString(lengthString, uiStartY, status[i]); lengthString += status[i].length(); if (i < status.length - 1) { tg.setForegroundColor(TextColor.Factory.fromString("#B9F2FF")); tg.putString(lengthString + 1, uiStartY, "|"); lengthString += 3; } } tg.setForegroundColor(TextColor.ANSI.WHITE); String controls = "WASD: Move | ESC:Exit"; tg.putString(0, uiStartY + 2, controls); tg.setForegroundColor(TextColor.ANSI.MAGENTA); tg.putString(0, uiStartY + 4, "Врагов: " + gameSession.getCurrentLevel().getGeneration().getEnemies().size()); Map<ItemType, List<AbstractItem>> backpack = gameSession.getPlayer().getBackpack().getAllItems(); int padding = 10; int length = 0; for (Character ch: ItemType.getAllValue()) { ItemType type = ItemType.getType(ch); if (type != ItemType.TREASURE) { List<AbstractItem> items = backpack.get(type); int count = items.size(); tg.setForegroundColor(type.getColor()); String character = switch (type) { case ItemType.FOOD -> foodUnicode; case ItemType.ELIXIR -> elixirUnicode; case ItemType.SCROLL -> scrollUnicode; case ItemType.WEAPON -> weaponUnicode; default -> ""; }; tg.putString(padding * length, uiStartY + 6, String.format("%s:%d/9", character, count)); length++; } } } private void renderBackpack(GameSession gameSession, ItemType type) throws Exception { clear(); List<AbstractItem> items = gameSession.getPlayer().getBackpack().getItemFromBackpack(type); String text = ""; switch(type) { case ItemType.FOOD -> text = foodUnicode + " Food:"; case ItemType.ELIXIR -> text = elixirUnicode + " Elixir:"; case ItemType.SCROLL -> text = scrollUnicode + " Scroll:"; case ItemType.WEAPON -> text = weaponUnicode + " Weapon:"; } tg.setForegroundColor(type.getColor()); tg.putString(0, 2, text); if (items != null) { int startRow = 2; if (type == ItemType.WEAPON) { if (!items.isEmpty()) { tg.putString(0, 4, 0 + ") Убрать оружие из рук"); startRow = 4; } } for (int i = 0; i < items.size(); i++) { text = items.get(i).getName(); tg.putString(0, startRow + (i + 1) * 2,(i + 1) + ") " + text); } } screen.refresh(); } public int renderMenu() throws Exception { drawMenu(0); int currentIndex = 0; boolean running = true; int result = 0; while (running) { KeyStroke keyStroke = screen.pollInput(); if (keyStroke != null) { switch(keyStroke.getKeyType()) { case KeyType.Character -> { char ch = keyStroke.getCharacter(); switch (ch) { case 'w', 'ц' -> {if (currentIndex > 0) currentIndex--;} case 's', 'ы' -> {if (currentIndex < 2) currentIndex++;} } drawMenu(currentIndex); } case KeyType.Enter -> running = false; case KeyType.Escape -> { running = false; currentIndex = -1; } } } Thread.sleep(20); } return currentIndex; } public void drawMenu(int currentIndex) throws IOException { clear(); String[] actions = new String[] { "New game", "Continue", "Top results" }; String text = ""; for (int i = 0; i < actions.length; i++) { if (i == currentIndex) { tg.setForegroundColor(TextColor.Factory.fromString("#FFD700")); tg.putString(10, 10 + i * 2, actions[i]); } else { tg.setForegroundColor(TextColor.Factory.fromString("#3CB371")); tg.putString(10, 10 + i * 2, actions[i]); } } screen.refresh(); } public void renderRating(List<RunStatistics> allRuns) throws Exception { clear(); String[] titles = new String[] {treasureUnicode, "level", "dead", foodUnicode, elixirUnicode, scrollUnicode, "hit", "miss", "cells"}; TextColor[] colors = new TextColor[] { ItemType.TREASURE.getColor(), TextColor.Factory.fromString("#FFF0F5"), TextColor.ANSI.RED, ItemType.FOOD.getColor(), ItemType.ELIXIR.getColor(), ItemType.SCROLL.getColor(), TextColor.ANSI.GREEN, TextColor.ANSI.WHITE, TextColor.ANSI.CYAN_BRIGHT }; int padding = 0; for (int i = 0; i < titles.length; i++) { tg.setForegroundColor(colors[i]); tg.putString(padding, 1, titles[i]); padding += 7; } int count = 0, index = 3; for (RunStatistics stat: allRuns) { if (count < 10) { String[] text = RunStatistics.convertToString(stat); int i = 0, left = 0; for (String str: text) { tg.setForegroundColor(colors[i]); tg.putString(left, index, str); i++; left += 7; } count++; index += 2; } } screen.refresh(); boolean running = true; while (running) { KeyStroke keyStroke = screen.pollInput(); if (keyStroke != null && keyStroke.getKeyType() == KeyType.Escape) { running = false; } Thread.sleep(20); } } public Screen getScreen() { return screen; } public boolean[][]getCurrentlyVisible() { return currentlyVisible; } }