diff --git a/core/src/main/java/com/mygdx/game/AbsurdCityBuilder1.java b/core/src/main/java/com/mygdx/game/AbsurdCityBuilder1.java index 91f09c5..1040f87 100644 --- a/core/src/main/java/com/mygdx/game/AbsurdCityBuilder1.java +++ b/core/src/main/java/com/mygdx/game/AbsurdCityBuilder1.java @@ -11,8 +11,6 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.GlyphLayout; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; @@ -21,9 +19,9 @@ import java.util.Random; public class AbsurdCityBuilder1 extends ApplicationAdapter { // Константы - private static final int WIDTH = 1700; - private static final int HEIGHT = 950; - private static final int UI_INPUT_HEIGHT = 210; + private static final int WIDTH = GameConfig.WIDTH; + private static final int HEIGHT = GameConfig.HEIGHT; + private static final int UI_INPUT_HEIGHT = GameConfig.UI_INPUT_HEIGHT; // Основные объекты private SpriteBatch batch; @@ -52,9 +50,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { private int selectedBuildingType = 0; private StringBuilder inputText = new StringBuilder(); private boolean isTyping = false; - private String messageText = "Добро пожаловать! Выберите здание и кликните на поле."; + private String messageText = ""; private Color messageColor = Color.WHITE; - private String problemText = "Нажмите ESC для возврата в меню"; + private String problemText = ""; // Текстуры и рендереры private Texture backgroundTexture; @@ -62,6 +60,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { private UIRenderer uiRenderer; private MenuRenderer menuRenderer; + // Достижения + private AchievementPopup achievementPopup; + // Планета private Planet currentPlanet; private float planetSwitchTimer = 0; @@ -95,6 +96,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { // Начинаем с Земли currentPlanet = Planet.EARTH; + // Загружаем настройки и достижения + GameSave.loadSettings(); + try { backgroundTexture = new Texture(Gdx.files.internal("фон4.png")); } catch (Exception e) { @@ -104,6 +108,11 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { buildingRenderer = new BuildingRenderer(shapeRenderer, batch, font, glyphLayout, whitePixel); uiRenderer = new UIRenderer(batch, font, glyphLayout, whitePixel, WIDTH, HEIGHT, UI_INPUT_HEIGHT); menuRenderer = new MenuRenderer(batch, font, glyphLayout, whitePixel, WIDTH, HEIGHT); + achievementPopup = new AchievementPopup(); + + // Устанавливаем начальные сообщения + messageText = Localization.welcomeTo(currentPlanet); + problemText = Localization.isRu() ? "Нажмите ESC для возврата в меню" : "Press ESC to return to menu"; updateUI(); } @@ -133,10 +142,18 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { case ABOUT: renderAbout(); break; + case ACHIEVEMENTS: + renderAchievements(); + break; case PLAYING: renderGame(); break; } + + // Рендер уведомления о достижении поверх всего + if (achievementPopup.isActive()) { + achievementPopup.render(batch, font, glyphLayout, whitePixel, WIDTH, HEIGHT); + } } private void handleInput() { @@ -152,12 +169,12 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { // Отмена ввода setTyping(false); getInputText().setLength(0); - setMessageText("Ввод отменен."); + setMessageText(Localization.inputCanceled()); setMessageColor(Color.YELLOW); } else { - // Возврат в главное меню + // Возврат в главное меню с сохранением + GameSave.save(this); gameState = GameState.MAIN_MENU; - setMessageText("Игра приостановлена. Нажмите ESC для продолжения."); } } else if (gameState != GameState.MAIN_MENU) { // Возврат в главное меню из других состояний @@ -179,6 +196,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { case ABOUT: handleAboutInput(mouseX, mouseY, isClicked); break; + case ACHIEVEMENTS: + handleAchievementsInput(mouseX, mouseY, isClicked); + break; case PLAYING: InputHandler.handleInput(this); break; @@ -189,19 +209,30 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { private void handleMainMenuInput(float mouseX, float mouseY, boolean isClicked) { if (isClicked) { + // Проверяем клик на переключатель языка + if (menuRenderer.checkLanguageClick(mouseX, mouseY)) { + Localization.toggleLanguage(); + GameSave.saveSettings(); + menuRenderer.refreshMenuTexts(); + return; + } + MenuButton clickedButton = menuRenderer.getMainMenuButtonAt(mouseX, mouseY); if (clickedButton != null) { - String buttonText = clickedButton.getText(); // Используйте геттер + String buttonText = clickedButton.getText(); - if (buttonText.contains("НОВАЯ ИГРА")) { + if (buttonText.contains("ПРОДОЛЖИТЬ") || buttonText.contains("CONTINUE")) { + continueGame(); + } else if (buttonText.contains("НОВАЯ") || buttonText.contains("NEW")) { startNewGame(); - } else if (buttonText.contains("ВЫБОР ПЛАНЕТЫ")) { + } else if (buttonText.contains("ПЛАНЕТ") || buttonText.contains("PLANET")) { gameState = GameState.PLANET_SELECT; - } else if (buttonText.contains("ПОМОЩЬ")) { + } else if (buttonText.contains("ДОСТИЖЕНИЯ") || buttonText.contains("ACHIEVEMENTS")) { + gameState = GameState.ACHIEVEMENTS; + } else if (buttonText.contains("ПОМОЩЬ") || buttonText.contains("HELP")) { gameState = GameState.HELP; - } else if (buttonText.contains("ОБ ИГРЕ")) { - gameState = GameState.ABOUT; - } else if (buttonText.contains("ВЫХОД")) { + } else if (buttonText.contains("ВЫХОД") || buttonText.contains("EXIT")) { + GameSave.saveSettings(); Gdx.app.exit(); } } @@ -212,15 +243,15 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { if (isClicked) { MenuButton clickedButton = menuRenderer.getPlanetSelectButtonAt(mouseX, mouseY); if (clickedButton != null) { - String buttonText = clickedButton.getText(); // Используйте геттер + String buttonText = clickedButton.getText(); - if (buttonText.contains("ЗЕМЛЯ")) { + if (buttonText.contains("ЗЕМЛЯ") || buttonText.contains("EARTH")) { startNewGameOnPlanet(Planet.EARTH); - } else if (buttonText.contains("МАРС")) { + } else if (buttonText.contains("МАРС") || buttonText.contains("MARS")) { startNewGameOnPlanet(Planet.MARS); - } else if (buttonText.contains("ВЕНЕРА")) { + } else if (buttonText.contains("ВЕНЕРА") || buttonText.contains("VENUS")) { startNewGameOnPlanet(Planet.VENUS); - } else if (buttonText.contains("НАЗАД")) { + } else if (buttonText.contains("НАЗАД") || buttonText.contains("BACK")) { gameState = GameState.MAIN_MENU; } } @@ -231,11 +262,7 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { if (isClicked) { MenuButton clickedButton = menuRenderer.getHelpButtonAt(mouseX, mouseY); if (clickedButton != null) { - String buttonText = clickedButton.getText(); // Используйте геттер - - if (buttonText.contains("НАЗАД")) { - gameState = GameState.MAIN_MENU; - } + gameState = GameState.MAIN_MENU; } } } @@ -249,7 +276,50 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { } } + private void handleAchievementsInput(float mouseX, float mouseY, boolean isClicked) { + if (isClicked) { + MenuButton clickedButton = menuRenderer.getAchievementsButtonAt(mouseX, mouseY); + if (clickedButton != null) { + gameState = GameState.MAIN_MENU; + } + } + } + + private void continueGame() { + // Загружаем сохранение и продолжаем игру + GameSave.load(this); + + // Загружаем здания и жителей + jokeBubbles.clear(); + currentBuilding = null; + currentProblem = null; + selectedBuildingType = 0; + inputText.setLength(0); + isTyping = false; + isSwitchingPlanets = false; + + // Загружаем сохранённые здания + GameSave.loadBuildings(buildings, citizens, random); + + // Отмечаем посещение текущей планеты + Achievements.visitPlanet(currentPlanet); + + // Показываем прогресс + String progressInfo = Localization.isRu() + ? " (Загружено зданий: " + buildings.size + ")" + : " (Loaded buildings: " + buildings.size + ")"; + messageText = Localization.welcomeTo(currentPlanet) + progressInfo; + messageColor = Color.GREEN; + + gameState = GameState.PLAYING; + updateUI(); + } + private void startNewGame() { + // Сбрасываем ВСЮ статистику для новой игры + GameSave.resetAll(); + Achievements.reset(); + // Очищаем всё и начинаем новую игру на Земле buildings.clear(); citizens.clear(); @@ -263,7 +333,10 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { currentPlanet = Planet.EARTH; isSwitchingPlanets = false; - messageText = "Добро пожаловать на Землю! Выберите здание и кликните на поле."; + // Отмечаем посещение Земли + Achievements.visitPlanet(Planet.EARTH); + + messageText = Localization.welcomeTo(currentPlanet); messageColor = Color.GREEN; gameState = GameState.PLAYING; @@ -284,7 +357,10 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { currentPlanet = planet; isSwitchingPlanets = false; - messageText = "Добро пожаловать на " + planet.getName() + "! Выберите здание и кликните на поле."; + // Отмечаем посещение планеты + Achievements.visitPlanet(planet); + + messageText = Localization.welcomeTo(planet); messageColor = Color.GREEN; gameState = GameState.PLAYING; @@ -298,13 +374,32 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { // Обновляем меню menuRenderer.update(deltaTime); + // Обновляем уведомление о достижении + achievementPopup.update(deltaTime); + + // Проверяем новые достижения + if (Achievements.hasNewUnlock()) { + Achievement newAchievement = Achievements.getLastUnlocked(); + if (newAchievement != null && !achievementPopup.isActive()) { + achievementPopup.show(newAchievement); + GameSave.saveSettings(); + } + } + // Обработка плавной смены планет if (isSwitchingPlanets) { planetSwitchTimer += deltaTime; if (planetSwitchTimer >= 1.0f) { currentPlanet = targetPlanet; isSwitchingPlanets = false; - setMessageText("Добро пожаловать на " + currentPlanet.getName() + "! 🌍"); + + // Отмечаем посещение новой планеты и сохраняем + Achievements.visitPlanet(currentPlanet); + Achievements.check(this); + GameSave.savePlanet(currentPlanet); + GameSave.saveSettings(); + + setMessageText(Localization.welcomeTo(currentPlanet)); } } @@ -359,7 +454,7 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { currentProblem = null; selectedBuildingType = 0; - setMessageText("Запускаем космический корабль на " + newPlanet.getName() + "! 🚀"); + setMessageText(Localization.flying(newPlanet)); setMessageColor(Color.YELLOW); updateUI(); } @@ -392,6 +487,12 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { menuRenderer.renderAbout(mouseX, mouseY); } + private void renderAchievements() { + float mouseX = Gdx.input.getX(); + float mouseY = HEIGHT - Gdx.input.getY(); + menuRenderer.renderAchievements(mouseX, mouseY); + } + private void renderGame() { renderBackground(); renderBuildings(); @@ -473,9 +574,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { String transitionText; if (planetSwitchTimer < 0.5f) { - transitionText = "Покидаем " + currentPlanet.getName() + "..."; + transitionText = Localization.leaving(currentPlanet); } else { - transitionText = "Прибываем на " + targetPlanet.getName() + "!"; + transitionText = Localization.arriving(targetPlanet); } glyphLayout.setText(font, transitionText); @@ -500,6 +601,9 @@ public class AbsurdCityBuilder1 extends ApplicationAdapter { @Override public void dispose() { + // Сохраняем настройки при выходе + GameSave.saveSettings(); + batch.dispose(); shapeRenderer.dispose(); font.dispose(); diff --git a/core/src/main/java/com/mygdx/game/Achievement.java b/core/src/main/java/com/mygdx/game/Achievement.java new file mode 100644 index 0000000..0eba188 --- /dev/null +++ b/core/src/main/java/com/mygdx/game/Achievement.java @@ -0,0 +1,96 @@ +package com.mygdx.game; + +/** + * Перечисление всех достижений в игре. + */ +public enum Achievement { + // Строительство + FIRST_BUILDING("first_building", + "Первый кирпич", "First Brick", + "Построй первое здание", "Build your first building"), + + BUILDER_5("builder_5", + "Строитель", "Builder", + "Построй 5 зданий", "Build 5 buildings"), + + BUILDER_10("builder_10", + "Архитектор", "Architect", + "Построй 10 зданий", "Build 10 buildings"), + + BUILDER_25("builder_25", + "Мастер-строитель", "Master Builder", + "Построй 25 зданий", "Build 25 buildings"), + + // Планеты + MARS_VISITOR("mars_visitor", + "Марсианин", "Martian", + "Посети Марс", "Visit Mars"), + + VENUS_VISITOR("venus_visitor", + "Венерианец", "Venusian", + "Посети Венеру", "Visit Venus"), + + ALL_PLANETS("all_planets", + "Космонавт", "Astronaut", + "Посети все планеты", "Visit all planets"), + + // Математика + MATH_STREAK_5("math_streak_5", + "Умник", "Smart One", + "5 правильных ответов подряд", "5 correct answers in a row"), + + MATH_STREAK_10("math_streak_10", + "Математик", "Mathematician", + "10 правильных ответов подряд", "10 correct answers in a row"), + + MATH_STREAK_20("math_streak_20", + "Гений", "Genius", + "20 правильных ответов подряд", "20 correct answers in a row"); + + private final String id; + private final String titleRu; + private final String titleEn; + private final String descriptionRu; + private final String descriptionEn; + + Achievement(String id, String titleRu, String titleEn, + String descriptionRu, String descriptionEn) { + this.id = id; + this.titleRu = titleRu; + this.titleEn = titleEn; + this.descriptionRu = descriptionRu; + this.descriptionEn = descriptionEn; + } + + public String getId() { + return id; + } + + public String getTitle() { + return Localization.isRu() ? titleRu : titleEn; + } + + public String getDescription() { + return Localization.isRu() ? descriptionRu : descriptionEn; + } + + public String getTitleRu() { + return titleRu; + } + + public String getTitleEn() { + return titleEn; + } + + /** + * Найти достижение по ID + */ + public static Achievement fromId(String id) { + for (Achievement a : values()) { + if (a.id.equals(id)) { + return a; + } + } + return null; + } +} diff --git a/core/src/main/java/com/mygdx/game/AchievementPopup.java b/core/src/main/java/com/mygdx/game/AchievementPopup.java new file mode 100644 index 0000000..6d0f8e0 --- /dev/null +++ b/core/src/main/java/com/mygdx/game/AchievementPopup.java @@ -0,0 +1,126 @@ +package com.mygdx.game; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; + +// Всплывающее уведомление о разблокировке достижения. + +public class AchievementPopup { + + private static final float POPUP_WIDTH = 400; + private static final float POPUP_HEIGHT = 80; + private static final float POPUP_DURATION = 3.0f; + private static final Color BG_COLOR = new Color(0.1f, 0.1f, 0.2f, 0.95f); + private static final Color BORDER_COLOR = new Color(1.0f, 0.8f, 0.2f, 1f); + private static final Color TITLE_COLOR = new Color(1.0f, 0.9f, 0.3f, 1f); + + private Achievement currentAchievement; + private float timer; + private boolean active; + + public AchievementPopup() { + this.currentAchievement = null; + this.timer = 0; + this.active = false; + } + + // Показать уведомление о достижении + public void show(Achievement achievement) { + this.currentAchievement = achievement; + this.timer = POPUP_DURATION; + this.active = true; + Achievements.clearNewUnlock(); + } + + /** + * Обновить таймер + */ + public void update(float deltaTime) { + if (active) { + timer -= deltaTime; + if (timer <= 0) { + active = false; + currentAchievement = null; + } + } + } + + /** + * Активен ли попап + */ + public boolean isActive() { + return active && currentAchievement != null; + } + + /** + * Отрисовать попап достижения + */ + public void render(SpriteBatch batch, BitmapFont font, GlyphLayout layout, + Texture whitePixel, int screenWidth, int screenHeight) { + if (!isActive()) { + return; + } + + float progress = timer / POPUP_DURATION; + + // Анимация появления/исчезновения + float alpha = 1.0f; + float offsetY = 0; + + if (progress > 0.8f) { + // Появление (первые 20% времени) + float appearProgress = (1.0f - progress) / 0.2f; + alpha = appearProgress; + offsetY = (1.0f - appearProgress) * 50; + } else if (progress < 0.2f) { + // Исчезновение (последние 20% времени) + alpha = progress / 0.2f; + offsetY = (1.0f - alpha) * 50; + } + + float x = screenWidth / 2f - POPUP_WIDTH / 2f; + float y = screenHeight - POPUP_HEIGHT - 20 - offsetY; + + batch.begin(); + + // Фон + batch.setColor(BG_COLOR.r, BG_COLOR.g, BG_COLOR.b, BG_COLOR.a * alpha); + batch.draw(whitePixel, x, y, POPUP_WIDTH, POPUP_HEIGHT); + + // Рамка + batch.setColor(BORDER_COLOR.r, BORDER_COLOR.g, BORDER_COLOR.b, BORDER_COLOR.a * alpha); + batch.draw(whitePixel, x, y, POPUP_WIDTH, 3); // низ + batch.draw(whitePixel, x, y + POPUP_HEIGHT - 3, POPUP_WIDTH, 3); // верх + batch.draw(whitePixel, x, y, 3, POPUP_HEIGHT); // лево + batch.draw(whitePixel, x + POPUP_WIDTH - 3, y, 3, POPUP_HEIGHT); // право + + // Заголовок "Достижение разблокировано!" + font.setColor(TITLE_COLOR.r, TITLE_COLOR.g, TITLE_COLOR.b, alpha); + font.getData().setScale(0.9f); + String header = Localization.achievementUnlocked(); + layout.setText(font, header); + font.draw(batch, header, x + POPUP_WIDTH / 2f - layout.width / 2f, y + POPUP_HEIGHT - 15); + + // Название достижения + font.setColor(1, 1, 1, alpha); + font.getData().setScale(1.1f); + String title = "🏆 " + currentAchievement.getTitle(); + layout.setText(font, title); + font.draw(batch, title, x + POPUP_WIDTH / 2f - layout.width / 2f, y + POPUP_HEIGHT - 40); + + // Описание + font.setColor(0.8f, 0.8f, 0.8f, alpha); + font.getData().setScale(0.8f); + String desc = currentAchievement.getDescription(); + layout.setText(font, desc); + font.draw(batch, desc, x + POPUP_WIDTH / 2f - layout.width / 2f, y + 20); + + font.getData().setScale(1.0f); + batch.setColor(Color.WHITE); + + batch.end(); + } +} diff --git a/core/src/main/java/com/mygdx/game/Achievements.java b/core/src/main/java/com/mygdx/game/Achievements.java new file mode 100644 index 0000000..2a58cd8 --- /dev/null +++ b/core/src/main/java/com/mygdx/game/Achievements.java @@ -0,0 +1,212 @@ +package com.mygdx.game; + +import java.util.HashSet; +import java.util.Set; + +/** + * Менеджер достижений - проверка условий и разблокировка. + */ +public class Achievements { + private static Set unlocked = new HashSet<>(); + private static Achievement lastUnlocked = null; + private static float popupTimer = 0; + private static final float POPUP_DURATION = 3.0f; + private static boolean hasNewUnlockFlag = false; + + /** + * Проверить все условия достижений + */ + public static void check(AbsurdCityBuilder1 game) { + // Строительство + int total = GameSave.getTotalBuildings(); + + if (total >= 1) { + tryUnlock(Achievement.FIRST_BUILDING); + } + if (total >= 5) { + tryUnlock(Achievement.BUILDER_5); + } + if (total >= 10) { + tryUnlock(Achievement.BUILDER_10); + } + if (total >= 25) { + tryUnlock(Achievement.BUILDER_25); + } + + // Планеты + if (GameSave.hasVisitedMars()) { + tryUnlock(Achievement.MARS_VISITOR); + } + if (GameSave.hasVisitedVenus()) { + tryUnlock(Achievement.VENUS_VISITOR); + } + if (GameSave.hasVisitedAllPlanets()) { + tryUnlock(Achievement.ALL_PLANETS); + } + + // Математика + int streak = GameSave.getCorrectStreak(); + + if (streak >= 5) { + tryUnlock(Achievement.MATH_STREAK_5); + } + if (streak >= 10) { + tryUnlock(Achievement.MATH_STREAK_10); + } + if (streak >= 20) { + tryUnlock(Achievement.MATH_STREAK_20); + } + } + + /** + * Попробовать разблокировать достижение + */ + private static void tryUnlock(Achievement achievement) { + if (!unlocked.contains(achievement)) { + unlock(achievement); + } + } + + /** + * Разблокировать достижение + */ + public static void unlock(Achievement achievement) { + if (unlocked.contains(achievement)) { + return; + } + + unlocked.add(achievement); + lastUnlocked = achievement; + popupTimer = POPUP_DURATION; + hasNewUnlockFlag = true; + + // Сохраняем сразу + GameSave.saveSettings(); + } + + /** + * Отметить посещение планеты + */ + public static void visitPlanet(Planet planet) { + GameSave.onVisitPlanet(planet); + } + + /** + * Есть ли новое непоказанное достижение + */ + public static boolean hasNewUnlock() { + return hasNewUnlockFlag; + } + + /** + * Сбросить флаг нового достижения + */ + public static void clearNewUnlock() { + hasNewUnlockFlag = false; + } + + /** + * Обновить таймер попапа + */ + public static void update(float deltaTime) { + if (popupTimer > 0) { + popupTimer -= deltaTime; + if (popupTimer <= 0) { + lastUnlocked = null; + } + } + } + + /** + * Проверить, разблокировано ли достижение + */ + public static boolean isUnlocked(Achievement achievement) { + return unlocked.contains(achievement); + } + + /** + * Получить количество разблокированных достижений + */ + public static int getUnlockedCount() { + return unlocked.size(); + } + + /** + * Получить общее количество достижений + */ + public static int getTotalCount() { + return Achievement.values().length; + } + + /** + * Получить последнее разблокированное достижение (для показа попапа) + */ + public static Achievement getLastUnlocked() { + return lastUnlocked; + } + + /** + * Показывается ли сейчас попап + */ + public static boolean isShowingPopup() { + return popupTimer > 0 && lastUnlocked != null; + } + + /** + * Получить прогресс попапа (0-1) + */ + public static float getPopupProgress() { + return popupTimer / POPUP_DURATION; + } + + // Сериализация разблокированных достижений в строку + public static String getUnlockedAsString() { + if (unlocked.isEmpty()) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + for (Achievement a : unlocked) { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(a.getId()); + } + return sb.toString(); + } + + // Загрузка достижений из строки + + public static void loadFromString(String data) { + unlocked.clear(); + + if (data == null || data.isEmpty()) { + return; + } + + String[] ids = data.split(","); + for (String id : ids) { + Achievement a = Achievement.fromId(id.trim()); + if (a != null) { + unlocked.add(a); + } + } + } + + // Сбросить все достижения + public static void reset() { + unlocked.clear(); + lastUnlocked = null; + popupTimer = 0; + } + + // Получить все разблокированные достижения + public static Set getUnlocked() { + return new HashSet<>(unlocked); + } + + // Получить все достижения + public static Achievement[] getAll() { + return Achievement.values(); + } +} diff --git a/core/src/main/java/com/mygdx/game/AnswerChecker.java b/core/src/main/java/com/mygdx/game/AnswerChecker.java index 159a802..6b78928 100644 --- a/core/src/main/java/com/mygdx/game/AnswerChecker.java +++ b/core/src/main/java/com/mygdx/game/AnswerChecker.java @@ -3,78 +3,10 @@ package com.mygdx.game; import com.badlogic.gdx.graphics.Color; public class AnswerChecker { - private static final String[][] FUNNY_COMMENTS_BY_PLANET = { - // Земля - { - "Вау! Такое здание видел только в мультиках!", - "Архитектор сошел с ума от радости!", - "Город стал похож на мультфильм!", - "Это самое безумное здание в городе!", - "Жители в восторге от этой абсурдности!", - "Эй, это похоже на город из моих снов!", - "Такое здание украсит любой мультфильм!" - }, - // Марс - { - "Отлично! Марсианская колония растёт! 🚀", - "На Марсе теперь есть своё безумие!", - "Эти здания переживут любую пылевую бурю!", - "Марсиане будут в восторге! 👽", - "Похоже, мы колонизируем Марс!", - "Красная планета стала разноцветнее!", - "Это здание выглядит инопланетно круто!" - }, - // Венера - { - "Горячо! Венерианский шедевр готов! 🔥", - "Здание плавится от собственной красоты!", - "Венера стала ещё ярче! 🌟", - "Это здание сияет как сама Венера!", - "Похоже, мы выживаем на Венере!", - "Такая красота плавит сердце!", - "Золотой век венерианской архитектуры!" - } - }; - - private static final String[][] WRONG_ANSWER_JOKES_BY_PLANET = { - // Земля - { - "Твоя математика кривее моих зданий!", - "Даже мультяшный архитектор считает лучше!", - "Ты что, в мультиках учился математике?", - "Ошибка! Попробуй посчитать на пальцах ног!", - "Неправильно! Давай еще разочек, как в мультике!", - "Бывает! Даже мультяшные гении ошибаются!", - "Ой, кажется, ты перепутал с мультипликацией!", - "Неверно! Но зато здание выглядит смешнее!" - }, - // Марс - { - "Неверно! Марсиане считают лучше! 👽", - "Ошибка в расчётах! Пылевая буря съела цифры!", - "Твоя математика не переживёт марсианскую зиму!", - "Неудача! Даже марсоход считает точнее!", - "Неправильно! Попробуй считать в скафандре!", - "Ошибка! Кислородное голодание сказывается?", - "Марсианские калькуляторы не одобряют!", - "Неверно! Может, радиация помешала?" - }, - // Венера - { - "Горячая ошибка! 🔥 Попробуй ещё!", - "Неверно! Даже венерианская жара не оправдывает!", - "Ошибка! Кислотные облака затуманили разум?", - "Неправильно! Слишком жарко для точных расчётов?", - "Провал! Венерианские калькуляторы плавятся!", - "Неудача! Давление в 90 атмосфер давит на мозги?", - "Ошибка! Попробуй считать в теплозащитном костюме!", - "Неверно! Золотое сечение не спасло!" - } - }; public static void checkAnswer(AbsurdCityBuilder1 game) { if (game.getCurrentBuilding() == null || game.getInputText().length() == 0) { - game.setMessageText("Введите ответ!"); + game.setMessageText(Localization.isRu() ? "Введите ответ!" : "Enter an answer!"); game.setMessageColor(Color.RED); return; } @@ -82,22 +14,32 @@ public class AnswerChecker { try { int userAnswer = Integer.parseInt(game.getInputText().toString()); Planet currentPlanet = game.getCurrentPlanet(); - int planetIndex = currentPlanet.ordinal(); if (userAnswer == game.getCurrentProblem().getAnswer()) { // Правильный ответ game.getCurrentBuilding().addBlock(); + + // Увеличиваем счетчик серии правильных ответов + GameSave.addCorrectAnswer(); - String[] planetComments = FUNNY_COMMENTS_BY_PLANET[planetIndex]; - String successMessage = "Отлично! Блок построен!"; + String[] planetComments = Localization.getSuccessComments(currentPlanet); + String successMessage = Localization.blockBuilt(); if (game.getCurrentBuilding().isComplete()) { - successMessage = "Успех! " + planetComments[game.getRandom().nextInt(planetComments.length)]; + successMessage = Localization.buildingComplete() + " " + + planetComments[game.getRandom().nextInt(planetComments.length)]; game.getBuildings().add(game.getCurrentBuilding()); // Создаем жителей при завершении здания game.getCurrentBuilding().createCitizensForBuilding(game.getCitizens(), game.getRandom()); + // Добавляем здание в статистику и сохраняем + GameSave.addBuilding(currentPlanet); + GameSave.saveSettings(); + + // Проверяем достижения + Achievements.check(game); + // Проверяем разблокировку планет checkPlanetUnlock(game); @@ -114,8 +56,11 @@ public class AnswerChecker { } else { // Неправильный ответ game.getCurrentBuilding().removeBlock(); + + // Сбрасываем счетчик серии + GameSave.resetCorrectStreak(); - String[] planetJokes = WRONG_ANSWER_JOKES_BY_PLANET[planetIndex]; + String[] planetJokes = Localization.getWrongAnswerJokes(currentPlanet); String joke = planetJokes[game.getRandom().nextInt(planetJokes.length)]; game.setWrongAnswerJoke(joke); game.setShowWrongAnswerJoke(true); @@ -129,12 +74,12 @@ public class AnswerChecker { String message; if (game.getCurrentBuilding().constructionProgress == 0) { - message = "Здание разрушено до основания! " + joke; + message = (Localization.isRu() ? "Здание разрушено до основания! " : "Building destroyed! ") + joke; game.setCurrentBuilding(null); game.setCurrentProblem(null); game.setTyping(false); } else { - message = "Неверно! Блок разрушен! " + joke; + message = Localization.wrongAnswer() + " " + joke; game.setCurrentProblem(MathProblem.generateProblem(game.getBuildings().size, game.getRandom())); } @@ -147,21 +92,7 @@ public class AnswerChecker { } catch (NumberFormatException e) { // Обработка некорректного ввода - Planet currentPlanet = game.getCurrentPlanet(); - String errorMessage; - - switch (currentPlanet) { - case MARS: - errorMessage = "Марсиане не понимают такие цифры! Введите целое число!"; - break; - case VENUS: - errorMessage = "Слишком жарко для таких символов! Введите целое число!"; - break; - default: - errorMessage = "Введите целое число!"; - } - - game.setMessageText(errorMessage); + game.setMessageText(Localization.enterNumber()); game.setMessageColor(Color.RED); game.getInputText().setLength(0); } @@ -173,19 +104,22 @@ public class AnswerChecker { // Проверяем условия для разблокировки Марса if (currentPlanet == Planet.EARTH && buildingsCount >= 3) { - // Марс уже разблокирован по умолчанию в нашей реализации - // Но можно добавить специальное сообщение if (buildingsCount == 3) { - game.setMessageText(game.getMessageText() + " 🚀 Марс доступен! Нажмите ↑ для полёта!"); + String extra = Localization.isRu() + ? " 🚀 Марс доступен! Нажмите ↑ для полёта!" + : " 🚀 Mars unlocked! Press ↑ to fly!"; + game.setMessageText(game.getMessageText() + extra); game.setMessageColor(Color.CYAN); } } // Проверяем условия для разблокировки Венеры if (currentPlanet == Planet.MARS && buildingsCount >= 6) { - // Венера уже разблокирована if (buildingsCount == 6) { - game.setMessageText(game.getMessageText() + " 🔥 Венера доступна! Нажмите ↑ для полёта!"); + String extra = Localization.isRu() + ? " 🔥 Венера доступна! Нажмите ↑ для полёта!" + : " 🔥 Venus unlocked! Press ↑ to fly!"; + game.setMessageText(game.getMessageText() + extra); game.setMessageColor(Color.ORANGE); } } @@ -198,52 +132,95 @@ public class AnswerChecker { } private static String getBonusMessage(Planet planet, int buildingsCount) { - switch (planet) { - case EARTH: - return "🎉 Вы построили " + buildingsCount + " зданий на Земле!"; - case MARS: - return "👽 Марсианская колония из " + buildingsCount + " зданий!"; - case VENUS: - return "🌟 Венерианский мегаполис из " + buildingsCount + " зданий!"; - default: - return "🏆 Достижение: " + buildingsCount + " зданий!"; + if (Localization.isRu()) { + switch (planet) { + case EARTH: + return "🎉 Вы построили " + buildingsCount + " зданий на Земле!"; + case MARS: + return "👽 Марсианская колония из " + buildingsCount + " зданий!"; + case VENUS: + return "🌟 Венерианский мегаполис из " + buildingsCount + " зданий!"; + default: + return "🏆 Достижение: " + buildingsCount + " зданий!"; + } + } else { + switch (planet) { + case EARTH: + return "🎉 You built " + buildingsCount + " buildings on Earth!"; + case MARS: + return "👽 Martian colony of " + buildingsCount + " buildings!"; + case VENUS: + return "🌟 Venusian metropolis of " + buildingsCount + " buildings!"; + default: + return "🏆 Achievement: " + buildingsCount + " buildings!"; + } } } - // Метод для получения подсказки (опционально) + // Метод для получения подсказки public static String getHint(MathProblem problem, Planet planet) { - int answer = problem.getAnswer(); String question = problem.getQuestion(); - switch (planet) { - case MARS: - if (question.contains("+")) { - return "Подсказка: складывай как марсиане - от красного к красному!"; - } else if (question.contains("-")) { - return "Подсказка: вычитай как улетающую ракету!"; - } else if (question.contains("×")) { - return "Подсказка: умножай на количество марсоходов!"; - } - break; - case VENUS: - if (question.contains("+")) { - return "Подсказка: складывай жар как на Венере!"; - } else if (question.contains("-")) { - return "Подсказка: вычитай облака кислоты!"; - } else if (question.contains("×")) { - return "Подсказка: умножай как давление на Венере!"; - } - break; - default: - if (question.contains("+")) { - return "Подсказка: представь, что складываешь мультяшных зверюшек!"; - } else if (question.contains("-")) { - return "Подсказка: убери лишние мультяшные детали!"; - } else if (question.contains("×")) { - return "Подсказка: умножай как в мультике - всё становится больше!"; - } + if (Localization.isRu()) { + switch (planet) { + case MARS: + if (question.contains("+")) { + return "Подсказка: складывай как марсиане - от красного к красному!"; + } else if (question.contains("-")) { + return "Подсказка: вычитай как улетающую ракету!"; + } else if (question.contains("×")) { + return "Подсказка: умножай на количество марсоходов!"; + } + break; + case VENUS: + if (question.contains("+")) { + return "Подсказка: складывай жар как на Венере!"; + } else if (question.contains("-")) { + return "Подсказка: вычитай облака кислоты!"; + } else if (question.contains("×")) { + return "Подсказка: умножай как давление на Венере!"; + } + break; + default: + if (question.contains("+")) { + return "Подсказка: представь, что складываешь мультяшных зверюшек!"; + } else if (question.contains("-")) { + return "Подсказка: убери лишние мультяшные детали!"; + } else if (question.contains("×")) { + return "Подсказка: умножай как в мультике - всё становится больше!"; + } + } + return "Подсказка: внимательно посчитай!"; + } else { + switch (planet) { + case MARS: + if (question.contains("+")) { + return "Hint: add like Martians - from red to red!"; + } else if (question.contains("-")) { + return "Hint: subtract like a flying rocket!"; + } else if (question.contains("×")) { + return "Hint: multiply by the number of rovers!"; + } + break; + case VENUS: + if (question.contains("+")) { + return "Hint: add heat like on Venus!"; + } else if (question.contains("-")) { + return "Hint: subtract acid clouds!"; + } else if (question.contains("×")) { + return "Hint: multiply like Venus pressure!"; + } + break; + default: + if (question.contains("+")) { + return "Hint: imagine adding cartoon creatures!"; + } else if (question.contains("-")) { + return "Hint: remove extra cartoon details!"; + } else if (question.contains("×")) { + return "Hint: multiply like in cartoons - everything gets bigger!"; + } + } + return "Hint: calculate carefully!"; } - - return "Подсказка: внимательно посчитай!"; } } diff --git a/core/src/main/java/com/mygdx/game/Building.java b/core/src/main/java/com/mygdx/game/Building.java index 0d8b8bd..8da82d5 100644 --- a/core/src/main/java/com/mygdx/game/Building.java +++ b/core/src/main/java/com/mygdx/game/Building.java @@ -6,302 +6,13 @@ import com.badlogic.gdx.utils.Array; import java.util.Random; public class Building { - // Названия зданий по планетам - public static final String[][] BUILDING_TYPES_BY_PLANET = { - // Земля (существующие здания) - { - "✨ Уютный Домик ✨", - "🏥 Детская Больница 🏥", - "🎒 Весёлая Школа 🎒", - "🎪 Игровая Площадка 🎪", - "💰 Надёжный Банк 💰", - "💊 Здоровая Аптека 💊", - "🎭 Волшебный Театр 🎭", - "🎬 КиноМир 🎬" - }, - // Марс (красные, технологичные) - { - "🚀 Марсианская База 🚀", - "🔴 Красная Лаборатория 🔴", - "🛰️ Космопорт 🛰️", - "⚡ Энергокупол ⚡", - "💧 Водородный Завод 💧", - "🌌 Обсерватория 🌌", - "🤖 Робо-Фабрика 🤖", - "🧪 Биокупол 🧪" - }, - // Венера (желтые, вулканические) - { - "🌋 Вулканический Дом 🌋", - "🔥 Термальная Станция 🔥", - "🌅 Золотой Дворец 🌅", - "☁️ Облачный Город ☁️", - "💎 Кристальная Шахта 💎", - "🌡️ Теплица 🌡️", - "🌀 Вихревой Генератор 🌀", - "✨ Сияющая Башня ✨" - } - }; - - // Яркие цвета для разных планет - public static final Color[][][] BUILDING_COLOR_THEMES_BY_PLANET = { - // 0. Земля - тёплые цвета - { - // Дома - тёплые цвета - { - new Color(1.0f, 0.85f, 0.7f, 1), // Персиковый - new Color(0.95f, 0.9f, 0.75f, 1), // Светло-бежевый - new Color(0.9f, 0.8f, 0.85f, 1) // Розоватый - }, - // Больницы - чистые светлые цвета - { - new Color(1.0f, 1.0f, 1.0f, 1), // Белоснежный - new Color(0.98f, 0.98f, 1.0f, 1), // Голубоватый - new Color(0.96f, 1.0f, 0.98f, 1) // Мятный - }, - // Школы - яркие весёлые цвета - { - new Color(1.0f, 0.95f, 0.8f, 1), // Лимонный - new Color(0.85f, 0.95f, 1.0f, 1), // Небесно-голубой - new Color(0.95f, 0.85f, 1.0f, 1) // Лавандовый - }, - // Игровые площадки - яркие игровые цвета - { - new Color(1.0f, 0.9f, 0.8f, 1), // Абрикосовый - new Color(0.9f, 1.0f, 0.9f, 1), // Салатовый - new Color(0.9f, 0.9f, 1.0f, 1) // Сиреневый - }, - // Банки - солидные цвета - { - new Color(0.95f, 0.95f, 0.9f, 1), // Слоновая кость - new Color(0.9f, 0.92f, 0.85f, 1), // Бежевый - new Color(0.85f, 0.89f, 0.8f, 1) // Оливковый - }, - // Аптеки - медицинские цвета - { - new Color(1.0f, 1.0f, 1.0f, 1), // Белый - new Color(0.98f, 1.0f, 0.98f, 1), // Светло-зелёный - new Color(0.96f, 0.98f, 1.0f, 1) // Светло-голубой - }, - // Театры - благородные цвета - { - new Color(0.95f, 0.9f, 0.95f, 1), // Сиреневый - new Color(0.9f, 0.95f, 1.0f, 1), // Лазурный - new Color(1.0f, 0.95f, 0.9f, 1) // Кремовый - }, - // Кинотеатры - тёмные с неоном - { - new Color(0.2f, 0.2f, 0.3f, 1), // Тёмно-синий - new Color(0.3f, 0.2f, 0.4f, 1), // Фиолетовый - new Color(0.4f, 0.3f, 0.5f, 1) // Пурпурный - } - }, - // 1. Марс - красные, оранжевые, коричневые - { - // Марсианская База - { - new Color(0.8f, 0.3f, 0.2f, 1), // Красный марсианский - new Color(0.9f, 0.5f, 0.3f, 1), // Оранжевый - new Color(0.7f, 0.4f, 0.3f, 1) // Коричневый - }, - // Красная Лаборатория - { - new Color(0.9f, 0.4f, 0.4f, 1), - new Color(1.0f, 0.6f, 0.5f, 1), - new Color(0.8f, 0.5f, 0.5f, 1) - }, - // Космопорт - { - new Color(0.7f, 0.5f, 0.4f, 1), - new Color(0.8f, 0.6f, 0.5f, 1), - new Color(0.6f, 0.4f, 0.3f, 1) - }, - // Энергокупол - { - new Color(0.9f, 0.6f, 0.3f, 1), - new Color(1.0f, 0.7f, 0.4f, 1), - new Color(0.8f, 0.5f, 0.2f, 1) - }, - // Водородный Завод - { - new Color(0.6f, 0.7f, 0.8f, 1), - new Color(0.7f, 0.8f, 0.9f, 1), - new Color(0.5f, 0.6f, 0.7f, 1) - }, - // Обсерватория - { - new Color(0.3f, 0.4f, 0.6f, 1), - new Color(0.4f, 0.5f, 0.7f, 1), - new Color(0.2f, 0.3f, 0.5f, 1) - }, - // Робо-Фабрика - { - new Color(0.5f, 0.5f, 0.5f, 1), - new Color(0.6f, 0.6f, 0.6f, 1), - new Color(0.4f, 0.4f, 0.4f, 1) - }, - // Биокупол - { - new Color(0.4f, 0.7f, 0.4f, 1), - new Color(0.5f, 0.8f, 0.5f, 1), - new Color(0.3f, 0.6f, 0.3f, 1) - } - }, - // 2. Венера - желтые, золотые, оранжевые - { - // Вулканический Дом - { - new Color(1.0f, 0.7f, 0.3f, 1), // Золотистый - new Color(1.0f, 0.8f, 0.4f, 1), // Желтый - new Color(0.9f, 0.6f, 0.2f, 1) // Оранжевый - }, - // Термальная Станция - { - new Color(1.0f, 0.6f, 0.2f, 1), - new Color(1.0f, 0.7f, 0.3f, 1), - new Color(0.9f, 0.5f, 0.1f, 1) - }, - // Золотой Дворец - { - new Color(1.0f, 0.9f, 0.3f, 1), - new Color(1.0f, 1.0f, 0.5f, 1), - new Color(0.9f, 0.8f, 0.2f, 1) - }, - // Облачный Город - { - new Color(1.0f, 0.95f, 0.8f, 1), - new Color(1.0f, 1.0f, 0.9f, 1), - new Color(0.95f, 0.9f, 0.7f, 1) - }, - // Кристальная Шахта - { - new Color(0.8f, 0.9f, 1.0f, 1), - new Color(0.9f, 1.0f, 1.0f, 1), - new Color(0.7f, 0.8f, 0.9f, 1) - }, - // Теплица - { - new Color(0.7f, 0.9f, 0.6f, 1), - new Color(0.8f, 1.0f, 0.7f, 1), - new Color(0.6f, 0.8f, 0.5f, 1) - }, - // Вихревой Генератор - { - new Color(0.9f, 0.8f, 0.5f, 1), - new Color(1.0f, 0.9f, 0.6f, 1), - new Color(0.8f, 0.7f, 0.4f, 1) - }, - // Сияющая Башня - { - new Color(1.0f, 0.95f, 0.7f, 1), - new Color(1.0f, 1.0f, 0.8f, 1), - new Color(0.95f, 0.9f, 0.6f, 1) - } - } - }; - - // Крыши в мультяшных цветах по планетам - public static final Color[][][] ROOF_COLORS_BY_PLANET = { - // Земля - { - { new Color(0.9f, 0.3f, 0.2f, 1), new Color(0.7f, 0.4f, 0.2f, 1) }, // Дома - { new Color(1.0f, 0.8f, 0.8f, 1), new Color(0.9f, 0.7f, 0.7f, 1) }, // Больницы - { new Color(0.4f, 0.7f, 1.0f, 1), new Color(0.3f, 0.6f, 0.9f, 1) }, // Школы - { new Color(1.0f, 0.8f, 0.4f, 1), new Color(0.9f, 0.5f, 0.9f, 1) }, // Площадки - { new Color(1.0f, 0.9f, 0.3f, 1), new Color(0.9f, 0.8f, 0.2f, 1) }, // Банки - { new Color(0.4f, 0.9f, 0.5f, 1), new Color(0.3f, 0.8f, 0.4f, 1) }, // Аптеки - { new Color(0.8f, 0.4f, 1.0f, 1), new Color(0.7f, 0.3f, 0.9f, 1) }, // Театры - { new Color(0.3f, 0.3f, 0.4f, 1), new Color(0.4f, 0.3f, 0.5f, 1) } // Кинотеатры - }, - // Марс - { - { new Color(0.7f, 0.2f, 0.1f, 1), new Color(0.6f, 0.1f, 0.0f, 1) }, // Марсианская База - { new Color(0.8f, 0.3f, 0.2f, 1), new Color(0.7f, 0.2f, 0.1f, 1) }, // Красная Лаборатория - { new Color(0.5f, 0.4f, 0.3f, 1), new Color(0.4f, 0.3f, 0.2f, 1) }, // Космопорт - { new Color(0.8f, 0.5f, 0.2f, 1), new Color(0.7f, 0.4f, 0.1f, 1) }, // Энергокупол - { new Color(0.4f, 0.5f, 0.7f, 1), new Color(0.3f, 0.4f, 0.6f, 1) }, // Водородный Завод - { new Color(0.2f, 0.3f, 0.5f, 1), new Color(0.1f, 0.2f, 0.4f, 1) }, // Обсерватория - { new Color(0.4f, 0.4f, 0.4f, 1), new Color(0.3f, 0.3f, 0.3f, 1) }, // Робо-Фабрика - { new Color(0.3f, 0.6f, 0.3f, 1), new Color(0.2f, 0.5f, 0.2f, 1) } // Биокупол - }, - // Венера - { - { new Color(0.8f, 0.4f, 0.1f, 1), new Color(0.7f, 0.3f, 0.0f, 1) }, // Вулканический Дом - { new Color(0.9f, 0.5f, 0.1f, 1), new Color(0.8f, 0.4f, 0.0f, 1) }, // Термальная Станция - { new Color(1.0f, 0.8f, 0.1f, 1), new Color(0.9f, 0.7f, 0.0f, 1) }, // Золотой Дворец - { new Color(1.0f, 1.0f, 0.8f, 1), new Color(0.9f, 0.9f, 0.7f, 1) }, // Облачный Город - { new Color(0.7f, 0.8f, 0.9f, 1), new Color(0.6f, 0.7f, 0.8f, 1) }, // Кристальная Шахта - { new Color(0.6f, 0.8f, 0.5f, 1), new Color(0.5f, 0.7f, 0.4f, 1) }, // Теплица - { new Color(0.8f, 0.7f, 0.4f, 1), new Color(0.7f, 0.6f, 0.3f, 1) }, // Вихревой Генератор - { new Color(0.95f, 0.9f, 0.6f, 1), new Color(0.85f, 0.8f, 0.5f, 1) } // Сияющая Башня - } - }; - - // Коэффициенты масштабирования для разных планет - public static final float[][] SIZE_SCALE_FACTORS_BY_PLANET = { - // Земля - {1.0f, 0.75f, 0.8f, 0.85f, 0.7f, 0.65f, 0.8f, 0.85f}, - // Марс (компактнее) - {0.9f, 0.7f, 0.8f, 0.75f, 0.65f, 0.6f, 0.7f, 0.75f}, - // Венера (выше) - {1.1f, 1.0f, 1.05f, 1.0f, 0.9f, 0.85f, 1.0f, 1.05f} - }; - - // Цвета для деталей по планетам - public static final Color[][] DETAIL_COLORS_BY_PLANET = { - // Земля - { - new Color(1.0f, 0.9f, 0.2f, 1), // Золотой - new Color(1.0f, 0.5f, 0.5f, 1), // Коралловый - new Color(0.5f, 0.8f, 1.0f, 1), // Голубой - new Color(0.8f, 1.0f, 0.5f, 1), // Лаймовый - new Color(1.0f, 0.7f, 1.0f, 1) // Розовый - }, - // Марс - { - new Color(1.0f, 0.6f, 0.2f, 1), // Оранжевый - new Color(0.8f, 0.3f, 0.2f, 1), // Красный - new Color(0.9f, 0.8f, 0.4f, 1), // Песочный - new Color(0.7f, 0.8f, 0.9f, 1), // Стальной - new Color(0.4f, 0.7f, 0.4f, 1) // Зеленый марсианский - }, - // Венера - { - new Color(1.0f, 0.9f, 0.3f, 1), // Золотой - new Color(1.0f, 0.7f, 0.2f, 1), // Янтарный - new Color(1.0f, 1.0f, 0.8f, 1), // Светло-желтый - new Color(0.9f, 0.6f, 0.1f, 1), // Темно-оранжевый - new Color(0.8f, 0.9f, 1.0f, 1) // Кристальный - } - }; - - // Цвета для названий по планетам - public static final Color[][] GLOWING_NAME_COLORS_BY_PLANET = { - // Земля - { - new Color(0.3f, 0.7f, 1.0f, 1), // Ярко-синий - new Color(1.0f, 0.4f, 0.4f, 1), // Ярко-красный - new Color(0.3f, 0.9f, 0.3f, 1), // Ярко-зелёный - new Color(1.0f, 0.7f, 0.2f, 1), // Оранжевый - new Color(0.8f, 0.4f, 1.0f, 1) // Фиолетовый - }, - // Марс - { - new Color(1.0f, 0.5f, 0.3f, 1), // Оранжево-красный - new Color(0.8f, 0.3f, 0.2f, 1), // Марсианский красный - new Color(0.9f, 0.7f, 0.4f, 1), // Песочный - new Color(0.6f, 0.8f, 0.9f, 1), // Голубой стальной - new Color(0.4f, 0.6f, 0.3f, 1) // Оливковый - }, - // Венера - { - new Color(1.0f, 0.9f, 0.3f, 1), // Золотой - new Color(1.0f, 0.7f, 0.2f, 1), // Янтарный - new Color(1.0f, 1.0f, 0.6f, 1), // Ярко-желтый - new Color(0.9f, 0.5f, 0.1f, 1), // Теплый оранжевый - new Color(1.0f, 0.95f, 0.8f, 1) // Светло-золотой - } - }; + // Ссылки на данные из GameConfig для обратной совместимости + public static final String[][] BUILDING_TYPES_BY_PLANET = GameConfig.BUILDING_TYPES_BY_PLANET; + public static final Color[][][] BUILDING_COLOR_THEMES_BY_PLANET = GameConfig.BUILDING_COLOR_THEMES_BY_PLANET; + public static final Color[][][] ROOF_COLORS_BY_PLANET = GameConfig.ROOF_COLORS_BY_PLANET; + public static final float[][] SIZE_SCALE_FACTORS_BY_PLANET = GameConfig.SIZE_SCALE_FACTORS_BY_PLANET; + public static final Color[][] DETAIL_COLORS_BY_PLANET = GameConfig.DETAIL_COLORS_BY_PLANET; + public static final Color[][] GLOWING_NAME_COLORS_BY_PLANET = GameConfig.GLOWING_NAME_COLORS_BY_PLANET; String type; float x; diff --git a/core/src/main/java/com/mygdx/game/GameConfig.java b/core/src/main/java/com/mygdx/game/GameConfig.java new file mode 100644 index 0000000..0eab815 --- /dev/null +++ b/core/src/main/java/com/mygdx/game/GameConfig.java @@ -0,0 +1,252 @@ +package com.mygdx.game; + +import com.badlogic.gdx.graphics.Color; + +/** + * Конфигурация игры - все цвета, константы и настройки в одном месте. + */ +public class GameConfig { + + // ==================== РАЗМЕРЫ ЭКРАНА ==================== + public static final int WIDTH = 1700; + public static final int HEIGHT = 950; + public static final int UI_INPUT_HEIGHT = 210; + + // ==================== ЦВЕТА UI ==================== + public static final Color UI_PANEL_BG = new Color(0.2f, 0.3f, 0.4f, 0.95f); + public static final Color UI_PANEL_BORDER = new Color(0.4f, 0.6f, 0.8f, 1f); + public static final Color UI_INPUT_BG = new Color(0.3f, 0.4f, 0.5f, 0.8f); + public static final Color UI_WRONG_ANSWER_BG = new Color(1f, 0.2f, 0.2f, 0.3f); + + // ==================== ЦВЕТА МЕНЮ ==================== + public static final Color MENU_SPACE_BG = new Color(0.05f, 0.05f, 0.1f, 1f); + public static final Color MENU_BUTTON_BORDER = new Color(1f, 1f, 1f, 0.3f); + public static final Color MENU_BUTTON_HOVER = new Color(1f, 1f, 1f, 0.1f); + + // Цвета кнопок главного меню + public static final Color BUTTON_NEW_GAME = new Color(0.2f, 0.5f, 0.8f, 0.9f); + public static final Color BUTTON_NEW_GAME_HOVER = new Color(0.3f, 0.6f, 0.9f, 1f); + public static final Color BUTTON_PLANET = new Color(0.8f, 0.4f, 0.2f, 0.9f); + public static final Color BUTTON_PLANET_HOVER = new Color(0.9f, 0.5f, 0.3f, 1f); + public static final Color BUTTON_HELP = new Color(0.2f, 0.7f, 0.3f, 0.9f); + public static final Color BUTTON_HELP_HOVER = new Color(0.3f, 0.8f, 0.4f, 1f); + public static final Color BUTTON_ABOUT = new Color(0.7f, 0.2f, 0.7f, 0.9f); + public static final Color BUTTON_ABOUT_HOVER = new Color(0.8f, 0.3f, 0.8f, 1f); + public static final Color BUTTON_EXIT = new Color(0.8f, 0.2f, 0.2f, 0.9f); + public static final Color BUTTON_EXIT_HOVER = new Color(0.9f, 0.3f, 0.3f, 1f); + public static final Color BUTTON_BACK = new Color(0.4f, 0.4f, 0.4f, 0.9f); + public static final Color BUTTON_BACK_HOVER = new Color(0.5f, 0.5f, 0.5f, 1f); + + // Цвета кнопок планет + public static final Color BUTTON_EARTH = new Color(0.3f, 0.6f, 0.9f, 0.9f); + public static final Color BUTTON_EARTH_HOVER = new Color(0.4f, 0.7f, 1.0f, 1f); + public static final Color BUTTON_MARS = new Color(0.8f, 0.3f, 0.2f, 0.9f); + public static final Color BUTTON_MARS_HOVER = new Color(0.9f, 0.4f, 0.3f, 1f); + public static final Color BUTTON_VENUS = new Color(1.0f, 0.7f, 0.2f, 0.9f); + public static final Color BUTTON_VENUS_HOVER = new Color(1.0f, 0.8f, 0.3f, 1f); + + // ==================== НАЗВАНИЯ ЗДАНИЙ ПО ПЛАНЕТАМ ==================== + public static final String[][] BUILDING_TYPES_BY_PLANET = { + // Земля + { + "✨ Уютный Домик ✨", + "🏥 Детская Больница 🏥", + "🎒 Весёлая Школа 🎒", + "🎪 Игровая Площадка 🎪", + "💰 Надёжный Банк 💰", + "💊 Здоровая Аптека 💊", + "🎭 Волшебный Театр 🎭", + "🎬 КиноМир 🎬" + }, + // Марс + { + "🚀 Марсианская База 🚀", + "🔴 Красная Лаборатория 🔴", + "🛰️ Космопорт 🛰️", + "⚡ Энергокупол ⚡", + "💧 Водородный Завод 💧", + "🌌 Обсерватория 🌌", + "🤖 Робо-Фабрика 🤖", + "🧪 Биокупол 🧪" + }, + // Венера + { + "🌋 Вулканический Дом 🌋", + "🔥 Термальная Станция 🔥", + "🌅 Золотой Дворец 🌅", + "☁️ Облачный Город ☁️", + "💎 Кристальная Шахта 💎", + "🌡️ Теплица 🌡️", + "🌀 Вихревой Генератор 🌀", + "✨ Сияющая Башня ✨" + } + }; + + // ==================== ЦВЕТА ЗДАНИЙ ПО ПЛАНЕТАМ ==================== + public static final Color[][][] BUILDING_COLOR_THEMES_BY_PLANET = { + // 0. Земля - тёплые цвета + { + // Дома + { new Color(1.0f, 0.85f, 0.7f, 1), new Color(0.95f, 0.9f, 0.75f, 1), new Color(0.9f, 0.8f, 0.85f, 1) }, + // Больницы + { new Color(1.0f, 1.0f, 1.0f, 1), new Color(0.98f, 0.98f, 1.0f, 1), new Color(0.96f, 1.0f, 0.98f, 1) }, + // Школы + { new Color(1.0f, 0.95f, 0.8f, 1), new Color(0.85f, 0.95f, 1.0f, 1), new Color(0.95f, 0.85f, 1.0f, 1) }, + // Игровые площадки + { new Color(1.0f, 0.9f, 0.8f, 1), new Color(0.9f, 1.0f, 0.9f, 1), new Color(0.9f, 0.9f, 1.0f, 1) }, + // Банки + { new Color(0.95f, 0.95f, 0.9f, 1), new Color(0.9f, 0.92f, 0.85f, 1), new Color(0.85f, 0.89f, 0.8f, 1) }, + // Аптеки + { new Color(1.0f, 1.0f, 1.0f, 1), new Color(0.98f, 1.0f, 0.98f, 1), new Color(0.96f, 0.98f, 1.0f, 1) }, + // Театры + { new Color(0.95f, 0.9f, 0.95f, 1), new Color(0.9f, 0.95f, 1.0f, 1), new Color(1.0f, 0.95f, 0.9f, 1) }, + // Кинотеатры + { new Color(0.2f, 0.2f, 0.3f, 1), new Color(0.3f, 0.2f, 0.4f, 1), new Color(0.4f, 0.3f, 0.5f, 1) } + }, + // 1. Марс - красные, оранжевые, коричневые + { + { new Color(0.8f, 0.3f, 0.2f, 1), new Color(0.9f, 0.5f, 0.3f, 1), new Color(0.7f, 0.4f, 0.3f, 1) }, + { new Color(0.9f, 0.4f, 0.4f, 1), new Color(1.0f, 0.6f, 0.5f, 1), new Color(0.8f, 0.5f, 0.5f, 1) }, + { new Color(0.7f, 0.5f, 0.4f, 1), new Color(0.8f, 0.6f, 0.5f, 1), new Color(0.6f, 0.4f, 0.3f, 1) }, + { new Color(0.9f, 0.6f, 0.3f, 1), new Color(1.0f, 0.7f, 0.4f, 1), new Color(0.8f, 0.5f, 0.2f, 1) }, + { new Color(0.6f, 0.7f, 0.8f, 1), new Color(0.7f, 0.8f, 0.9f, 1), new Color(0.5f, 0.6f, 0.7f, 1) }, + { new Color(0.3f, 0.4f, 0.6f, 1), new Color(0.4f, 0.5f, 0.7f, 1), new Color(0.2f, 0.3f, 0.5f, 1) }, + { new Color(0.5f, 0.5f, 0.5f, 1), new Color(0.6f, 0.6f, 0.6f, 1), new Color(0.4f, 0.4f, 0.4f, 1) }, + { new Color(0.4f, 0.7f, 0.4f, 1), new Color(0.5f, 0.8f, 0.5f, 1), new Color(0.3f, 0.6f, 0.3f, 1) } + }, + // 2. Венера - желтые, золотые, оранжевые + { + { new Color(1.0f, 0.7f, 0.3f, 1), new Color(1.0f, 0.8f, 0.4f, 1), new Color(0.9f, 0.6f, 0.2f, 1) }, + { new Color(1.0f, 0.6f, 0.2f, 1), new Color(1.0f, 0.7f, 0.3f, 1), new Color(0.9f, 0.5f, 0.1f, 1) }, + { new Color(1.0f, 0.9f, 0.3f, 1), new Color(1.0f, 1.0f, 0.5f, 1), new Color(0.9f, 0.8f, 0.2f, 1) }, + { new Color(1.0f, 0.95f, 0.8f, 1), new Color(1.0f, 1.0f, 0.9f, 1), new Color(0.95f, 0.9f, 0.7f, 1) }, + { new Color(0.8f, 0.9f, 1.0f, 1), new Color(0.9f, 1.0f, 1.0f, 1), new Color(0.7f, 0.8f, 0.9f, 1) }, + { new Color(0.7f, 0.9f, 0.6f, 1), new Color(0.8f, 1.0f, 0.7f, 1), new Color(0.6f, 0.8f, 0.5f, 1) }, + { new Color(0.9f, 0.8f, 0.5f, 1), new Color(1.0f, 0.9f, 0.6f, 1), new Color(0.8f, 0.7f, 0.4f, 1) }, + { new Color(1.0f, 0.95f, 0.7f, 1), new Color(1.0f, 1.0f, 0.8f, 1), new Color(0.95f, 0.9f, 0.6f, 1) } + } + }; + + // ==================== ЦВЕТА КРЫШ ПО ПЛАНЕТАМ ==================== + public static final Color[][][] ROOF_COLORS_BY_PLANET = { + // Земля + { + { new Color(0.9f, 0.3f, 0.2f, 1), new Color(0.7f, 0.4f, 0.2f, 1) }, + { new Color(1.0f, 0.8f, 0.8f, 1), new Color(0.9f, 0.7f, 0.7f, 1) }, + { new Color(0.4f, 0.7f, 1.0f, 1), new Color(0.3f, 0.6f, 0.9f, 1) }, + { new Color(1.0f, 0.8f, 0.4f, 1), new Color(0.9f, 0.5f, 0.9f, 1) }, + { new Color(1.0f, 0.9f, 0.3f, 1), new Color(0.9f, 0.8f, 0.2f, 1) }, + { new Color(0.4f, 0.9f, 0.5f, 1), new Color(0.3f, 0.8f, 0.4f, 1) }, + { new Color(0.8f, 0.4f, 1.0f, 1), new Color(0.7f, 0.3f, 0.9f, 1) }, + { new Color(0.3f, 0.3f, 0.4f, 1), new Color(0.4f, 0.3f, 0.5f, 1) } + }, + // Марс + { + { new Color(0.7f, 0.2f, 0.1f, 1), new Color(0.6f, 0.1f, 0.0f, 1) }, + { new Color(0.8f, 0.3f, 0.2f, 1), new Color(0.7f, 0.2f, 0.1f, 1) }, + { new Color(0.5f, 0.4f, 0.3f, 1), new Color(0.4f, 0.3f, 0.2f, 1) }, + { new Color(0.8f, 0.5f, 0.2f, 1), new Color(0.7f, 0.4f, 0.1f, 1) }, + { new Color(0.4f, 0.5f, 0.7f, 1), new Color(0.3f, 0.4f, 0.6f, 1) }, + { new Color(0.2f, 0.3f, 0.5f, 1), new Color(0.1f, 0.2f, 0.4f, 1) }, + { new Color(0.4f, 0.4f, 0.4f, 1), new Color(0.3f, 0.3f, 0.3f, 1) }, + { new Color(0.3f, 0.6f, 0.3f, 1), new Color(0.2f, 0.5f, 0.2f, 1) } + }, + // Венера + { + { new Color(0.8f, 0.4f, 0.1f, 1), new Color(0.7f, 0.3f, 0.0f, 1) }, + { new Color(0.9f, 0.5f, 0.1f, 1), new Color(0.8f, 0.4f, 0.0f, 1) }, + { new Color(1.0f, 0.8f, 0.1f, 1), new Color(0.9f, 0.7f, 0.0f, 1) }, + { new Color(1.0f, 1.0f, 0.8f, 1), new Color(0.9f, 0.9f, 0.7f, 1) }, + { new Color(0.7f, 0.8f, 0.9f, 1), new Color(0.6f, 0.7f, 0.8f, 1) }, + { new Color(0.6f, 0.8f, 0.5f, 1), new Color(0.5f, 0.7f, 0.4f, 1) }, + { new Color(0.8f, 0.7f, 0.4f, 1), new Color(0.7f, 0.6f, 0.3f, 1) }, + { new Color(0.95f, 0.9f, 0.6f, 1), new Color(0.85f, 0.8f, 0.5f, 1) } + } + }; + + // ==================== МАСШТАБЫ ЗДАНИЙ ПО ПЛАНЕТАМ ==================== + public static final float[][] SIZE_SCALE_FACTORS_BY_PLANET = { + // Земля + {1.0f, 0.75f, 0.8f, 0.85f, 0.7f, 0.65f, 0.8f, 0.85f}, + // Марс (компактнее) + {0.9f, 0.7f, 0.8f, 0.75f, 0.65f, 0.6f, 0.7f, 0.75f}, + // Венера (выше) + {1.1f, 1.0f, 1.05f, 1.0f, 0.9f, 0.85f, 1.0f, 1.05f} + }; + + // ==================== ЦВЕТА ДЕТАЛЕЙ ПО ПЛАНЕТАМ ==================== + public static final Color[][] DETAIL_COLORS_BY_PLANET = { + // Земля + { + new Color(1.0f, 0.9f, 0.2f, 1), + new Color(1.0f, 0.5f, 0.5f, 1), + new Color(0.5f, 0.8f, 1.0f, 1), + new Color(0.8f, 1.0f, 0.5f, 1), + new Color(1.0f, 0.7f, 1.0f, 1) + }, + // Марс + { + new Color(1.0f, 0.6f, 0.2f, 1), + new Color(0.8f, 0.3f, 0.2f, 1), + new Color(0.9f, 0.8f, 0.4f, 1), + new Color(0.7f, 0.8f, 0.9f, 1), + new Color(0.4f, 0.7f, 0.4f, 1) + }, + // Венера + { + new Color(1.0f, 0.9f, 0.3f, 1), + new Color(1.0f, 0.7f, 0.2f, 1), + new Color(1.0f, 1.0f, 0.8f, 1), + new Color(0.9f, 0.6f, 0.1f, 1), + new Color(0.8f, 0.9f, 1.0f, 1) + } + }; + + // ==================== ЦВЕТА НАЗВАНИЙ ЗДАНИЙ ПО ПЛАНЕТАМ ==================== + public static final Color[][] GLOWING_NAME_COLORS_BY_PLANET = { + // Земля + { + new Color(0.3f, 0.7f, 1.0f, 1), + new Color(1.0f, 0.4f, 0.4f, 1), + new Color(0.3f, 0.9f, 0.3f, 1), + new Color(1.0f, 0.7f, 0.2f, 1), + new Color(0.8f, 0.4f, 1.0f, 1) + }, + // Марс + { + new Color(1.0f, 0.5f, 0.3f, 1), + new Color(0.8f, 0.3f, 0.2f, 1), + new Color(0.9f, 0.7f, 0.4f, 1), + new Color(0.6f, 0.8f, 0.9f, 1), + new Color(0.4f, 0.6f, 0.3f, 1) + }, + // Венера + { + new Color(1.0f, 0.9f, 0.3f, 1), + new Color(1.0f, 0.7f, 0.2f, 1), + new Color(1.0f, 1.0f, 0.6f, 1), + new Color(0.9f, 0.5f, 0.1f, 1), + new Color(1.0f, 0.95f, 0.8f, 1) + } + }; + + // ==================== ЦВЕТА ПЛАНЕТ ДЛЯ UI ==================== + public static Color getPlanetUIColor(Planet planet) { + switch (planet) { + case EARTH: return new Color(0.3f, 0.7f, 1.0f, 1); + case MARS: return new Color(1.0f, 0.4f, 0.3f, 1); + case VENUS: return new Color(1.0f, 0.8f, 0.3f, 1); + default: return Color.WHITE; + } + } + + public static String getPlanetEmoji(Planet planet) { + switch (planet) { + case EARTH: return "🌍"; + case MARS: return "♂️"; + case VENUS: return "♀️"; + default: return "🪐"; + } + } +} + diff --git a/core/src/main/java/com/mygdx/game/GameSave.java b/core/src/main/java/com/mygdx/game/GameSave.java new file mode 100644 index 0000000..b0bacc3 --- /dev/null +++ b/core/src/main/java/com/mygdx/game/GameSave.java @@ -0,0 +1,357 @@ +package com.mygdx.game; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Preferences; +import com.badlogic.gdx.utils.Array; +import java.util.Random; + +// Система сохранения игры через LibGDX Preferences. +public class GameSave { + private static final String PREF_NAME = "AbsurdCityBuilder"; + + // Ключи для сохранения + private static final String KEY_PLANET = "planet"; + private static final String KEY_TOTAL_BUILDINGS = "totalBuildings"; + private static final String KEY_EARTH_BUILDINGS = "earthBuildings"; + private static final String KEY_MARS_BUILDINGS = "marsBuildings"; + private static final String KEY_VENUS_BUILDINGS = "venusBuildings"; + private static final String KEY_LANGUAGE = "language"; + private static final String KEY_ACHIEVEMENTS = "achievements"; + private static final String KEY_CORRECT_STREAK = "correctStreak"; + private static final String KEY_VISITED_MARS = "visitedMars"; + private static final String KEY_VISITED_VENUS = "visitedVenus"; + private static final String KEY_BUILDINGS = "buildings"; + + // Статистика для достижений + private static int totalBuildings = 0; + private static int earthBuildings = 0; + private static int marsBuildings = 0; + private static int venusBuildings = 0; + private static int correctStreak = 0; + private static boolean visitedMars = false; + private static boolean visitedVenus = false; + + // Сохранить состояние игры + public static void save(AbsurdCityBuilder1 game) { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + + // Сохраняем текущую планету + prefs.putString(KEY_PLANET, game.getCurrentPlanet().name()); + + // Сохраняем статистику + prefs.putInteger(KEY_TOTAL_BUILDINGS, totalBuildings); + prefs.putInteger(KEY_EARTH_BUILDINGS, earthBuildings); + prefs.putInteger(KEY_MARS_BUILDINGS, marsBuildings); + prefs.putInteger(KEY_VENUS_BUILDINGS, venusBuildings); + prefs.putInteger(KEY_CORRECT_STREAK, correctStreak); + prefs.putBoolean(KEY_VISITED_MARS, visitedMars); + prefs.putBoolean(KEY_VISITED_VENUS, visitedVenus); + + // Сохраняем язык + prefs.putString(KEY_LANGUAGE, Localization.getCurrentLanguage()); + + // Сохраняем достижения + prefs.putString(KEY_ACHIEVEMENTS, Achievements.getUnlockedAsString()); + + prefs.flush(); + + // Сохраняем здания отдельно + saveBuildings(game.getBuildings()); + } + + // Загрузить состояние игры + public static void load(AbsurdCityBuilder1 game) { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + + // Загружаем язык + String language = prefs.getString(KEY_LANGUAGE, "ru"); + Localization.setLanguage(language); + + // Загружаем статистику + totalBuildings = prefs.getInteger(KEY_TOTAL_BUILDINGS, 0); + earthBuildings = prefs.getInteger(KEY_EARTH_BUILDINGS, 0); + marsBuildings = prefs.getInteger(KEY_MARS_BUILDINGS, 0); + venusBuildings = prefs.getInteger(KEY_VENUS_BUILDINGS, 0); + correctStreak = prefs.getInteger(KEY_CORRECT_STREAK, 0); + visitedMars = prefs.getBoolean(KEY_VISITED_MARS, false); + visitedVenus = prefs.getBoolean(KEY_VISITED_VENUS, false); + + // Загружаем достижения + String achievementsStr = prefs.getString(KEY_ACHIEVEMENTS, ""); + Achievements.loadFromString(achievementsStr); + + // Загружаем планету для продолжения + String planetStr = prefs.getString(KEY_PLANET, "EARTH"); + try { + Planet planet = Planet.valueOf(planetStr); + game.setCurrentPlanet(planet); + } catch (Exception e) { + game.setCurrentPlanet(Planet.EARTH); + } + } + + /** + * Проверить, есть ли сохранение + */ + public static boolean hasSave() { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + // Есть сохранение если есть здания ИЛИ статистика + String buildings = prefs.getString(KEY_BUILDINGS, ""); + int totalBuilt = prefs.getInteger(KEY_TOTAL_BUILDINGS, 0); + return !buildings.isEmpty() || totalBuilt > 0; + } + + /** + * Удалить сохранение + */ + public static void deleteSave() { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + prefs.clear(); + prefs.flush(); + + resetAll(); + } + + /** + * Сбросить всю статистику (для новой игры) + */ + public static void resetAll() { + totalBuildings = 0; + earthBuildings = 0; + marsBuildings = 0; + venusBuildings = 0; + correctStreak = 0; + visitedMars = false; + visitedVenus = false; + + // Сохраняем сброс + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + prefs.putInteger(KEY_TOTAL_BUILDINGS, 0); + prefs.putInteger(KEY_EARTH_BUILDINGS, 0); + prefs.putInteger(KEY_MARS_BUILDINGS, 0); + prefs.putInteger(KEY_VENUS_BUILDINGS, 0); + prefs.putInteger(KEY_CORRECT_STREAK, 0); + prefs.putBoolean(KEY_VISITED_MARS, false); + prefs.putBoolean(KEY_VISITED_VENUS, false); + prefs.putString(KEY_PLANET, "EARTH"); + prefs.putString(KEY_ACHIEVEMENTS, ""); + prefs.putString(KEY_BUILDINGS, ""); // Очищаем здания + prefs.flush(); + } + + /** + * Загрузить только настройки (язык) при старте + */ + public static void loadSettings() { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + String language = prefs.getString(KEY_LANGUAGE, "ru"); + Localization.setLanguage(language); + + // Загружаем достижения + String achievementsStr = prefs.getString(KEY_ACHIEVEMENTS, ""); + Achievements.loadFromString(achievementsStr); + + // Загружаем статистику + totalBuildings = prefs.getInteger(KEY_TOTAL_BUILDINGS, 0); + earthBuildings = prefs.getInteger(KEY_EARTH_BUILDINGS, 0); + marsBuildings = prefs.getInteger(KEY_MARS_BUILDINGS, 0); + venusBuildings = prefs.getInteger(KEY_VENUS_BUILDINGS, 0); + correctStreak = prefs.getInteger(KEY_CORRECT_STREAK, 0); + visitedMars = prefs.getBoolean(KEY_VISITED_MARS, false); + visitedVenus = prefs.getBoolean(KEY_VISITED_VENUS, false); + } + + /** + * Сохранить настройки и статистику + */ + public static void saveSettings() { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + + // Язык + prefs.putString(KEY_LANGUAGE, Localization.getCurrentLanguage()); + + // Достижения + prefs.putString(KEY_ACHIEVEMENTS, Achievements.getUnlockedAsString()); + + // Статистика + prefs.putInteger(KEY_TOTAL_BUILDINGS, totalBuildings); + prefs.putInteger(KEY_EARTH_BUILDINGS, earthBuildings); + prefs.putInteger(KEY_MARS_BUILDINGS, marsBuildings); + prefs.putInteger(KEY_VENUS_BUILDINGS, venusBuildings); + prefs.putInteger(KEY_CORRECT_STREAK, correctStreak); + prefs.putBoolean(KEY_VISITED_MARS, visitedMars); + prefs.putBoolean(KEY_VISITED_VENUS, visitedVenus); + + prefs.flush(); + } + + /** + * Сохранить текущую планету + */ + public static void savePlanet(Planet planet) { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + prefs.putString(KEY_PLANET, planet.name()); + prefs.flush(); + } + + /** + * Сохранить здания + * Формат: type|x|y|width|height|planetIndex|progress;type|x|y|... + */ + public static void saveBuildings(Array buildings) { + if (buildings == null || buildings.size == 0) { + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + prefs.putString(KEY_BUILDINGS, ""); + prefs.flush(); + return; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < buildings.size; i++) { + Building b = buildings.get(i); + if (i > 0) sb.append(";"); + sb.append(b.type).append("|"); + sb.append((int)b.x).append("|"); + sb.append((int)b.y).append("|"); + sb.append((int)b.width).append("|"); + sb.append((int)b.height).append("|"); + sb.append(b.planetIndex).append("|"); + sb.append(b.constructionProgress); + } + + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + prefs.putString(KEY_BUILDINGS, sb.toString()); + prefs.flush(); + } + + // загружаем здания + public static void loadBuildings(Array buildings, Array citizens, Random random) { + buildings.clear(); + citizens.clear(); + + Preferences prefs = Gdx.app.getPreferences(PREF_NAME); + String data = prefs.getString(KEY_BUILDINGS, ""); + + if (data.isEmpty()) { + return; + } + + String[] buildingData = data.split(";"); + for (String bd : buildingData) { + String[] parts = bd.split("\\|"); + if (parts.length >= 7) { + try { + String type = parts[0]; + float x = Float.parseFloat(parts[1]); + float y = Float.parseFloat(parts[2]); + float width = Float.parseFloat(parts[3]); + float height = Float.parseFloat(parts[4]); + int planetIndex = Integer.parseInt(parts[5]); + int progress = Integer.parseInt(parts[6]); + + Planet planet = Planet.values()[planetIndex]; + Building building = new Building(type, x, y, width, height, random, planet); + + // Восстанавливаем прогресс + for (int i = 0; i < progress; i++) { + building.addBlock(); + } + + buildings.add(building); + + // Создаём жителей для завершённых зданий + if (building.isComplete()) { + building.createCitizensForBuilding(citizens, random); + } + } catch (Exception e) { + // Пропускаем битые данные + } + } + } + } + + // ==================== СТАТИСТИКА ==================== + + public static void onBuildingComplete(Planet planet) { + totalBuildings++; + switch (planet) { + case EARTH: + earthBuildings++; + break; + case MARS: + marsBuildings++; + break; + case VENUS: + venusBuildings++; + break; + } + } + + public static void onCorrectAnswer() { + correctStreak++; + } + + public static void onWrongAnswer() { + correctStreak = 0; + } + + // Алиасы для AnswerChecker + public static void addCorrectAnswer() { + onCorrectAnswer(); + } + + public static void resetCorrectStreak() { + onWrongAnswer(); + } + + public static void addBuilding(Planet planet) { + onBuildingComplete(planet); + } + + public static void onVisitPlanet(Planet planet) { + switch (planet) { + case MARS: + visitedMars = true; + break; + case VENUS: + visitedVenus = true; + break; + default: + break; + } + } + + // ==================== ГЕТТЕРЫ ДЛЯ ДОСТИЖЕНИЙ ==================== + + public static int getTotalBuildings() { + return totalBuildings; + } + + public static int getEarthBuildings() { + return earthBuildings; + } + + public static int getMarsBuildings() { + return marsBuildings; + } + + public static int getVenusBuildings() { + return venusBuildings; + } + + public static int getCorrectStreak() { + return correctStreak; + } + + public static boolean hasVisitedMars() { + return visitedMars; + } + + public static boolean hasVisitedVenus() { + return visitedVenus; + } + + public static boolean hasVisitedAllPlanets() { + return visitedMars && visitedVenus; + } +} diff --git a/core/src/main/java/com/mygdx/game/GameState.java b/core/src/main/java/com/mygdx/game/GameState.java index e232ea0..d319b02 100644 --- a/core/src/main/java/com/mygdx/game/GameState.java +++ b/core/src/main/java/com/mygdx/game/GameState.java @@ -5,5 +5,6 @@ public enum GameState { PLAYING, // Игровой процесс PLANET_SELECT, // Выбор планеты HELP, // Помощь/инструкции - ABOUT // Об игре + ABOUT, // Об игре + ACHIEVEMENTS // Достижения } diff --git a/core/src/main/java/com/mygdx/game/Localization.java b/core/src/main/java/com/mygdx/game/Localization.java new file mode 100644 index 0000000..3e01a9f --- /dev/null +++ b/core/src/main/java/com/mygdx/game/Localization.java @@ -0,0 +1,599 @@ +package com.mygdx.game; + +/** + * Локализация игры - все тексты на русском и английском. + */ +public class Localization { + private static String currentLanguage = "ru"; + + // ==================== МЕНЮ ==================== + public static String newGame() { + return isRu() ? "🚀 НОВАЯ ИГРА" : "🚀 NEW GAME"; + } + + public static String continueGame() { + return isRu() ? "▶️ ПРОДОЛЖИТЬ" : "▶️ CONTINUE"; + } + + public static String selectPlanet() { + return isRu() ? "🪐 ВЫБОР ПЛАНЕТЫ" : "🪐 SELECT PLANET"; + } + + public static String help() { + return isRu() ? "❓ ПОМОЩЬ" : "❓ HELP"; + } + + public static String about() { + return isRu() ? "ℹ️ ОБ ИГРЕ" : "ℹ️ ABOUT"; + } + + public static String achievements() { + return isRu() ? "🏆 ДОСТИЖЕНИЯ" : "🏆 ACHIEVEMENTS"; + } + + public static String exit() { + return isRu() ? "🚪 ВЫХОД" : "🚪 EXIT"; + } + + public static String back() { + return isRu() ? "⬅️ НАЗАД" : "⬅️ BACK"; + } + + public static String gameTitle() { + return "✨ ABSURD CITY BUILDER ✨"; + } + + public static String gameSubtitle() { + return isRu() + ? "Строй абсурдные города на разных планетах!" + : "Build absurd cities on different planets!"; + } + + public static String getLanguageLabel() { + return isRu() ? "EN" : "RU"; + } + + public static String welcomeTo(Planet planet) { + String name = planetName(planet); + return isRu() + ? "Добро пожаловать на " + name + "! Выберите здание и кликните на поле." + : "Welcome to " + name + "! Select a building and click on the field."; + } + + public static String flying(Planet planet) { + return isRu() + ? "Запускаем космический корабль на " + planetName(planet) + "! 🚀" + : "Launching spaceship to " + planetName(planet) + "! 🚀"; + } + + public static String blockBuilt() { + return isRu() ? "Отлично! Блок построен!" : "Great! Block built!"; + } + + public static String changePlanet() { + return isRu() ? "↑/↓ - сменить планету" : "↑/↓ - change planet"; + } + + public static String planetKeys() { + return isRu() ? "1-Земля, 2-Марс, 3-Венера" : "1-Earth, 2-Mars, 3-Venus"; + } + + public static String selectBuildingType() { + return isRu() ? "←/→ - выбрать тип здания" : "←/→ - select building type"; + } + + public static String task(String question) { + return isRu() ? "🧮 Задача: " + question : "🧮 Problem: " + question; + } + + public static String enterSubmit() { + return isRu() ? "⏎ Enter - отправить ответ" : "⏎ Enter - submit answer"; + } + + public static String escCancel() { + return isRu() ? "⎋ ESC - отмена ввода" : "⎋ ESC - cancel input"; + } + + public static String backspaceDelete() { + return isRu() ? "⌫ Backspace - удалить символ" : "⌫ Backspace - delete character"; + } + + public static String clickToBuild() { + return isRu() + ? "🖱️ Кликните на поле для строительства" + : "🖱️ Click on the field to build"; + } + + public static String controls() { + return isRu() + ? "🗑️ Delete/Ctrl+Z - удалить здание | ⌫ Backspace - удалить блок | ⎋ ESC - меню" + : "🗑️ Delete/Ctrl+Z - delete building | ⌫ Backspace - delete block | ⎋ ESC - menu"; + } + + // ==================== ПЛАНЕТЫ ==================== + public static String earth() { + return isRu() ? "🌍 ЗЕМЛЯ" : "🌍 EARTH"; + } + + public static String mars() { + return isRu() ? "♂️ МАРС" : "♂️ MARS"; + } + + public static String venus() { + return isRu() ? "♀️ ВЕНЕРА" : "♀️ VENUS"; + } + + public static String planetName(Planet planet) { + switch (planet) { + case EARTH: return isRu() ? "Земля" : "Earth"; + case MARS: return isRu() ? "Марс" : "Mars"; + case VENUS: return isRu() ? "Венера" : "Venus"; + default: return ""; + } + } + + // ==================== ИГРОВОЙ ПРОЦЕСС ==================== + public static String welcome(Planet planet) { + String name = planetName(planet); + return isRu() + ? "Добро пожаловать на " + name + "! Выберите здание и кликните на поле." + : "Welcome to " + name + "! Select a building and click on the field."; + } + + public static String buildingProgress(int current, int max) { + return isRu() + ? "📊 Прогресс: " + current + "/" + max + " блоков" + : "📊 Progress: " + current + "/" + max + " blocks"; + } + + public static String selectBuilding() { + return isRu() ? "🏗️ Тип здания: " : "🏗️ Building type: "; + } + + public static String currentPlanet() { + return isRu() ? "🌍 Планета: " : "🌍 Planet: "; + } + + public static String changePlanetHint() { + return isRu() ? "↑/↓ - сменить планету" : "↑/↓ - change planet"; + } + + public static String planetKeysHint() { + return isRu() ? "1-Земля, 2-Марс, 3-Венера" : "1-Earth, 2-Mars, 3-Venus"; + } + + public static String selectBuildingHint() { + return isRu() ? "←/→ - выбрать тип здания" : "←/→ - select building type"; + } + + public static String clickToPlace() { + return isRu() + ? "🖱️ Кликните на поле для строительства" + : "🖱️ Click on the field to build"; + } + + public static String controlsHint() { + return isRu() + ? "🗑️ Delete/Ctrl+Z - удалить здание | ⌫ Backspace - удалить блок | ⎋ ESC - меню" + : "🗑️ Delete/Ctrl+Z - remove building | ⌫ Backspace - remove block | ⎋ ESC - menu"; + } + + public static String enterAnswer() { + return isRu() ? "✏️ Введите ответ:" : "✏️ Enter answer:"; + } + + public static String mathProblem() { + return isRu() ? "🧮 Задача: " : "🧮 Problem: "; + } + + public static String enterHint() { + return isRu() ? "⏎ Enter - отправить ответ" : "⏎ Enter - submit answer"; + } + + public static String escHint() { + return isRu() ? "⎋ ESC - отмена ввода" : "⎋ ESC - cancel input"; + } + + public static String backspaceHint() { + return isRu() ? "⌫ Backspace - удалить символ" : "⌫ Backspace - delete character"; + } + + public static String escForMenu() { + return isRu() ? "Нажмите ESC для возврата в меню" : "Press ESC to return to menu"; + } + + public static String inFlight() { + return isRu() ? "(Перелет...)" : "(In flight...)"; + } + + // ==================== СООБЩЕНИЯ ==================== + public static String correctAnswer() { + return isRu() ? "Отлично! Блок построен!" : "Great! Block built!"; + } + + public static String wrongAnswer() { + return isRu() ? "Неверно! Блок разрушен!" : "Wrong! Block destroyed!"; + } + + public static String buildingComplete() { + return isRu() ? "Успех! " : "Success! "; + } + + public static String buildingDestroyed() { + return isRu() ? "Здание разрушено до основания! " : "Building destroyed completely! "; + } + + public static String enterNumber() { + return isRu() ? "Введите целое число!" : "Enter a whole number!"; + } + + public static String enterAnswer2() { + return isRu() ? "Введите ответ!" : "Enter an answer!"; + } + + public static String inputCanceled() { + return isRu() ? "Ввод отменен." : "Input canceled."; + } + + public static String gamePaused() { + return isRu() ? "Игра приостановлена. Нажмите ESC для продолжения." : "Game paused. Press ESC to continue."; + } + + public static String buildingSelected(String name) { + return isRu() ? "Выбран: " + name : "Selected: " + name; + } + + public static String buildingCanceled() { + return isRu() ? "Строительство отменено. Выберите новое место." : "Construction canceled. Choose a new location."; + } + + public static String lastBuildingRemoved() { + return isRu() ? "Последнее здание удалено." : "Last building removed."; + } + + public static String noBuildingsToRemove() { + return isRu() ? "Нет зданий для удаления." : "No buildings to remove."; + } + + public static String blockRemoved(int progress) { + return isRu() + ? "Блок удален! Текущий прогресс: " + progress + "/3" + : "Block removed! Current progress: " + progress + "/3"; + } + + public static String flyingTo(Planet planet) { + return isRu() + ? "Запускаем космический корабль на " + planetName(planet) + "! 🚀" + : "Launching spaceship to " + planetName(planet) + "! 🚀"; + } + + public static String leaving(Planet planet) { + return isRu() ? "Покидаем " + planetName(planet) + "..." : "Leaving " + planetName(planet) + "..."; + } + + public static String arriving(Planet planet) { + return isRu() ? "Прибываем на " + planetName(planet) + "!" : "Arriving at " + planetName(planet) + "!"; + } + + // ==================== НАЗВАНИЯ ЗДАНИЙ ==================== + public static String[][] getBuildingNames() { + if (isRu()) { + return GameConfig.BUILDING_TYPES_BY_PLANET; + } + return BUILDING_NAMES_EN; + } + + private static final String[][] BUILDING_NAMES_EN = { + // Earth + { + "✨ Cozy House ✨", + "🏥 Children's Hospital 🏥", + "🎒 Fun School 🎒", + "🎪 Playground 🎪", + "💰 Reliable Bank 💰", + "💊 Healthy Pharmacy 💊", + "🎭 Magic Theater 🎭", + "🎬 CinemaWorld 🎬" + }, + // Mars + { + "🚀 Martian Base 🚀", + "🔴 Red Laboratory 🔴", + "🛰️ Spaceport 🛰️", + "⚡ Energy Dome ⚡", + "💧 Hydrogen Plant 💧", + "🌌 Observatory 🌌", + "🤖 Robo-Factory 🤖", + "🧪 Bio-Dome 🧪" + }, + // Venus + { + "🌋 Volcanic House 🌋", + "🔥 Thermal Station 🔥", + "🌅 Golden Palace 🌅", + "☁️ Cloud City ☁️", + "💎 Crystal Mine 💎", + "🌡️ Greenhouse 🌡️", + "🌀 Vortex Generator 🌀", + "✨ Shining Tower ✨" + } + }; + + // ==================== ШУТКИ ПРИ ПРАВИЛЬНОМ ОТВЕТЕ ==================== + public static String[] getSuccessComments(Planet planet) { + if (isRu()) { + return SUCCESS_COMMENTS_RU[planet.ordinal()]; + } + return SUCCESS_COMMENTS_EN[planet.ordinal()]; + } + + private static final String[][] SUCCESS_COMMENTS_RU = { + // Земля + { + "Вау! Такое здание видел только в мультиках!", + "Архитектор сошел с ума от радости!", + "Город стал похож на мультфильм!", + "Это самое безумное здание в городе!", + "Жители в восторге от этой абсурдности!", + "Эй, это похоже на город из моих снов!", + "Такое здание украсит любой мультфильм!" + }, + // Марс + { + "Отлично! Марсианская колония растёт! 🚀", + "На Марсе теперь есть своё безумие!", + "Эти здания переживут любую пылевую бурю!", + "Марсиане будут в восторге! 👽", + "Похоже, мы колонизируем Марс!", + "Красная планета стала разноцветнее!", + "Это здание выглядит инопланетно круто!" + }, + // Венера + { + "Горячо! Венерианский шедевр готов! 🔥", + "Здание плавится от собственной красоты!", + "Венера стала ещё ярче! 🌟", + "Это здание сияет как сама Венера!", + "Похоже, мы выживаем на Венере!", + "Такая красота плавит сердце!", + "Золотой век венерианской архитектуры!" + } + }; + + private static final String[][] SUCCESS_COMMENTS_EN = { + // Earth + { + "Wow! I've only seen such buildings in cartoons!", + "The architect went crazy with joy!", + "The city looks like a cartoon now!", + "This is the craziest building in town!", + "Residents love this absurdity!", + "Hey, this looks like a city from my dreams!", + "Such a building would grace any cartoon!" + }, + // Mars + { + "Great! The Martian colony is growing! 🚀", + "Mars now has its own madness!", + "These buildings will survive any dust storm!", + "Martians will love it! 👽", + "Looks like we're colonizing Mars!", + "The red planet got more colorful!", + "This building looks alien-cool!" + }, + // Venus + { + "Hot! Venusian masterpiece complete! 🔥", + "The building is melting from its own beauty!", + "Venus got even brighter! 🌟", + "This building shines like Venus itself!", + "Looks like we're surviving on Venus!", + "Such beauty melts the heart!", + "The golden age of Venusian architecture!" + } + }; + + // ==================== ШУТКИ ПРИ НЕПРАВИЛЬНОМ ОТВЕТЕ ==================== + public static String[] getWrongAnswerJokes(Planet planet) { + if (isRu()) { + return WRONG_ANSWER_JOKES_RU[planet.ordinal()]; + } + return WRONG_ANSWER_JOKES_EN[planet.ordinal()]; + } + + private static final String[][] WRONG_ANSWER_JOKES_RU = { + // Земля + { + "Твоя математика кривее моих зданий!", + "Даже мультяшный архитектор считает лучше!", + "Ты что, в мультиках учился математике?", + "Ошибка! Попробуй посчитать на пальцах ног!", + "Неправильно! Давай еще разочек, как в мультике!", + "Бывает! Даже мультяшные гении ошибаются!", + "Ой, кажется, ты перепутал с мультипликацией!", + "Неверно! Но зато здание выглядит смешнее!" + }, + // Марс + { + "Неверно! Марсиане считают лучше! 👽", + "Ошибка в расчётах! Пылевая буря съела цифры!", + "Твоя математика не переживёт марсианскую зиму!", + "Неудача! Даже марсоход считает точнее!", + "Неправильно! Попробуй считать в скафандре!", + "Ошибка! Кислородное голодание сказывается?", + "Марсианские калькуляторы не одобряют!", + "Неверно! Может, радиация помешала?" + }, + // Венера + { + "Горячая ошибка! 🔥 Попробуй ещё!", + "Неверно! Даже венерианская жара не оправдывает!", + "Ошибка! Кислотные облака затуманили разум?", + "Неправильно! Слишком жарко для точных расчётов?", + "Провал! Венерианские калькуляторы плавятся!", + "Неудача! Давление в 90 атмосфер давит на мозги?", + "Ошибка! Попробуй считать в теплозащитном костюме!", + "Неверно! Золотое сечение не спасло!" + } + }; + + private static final String[][] WRONG_ANSWER_JOKES_EN = { + // Earth + { + "Your math is more crooked than my buildings!", + "Even a cartoon architect counts better!", + "Did you learn math from cartoons?", + "Wrong! Try counting on your toes!", + "Incorrect! Let's try again, cartoon style!", + "It happens! Even cartoon geniuses make mistakes!", + "Oops, looks like you confused it with animation!", + "Wrong! But the building looks funnier now!" + }, + // Mars + { + "Wrong! Martians count better! 👽", + "Calculation error! Dust storm ate the numbers!", + "Your math won't survive Martian winter!", + "Failed! Even the rover counts better!", + "Wrong! Try counting in a spacesuit!", + "Error! Oxygen deprivation kicking in?", + "Martian calculators disapprove!", + "Wrong! Maybe radiation interfered?" + }, + // Venus + { + "Hot mistake! 🔥 Try again!", + "Wrong! Even Venusian heat doesn't excuse this!", + "Error! Acid clouds clouding your mind?", + "Wrong! Too hot for accurate calculations?", + "Fail! Venusian calculators are melting!", + "Failed! Is 90 atmospheres of pressure getting to you?", + "Error! Try counting in a heat suit!", + "Wrong! Golden ratio didn't save you!" + } + }; + + // ==================== ДОСТИЖЕНИЯ ==================== + public static String achievementUnlocked() { + return isRu() ? "🏆 Достижение разблокировано!" : "🏆 Achievement unlocked!"; + } + + // ==================== ЭКРАН ПОМОЩИ ==================== + public static String helpTitle() { + return isRu() ? "❓ ПОМОЩЬ И УПРАВЛЕНИЕ" : "❓ HELP & CONTROLS"; + } + + public static String[] getHelpInstructions() { + if (isRu()) { + return HELP_INSTRUCTIONS_RU; + } + return HELP_INSTRUCTIONS_EN; + } + + private static final String[] HELP_INSTRUCTIONS_RU = { + "🎮 ОСНОВНОЕ УПРАВЛЕНИЕ:", + "• ЛКМ - кликнуть на поле для строительства", + "• ←/→ - выбрать тип здания", + "• Enter - отправить ответ на задачу", + "• Backspace - удалить блок/символ", + "• Delete/Ctrl+Z - удалить здание", + "• ESC - отмена ввода", + "", + "🪐 УПРАВЛЕНИЕ ПЛАНЕТАМИ:", + "• ↑/↓ - переключить планету", + "• 1 - Земля, 2 - Марс, 3 - Венера", + "", + "🎯 КАК ИГРАТЬ:", + "1. Выберите тип здания", + "2. Кликните на игровом поле", + "3. Решите математическую задачу", + "4. Постройте 3 блока для завершения", + "5. Стройте разные здания на разных планетах!" + }; + + private static final String[] HELP_INSTRUCTIONS_EN = { + "🎮 BASIC CONTROLS:", + "• LMB - click on field to build", + "• ←/→ - select building type", + "• Enter - submit answer", + "• Backspace - delete block/character", + "• Delete/Ctrl+Z - remove building", + "• ESC - cancel input", + "", + "🪐 PLANET CONTROLS:", + "• ↑/↓ - switch planet", + "• 1 - Earth, 2 - Mars, 3 - Venus", + "", + "🎯 HOW TO PLAY:", + "1. Select building type", + "2. Click on the game field", + "3. Solve the math problem", + "4. Build 3 blocks to complete", + "5. Build different buildings on different planets!" + }; + + // ==================== ЭКРАН "ОБ ИГРЕ" ==================== + public static String aboutTitle() { + return isRu() ? "✨ ОБ ИГРЕ" : "✨ ABOUT"; + } + + public static String[] getAboutText() { + if (isRu()) { + return ABOUT_TEXT_RU; + } + return ABOUT_TEXT_EN; + } + + private static final String[] ABOUT_TEXT_RU = { + "Absurd City Builder - это уникальная игра,", + "где вы строите безумные города на разных планетах!", + "", + "Особенности игры:", + "• 3 уникальные планеты с разными зданиями", + "• Забавные математические задачи", + "• Мультяшная графика и анимации", + "• Динамичные жители и шутки", + "• Бесконечные возможности для творчества!", + "", + "Разработано с ❤️ для любителей абсурда и математики.", + "", + "Версия 1.0" + }; + + private static final String[] ABOUT_TEXT_EN = { + "Absurd City Builder is a unique game", + "where you build crazy cities on different planets!", + "", + "Game features:", + "• 3 unique planets with different buildings", + "• Fun math problems", + "• Cartoon graphics and animations", + "• Dynamic citizens and jokes", + "• Endless creative possibilities!", + "", + "Made with ❤️ for absurdity and math lovers.", + "", + "Version 1.0" + }; + + // ==================== УПРАВЛЕНИЕ ЯЗЫКОМ ==================== + public static void setLanguage(String lang) { + currentLanguage = lang; + } + + public static String getCurrentLanguage() { + return currentLanguage; + } + + public static void toggleLanguage() { + currentLanguage = isRu() ? "en" : "ru"; + } + + public static boolean isRu() { + return "ru".equals(currentLanguage); + } + + public static String languageButtonText() { + return isRu() ? "🌐 EN" : "🌐 RU"; + } +} diff --git a/core/src/main/java/com/mygdx/game/MenuRenderer.java b/core/src/main/java/com/mygdx/game/MenuRenderer.java index f43af24..e9798be 100644 --- a/core/src/main/java/com/mygdx/game/MenuRenderer.java +++ b/core/src/main/java/com/mygdx/game/MenuRenderer.java @@ -20,6 +20,7 @@ public class MenuRenderer { private List mainMenuButtons; private List planetSelectButtons; private List helpButtons; + private List achievementsButtons; private float titlePulse = 0; private float starTimer = 0; @@ -40,61 +41,81 @@ public class MenuRenderer { createMainMenuButtons(); createPlanetSelectButtons(); createHelpButtons(); + createAchievementsButtons(); } private void createMainMenuButtons() { mainMenuButtons = new ArrayList<>(); float buttonWidth = 400; float buttonHeight = 70; - float startY = height/2 - 50; - float spacing = 85; + float startY = height/2 + 30; + float spacing = 75; + + // Кнопка "Продолжить" (если есть сохранение) + mainMenuButtons.add(new MenuButton( + width/2 - buttonWidth/2, startY, buttonWidth, buttonHeight, + Localization.continueGame(), + GameConfig.BUTTON_HELP, + GameConfig.BUTTON_HELP_HOVER, + () -> {} + ).withTextColor(Color.WHITE)); // Кнопка "Новая игра" mainMenuButtons.add(new MenuButton( - width/2 - buttonWidth/2, startY, buttonWidth, buttonHeight, - "🚀 НОВАЯ ИГРА", - new Color(0.2f, 0.5f, 0.8f, 0.9f), - new Color(0.3f, 0.6f, 0.9f, 1f), + width/2 - buttonWidth/2, startY - spacing, buttonWidth, buttonHeight, + Localization.newGame(), + GameConfig.BUTTON_NEW_GAME, + GameConfig.BUTTON_NEW_GAME_HOVER, () -> {} ).withTextColor(Color.YELLOW)); // Кнопка "Выбор планеты" mainMenuButtons.add(new MenuButton( - width/2 - buttonWidth/2, startY - spacing, buttonWidth, buttonHeight, - "🪐 ВЫБОР ПЛАНЕТЫ", - new Color(0.8f, 0.4f, 0.2f, 0.9f), - new Color(0.9f, 0.5f, 0.3f, 1f), + width/2 - buttonWidth/2, startY - spacing * 2, buttonWidth, buttonHeight, + Localization.selectPlanet(), + GameConfig.BUTTON_PLANET, + GameConfig.BUTTON_PLANET_HOVER, + () -> {} + )); + + // Кнопка "Достижения" + mainMenuButtons.add(new MenuButton( + width/2 - buttonWidth/2, startY - spacing * 3, buttonWidth, buttonHeight, + Localization.achievements(), + new Color(0.9f, 0.7f, 0.2f, 0.9f), + new Color(1.0f, 0.8f, 0.3f, 1f), () -> {} )); // Кнопка "Помощь" mainMenuButtons.add(new MenuButton( - width/2 - buttonWidth/2, startY - spacing * 2, buttonWidth, buttonHeight, - "❓ ПОМОЩЬ", - new Color(0.2f, 0.7f, 0.3f, 0.9f), - new Color(0.3f, 0.8f, 0.4f, 1f), - () -> {} - )); - - // Кнопка "Об игре" - mainMenuButtons.add(new MenuButton( - width/2 - buttonWidth/2, startY - spacing * 3, buttonWidth, buttonHeight, - "ℹ️ ОБ ИГРЕ", - new Color(0.7f, 0.2f, 0.7f, 0.9f), - new Color(0.8f, 0.3f, 0.8f, 1f), + width/2 - buttonWidth/2, startY - spacing * 4, buttonWidth, buttonHeight, + Localization.help(), + GameConfig.BUTTON_HELP, + GameConfig.BUTTON_HELP_HOVER, () -> {} )); // Кнопка "Выход" mainMenuButtons.add(new MenuButton( - width/2 - buttonWidth/2, startY - spacing * 4, buttonWidth, buttonHeight, - "🚪 ВЫХОД", - new Color(0.8f, 0.2f, 0.2f, 0.9f), - new Color(0.9f, 0.3f, 0.3f, 1f), + width/2 - buttonWidth/2, startY - spacing * 5, buttonWidth, buttonHeight, + Localization.exit(), + GameConfig.BUTTON_EXIT, + GameConfig.BUTTON_EXIT_HOVER, () -> System.exit(0) )); } + /** + * Обновить тексты кнопок меню (при смене языка). + */ + public void refreshMenuTexts() { + createMainMenuButtons(); + createPlanetSelectButtons(); + createHelpButtons(); + createAchievementsButtons(); + } + private void createPlanetSelectButtons() { planetSelectButtons = new ArrayList<>(); float buttonWidth = 350; @@ -105,36 +126,36 @@ public class MenuRenderer { // Земля planetSelectButtons.add(new MenuButton( width/2 - buttonWidth - 20, startY, buttonWidth, buttonHeight, - "🌍 ЗЕМЛЯ", - new Color(0.3f, 0.6f, 0.9f, 0.9f), - new Color(0.4f, 0.7f, 1.0f, 1f), + Localization.earth(), + GameConfig.BUTTON_EARTH, + GameConfig.BUTTON_EARTH_HOVER, () -> {} ).withTextColor(Color.WHITE)); // Марс planetSelectButtons.add(new MenuButton( width/2 + 20, startY, buttonWidth, buttonHeight, - "♂️ МАРС", - new Color(0.8f, 0.3f, 0.2f, 0.9f), - new Color(0.9f, 0.4f, 0.3f, 1f), + Localization.mars(), + GameConfig.BUTTON_MARS, + GameConfig.BUTTON_MARS_HOVER, () -> {} )); // Венера planetSelectButtons.add(new MenuButton( width/2 - buttonWidth/2, startY - spacing, buttonWidth, buttonHeight, - "♀️ ВЕНЕРА", - new Color(1.0f, 0.7f, 0.2f, 0.9f), - new Color(1.0f, 0.8f, 0.3f, 1f), + Localization.venus(), + GameConfig.BUTTON_VENUS, + GameConfig.BUTTON_VENUS_HOVER, () -> {} )); // Кнопка "Назад" planetSelectButtons.add(new MenuButton( 50, 50, 200, 60, - "⬅️ НАЗАД", - new Color(0.4f, 0.4f, 0.4f, 0.9f), - new Color(0.5f, 0.5f, 0.5f, 1f), + Localization.back(), + GameConfig.BUTTON_BACK, + GameConfig.BUTTON_BACK_HOVER, () -> {} )); } @@ -145,9 +166,22 @@ public class MenuRenderer { // Кнопка "Назад" helpButtons.add(new MenuButton( 50, 50, 200, 60, - "⬅️ НАЗАД", - new Color(0.4f, 0.4f, 0.4f, 0.9f), - new Color(0.5f, 0.5f, 0.5f, 1f), + Localization.back(), + GameConfig.BUTTON_BACK, + GameConfig.BUTTON_BACK_HOVER, + () -> {} + )); + } + + private void createAchievementsButtons() { + achievementsButtons = new ArrayList<>(); + + // Кнопка "Назад" + achievementsButtons.add(new MenuButton( + 50, 50, 200, 60, + Localization.back(), + GameConfig.BUTTON_BACK, + GameConfig.BUTTON_BACK_HOVER, () -> {} )); } @@ -169,16 +203,28 @@ public class MenuRenderer { // Подзаголовок font.setColor(new Color(0.8f, 0.9f, 1.0f, 0.8f)); font.getData().setScale(1.2f); - String subtitle = "Строй абсурдные города на разных планетах!"; + String subtitle = Localization.gameSubtitle(); layout.setText(font, subtitle); font.draw(batch, subtitle, width/2 - layout.width/2, height - 150); font.getData().setScale(1.0f); // Кнопки - for (MenuButton button : mainMenuButtons) { + boolean hasSave = GameSave.hasSave(); + for (int i = 0; i < mainMenuButtons.size(); i++) { + MenuButton button = mainMenuButtons.get(i); + // Скрываем кнопку "Продолжить" если нет сохранения + if (i == 0 && !hasSave) { + continue; + } button.render(batch, font, layout, whitePixel); } + // Переключатель языка + renderLanguageSwitch(mouseX, mouseY); + + // Статистика + renderStats(); + // Автор font.setColor(new Color(1, 1, 1, 0.5f)); font.getData().setScale(0.8f); @@ -188,6 +234,63 @@ public class MenuRenderer { batch.end(); } + private void renderLanguageSwitch(float mouseX, float mouseY) { + float langX = width - 80; + float langY = height - 50; + float langW = 60; + float langH = 35; + + // Фон кнопки + boolean hovered = mouseX >= langX && mouseX <= langX + langW && + mouseY >= langY && mouseY <= langY + langH; + batch.setColor(hovered ? new Color(0.4f, 0.5f, 0.6f, 0.9f) : new Color(0.3f, 0.4f, 0.5f, 0.8f)); + batch.draw(whitePixel, langX, langY, langW, langH); + + // Рамка + batch.setColor(Color.WHITE); + batch.draw(whitePixel, langX, langY, langW, 2); + batch.draw(whitePixel, langX, langY + langH - 2, langW, 2); + batch.draw(whitePixel, langX, langY, 2, langH); + batch.draw(whitePixel, langX + langW - 2, langY, 2, langH); + + // Текст языка + font.setColor(Color.WHITE); + font.getData().setScale(1.0f); + String langText = Localization.getLanguageLabel(); + layout.setText(font, langText); + font.draw(batch, langText, langX + langW/2 - layout.width/2, langY + langH/2 + layout.height/2); + } + + private void renderStats() { + font.setColor(new Color(0.7f, 0.8f, 0.9f, 0.7f)); + font.getData().setScale(0.8f); + + int total = GameSave.getTotalBuildings(); + int achievements = Achievements.getUnlockedCount(); + int totalAch = Achievements.getTotalCount(); + + String stats = Localization.isRu() + ? "Построено зданий: " + total + " | Достижения: " + achievements + "/" + totalAch + : "Buildings: " + total + " | Achievements: " + achievements + "/" + totalAch; + + layout.setText(font, stats); + font.draw(batch, stats, width/2 - layout.width/2, 60); + font.getData().setScale(1.0f); + } + + /** + * Проверить клик на переключатель языка. + */ + public boolean checkLanguageClick(float mouseX, float mouseY) { + float langX = width - 80; + float langY = height - 50; + float langW = 60; + float langH = 35; + + return mouseX >= langX && mouseX <= langX + langW && + mouseY >= langY && mouseY <= langY + langH; + } + public void renderPlanetSelect(float mouseX, float mouseY) { batch.begin(); @@ -196,14 +299,14 @@ public class MenuRenderer { // Заголовок titleFont.setColor(new Color(1, 1, 1, 0.9f)); - String title = "🪐 ВЫБОР ПЛАНЕТЫ"; + String title = Localization.selectPlanet(); layout.setText(titleFont, title); titleFont.draw(batch, title, width/2 - layout.width/2, height - 100); // Описание font.setColor(new Color(0.8f, 0.9f, 1.0f, 0.8f)); font.getData().setScale(1.1f); - String desc = "Выберите планету для строительства:"; + String desc = Localization.isRu() ? "Выберите планету для строительства:" : "Select a planet for building:"; layout.setText(font, desc); font.draw(batch, desc, width/2 - layout.width/2, height - 170); font.getData().setScale(1.0f); @@ -213,18 +316,21 @@ public class MenuRenderer { font.getData().setScale(0.9f); // Земля - String earthText = "Мультяшные здания\nЯркие цвета\nМилые жители"; - layout.setText(font, earthText); + String earthText = Localization.isRu() + ? "Мультяшные здания\nЯркие цвета\nМилые жители" + : "Cartoon buildings\nBright colors\nCute residents"; font.draw(batch, earthText, width/2 - 380, height/2 - 50); -// Марс - String marsText = "Технологичные постройки\nКрасный пейзаж\nМарсианские роботы"; - layout.setText(font, marsText); + // Марс + String marsText = Localization.isRu() + ? "Технологичные постройки\nКрасный пейзаж\nМарсианские роботы" + : "Tech buildings\nRed landscape\nMartian robots"; font.draw(batch, marsText, width/2 + 30, height/2 - 50); -// Венера - String venusText = "Вулканические здания\nРаскаленная атмосфера\nКристаллические формы"; - layout.setText(font, venusText); + // Венера + String venusText = Localization.isRu() + ? "Вулканические здания\nРаскаленная атмосфера\nКристаллические формы" + : "Volcanic buildings\nHot atmosphere\nCrystal forms"; font.draw(batch, venusText, width/2 - 175, height/2 - 200); font.getData().setScale(1.0f); @@ -240,13 +346,13 @@ public class MenuRenderer { batch.begin(); // Фон - batch.setColor(new Color(0.1f, 0.1f, 0.2f, 0.95f)); + batch.setColor(GameConfig.MENU_SPACE_BG); batch.draw(whitePixel, 0, 0, width, height); batch.setColor(Color.WHITE); // Заголовок titleFont.setColor(Color.YELLOW); - String title = "❓ ПОМОЩЬ И УПРАВЛЕНИЕ"; + String title = Localization.isRu() ? "❓ ПОМОЩЬ И УПРАВЛЕНИЕ" : "❓ HELP & CONTROLS"; layout.setText(titleFont, title); titleFont.draw(batch, title, width/2 - layout.width/2, height - 100); @@ -257,14 +363,14 @@ public class MenuRenderer { float textY = height - 200; float lineHeight = 35; - String[] instructions = { + String[] instructions = Localization.isRu() ? new String[] { "🎮 ОСНОВНОЕ УПРАВЛЕНИЕ:", "• ЛКМ - кликнуть на поле для строительства", "• ←/→ - выбрать тип здания", "• Enter - отправить ответ на задачу", "• Backspace - удалить блок/символ", "• Delete/Ctrl+Z - удалить здание", - "• ESC - отмена ввода", + "• ESC - отмена ввода / меню", "", "🪐 УПРАВЛЕНИЕ ПЛАНЕТАМИ:", "• ↑/↓ - переключить планету", @@ -274,8 +380,25 @@ public class MenuRenderer { "1. Выберите тип здания", "2. Кликните на игровом поле", "3. Решите математическую задачу", - "4. Постройте 3 блока для завершения", - "5. Стройте разные здания на разных планетах!" + "4. Постройте 3 блока для завершения" + } : new String[] { + "🎮 BASIC CONTROLS:", + "• LMB - click on the field to build", + "• ←/→ - select building type", + "• Enter - submit answer", + "• Backspace - delete block/character", + "• Delete/Ctrl+Z - delete building", + "• ESC - cancel input / menu", + "", + "🪐 PLANET CONTROLS:", + "• ↑/↓ - switch planet", + "• 1 - Earth, 2 - Mars, 3 - Venus", + "", + "🎯 HOW TO PLAY:", + "1. Select building type", + "2. Click on the game field", + "3. Solve the math problem", + "4. Build 3 blocks to complete" }; for (String line : instructions) { @@ -300,11 +423,83 @@ public class MenuRenderer { batch.end(); } + public void renderAchievements(float mouseX, float mouseY) { + batch.begin(); + + // Фон + batch.setColor(new Color(0.08f, 0.05f, 0.12f, 1)); + batch.draw(whitePixel, 0, 0, width, height); + batch.setColor(Color.WHITE); + + // Заголовок + titleFont.setColor(new Color(1f, 0.85f, 0.3f, 1)); + String title = Localization.achievements(); + layout.setText(titleFont, title); + titleFont.draw(batch, title, width/2 - layout.width/2, height - 80); + + // Прогресс + font.setColor(new Color(0.8f, 0.8f, 0.8f, 1)); + font.getData().setScale(1.0f); + String progress = Achievements.getUnlockedCount() + " / " + Achievements.getTotalCount(); + layout.setText(font, progress); + font.draw(batch, progress, width/2 - layout.width/2, height - 120); + + // Список достижений + float startY = height - 180; + float itemHeight = 70; + float itemWidth = 600; + float itemX = width/2 - itemWidth/2; + + Achievement[] all = Achievements.getAll(); + for (int i = 0; i < all.length; i++) { + Achievement a = all[i]; + boolean unlocked = Achievements.isUnlocked(a); + float y = startY - i * itemHeight; + + // Фон элемента + if (unlocked) { + batch.setColor(new Color(0.2f, 0.3f, 0.2f, 0.8f)); + } else { + batch.setColor(new Color(0.15f, 0.15f, 0.2f, 0.6f)); + } + batch.draw(whitePixel, itemX, y, itemWidth, itemHeight - 5); + + // Рамка + batch.setColor(unlocked ? new Color(0.5f, 0.8f, 0.5f, 0.5f) : new Color(0.3f, 0.3f, 0.4f, 0.3f)); + batch.draw(whitePixel, itemX, y, itemWidth, 2); + batch.draw(whitePixel, itemX, y + itemHeight - 7, itemWidth, 2); + + // Иконка + font.getData().setScale(1.3f); + font.setColor(unlocked ? new Color(0.3f, 0.9f, 0.3f, 1) : new Color(0.4f, 0.4f, 0.5f, 1)); + font.draw(batch, unlocked ? "✓" : "○", itemX + 15, y + itemHeight - 25); + + // Название + font.getData().setScale(1.1f); + font.setColor(unlocked ? Color.WHITE : new Color(0.6f, 0.6f, 0.6f, 1)); + font.draw(batch, a.getTitle(), itemX + 55, y + itemHeight - 20); + + // Описание + font.getData().setScale(0.85f); + font.setColor(unlocked ? new Color(0.8f, 0.8f, 0.8f, 1) : new Color(0.5f, 0.5f, 0.5f, 1)); + font.draw(batch, a.getDescription(), itemX + 55, y + itemHeight - 45); + } + + font.getData().setScale(1.0f); + + // Кнопка назад + for (MenuButton button : achievementsButtons) { + button.render(batch, font, layout, whitePixel); + } + + batch.end(); + } + public void renderAbout(float mouseX, float mouseY) { batch.begin(); // Галактический фон - batch.setColor(new Color(0.05f, 0.05f, 0.1f, 1)); + batch.setColor(GameConfig.MENU_SPACE_BG); batch.draw(whitePixel, 0, 0, width, height); // Звезды @@ -320,7 +515,7 @@ public class MenuRenderer { // Заголовок titleFont.setColor(new Color(0.8f, 0.4f, 1.0f, 1)); - String title = "✨ ОБ ИГРЕ"; + String title = Localization.about(); layout.setText(titleFont, title); titleFont.draw(batch, title, width/2 - layout.width/2, height - 100); @@ -328,7 +523,7 @@ public class MenuRenderer { font.setColor(new Color(0.9f, 0.9f, 1.0f, 0.9f)); font.getData().setScale(1.2f); - String[] aboutText = { + String[] aboutText = Localization.isRu() ? new String[] { "Absurd City Builder - это уникальная игра,", "где вы строите безумные города на разных планетах!", "", @@ -336,12 +531,26 @@ public class MenuRenderer { "• 3 уникальные планеты с разными зданиями", "• Забавные математические задачи", "• Мультяшная графика и анимации", - "• Динамичные жители и шутки", - "• Бесконечные возможности для творчества!", + "• Система достижений", + "• Поддержка русского и английского языков", "", "Разработано с ❤️ для любителей абсурда и математики.", "", - "Версия 1.0" + "Версия 1.1" + } : new String[] { + "Absurd City Builder is a unique game", + "where you build crazy cities on different planets!", + "", + "Features:", + "• 3 unique planets with different buildings", + "• Fun math puzzles", + "• Cartoon graphics and animations", + "• Achievement system", + "• Russian and English support", + "", + "Made with ❤️ for absurdity and math lovers.", + "", + "Version 1.1" }; float textY = height - 200; @@ -356,9 +565,9 @@ public class MenuRenderer { // Кнопка "Назад" MenuButton backButton = new MenuButton( 50, 50, 200, 60, - "⬅️ НАЗАД", - new Color(0.4f, 0.4f, 0.4f, 0.9f), - new Color(0.5f, 0.5f, 0.5f, 1f), + Localization.back(), + GameConfig.BUTTON_BACK, + GameConfig.BUTTON_BACK_HOVER, () -> {} ); backButton.render(batch, font, layout, whitePixel); @@ -368,7 +577,7 @@ public class MenuRenderer { private void renderSpaceBackground() { // Темный космический фон - batch.setColor(new Color(0.05f, 0.05f, 0.1f, 1)); + batch.setColor(GameConfig.MENU_SPACE_BG); batch.draw(whitePixel, 0, 0, width, height); // Звезды @@ -399,7 +608,7 @@ public class MenuRenderer { float pulse = 0.8f + 0.2f * (float)Math.sin(titlePulse); titleFont.setColor(new Color(1, pulse, 0.5f, 1)); - String title = "✨ ABSURD CITY BUILDER ✨"; + String title = Localization.gameTitle(); layout.setText(titleFont, title); titleFont.draw(batch, title, width/2 - layout.width/2, height - 100); @@ -415,7 +624,13 @@ public class MenuRenderer { } public MenuButton getMainMenuButtonAt(float x, float y) { - for (MenuButton button : mainMenuButtons) { + boolean hasSave = GameSave.hasSave(); + for (int i = 0; i < mainMenuButtons.size(); i++) { + // Пропускаем кнопку "Продолжить" если нет сохранения + if (i == 0 && !hasSave) { + continue; + } + MenuButton button = mainMenuButtons.get(i); if (button.contains(x, y)) { return button; } @@ -441,6 +656,15 @@ public class MenuRenderer { return null; } + public MenuButton getAchievementsButtonAt(float x, float y) { + for (MenuButton button : achievementsButtons) { + if (button.contains(x, y)) { + return button; + } + } + return null; + } + public void dispose() { titleFont.dispose(); } diff --git a/core/src/main/java/com/mygdx/game/UIRenderer.java b/core/src/main/java/com/mygdx/game/UIRenderer.java index c86d67b..ebd46e2 100644 --- a/core/src/main/java/com/mygdx/game/UIRenderer.java +++ b/core/src/main/java/com/mygdx/game/UIRenderer.java @@ -32,11 +32,13 @@ public class UIRenderer { Building currentBuilding, Planet currentPlanet, boolean isSwitchingPlanets) { batch.begin(); - batch.setColor(0.2f, 0.3f, 0.4f, 0.95f); + // Фон панели + batch.setColor(GameConfig.UI_PANEL_BG); batch.draw(whitePixel, 0, 0, WIDTH, UI_INPUT_HEIGHT); batch.setColor(Color.WHITE); - batch.setColor(0.4f, 0.6f, 0.8f, 1); + // Граница панели + batch.setColor(GameConfig.UI_PANEL_BORDER); batch.draw(whitePixel, 0, UI_INPUT_HEIGHT, WIDTH, 3); batch.setColor(Color.WHITE); @@ -47,19 +49,20 @@ public class UIRenderer { // ==================== ЛЕВАЯ КОЛОНКА ==================== // Отображение текущей планеты - String planetDisplay = "🌍 Планета: " + currentPlanet.getName(); + String planetLabel = Localization.isRu() ? "🌍 Планета: " : "🌍 Planet: "; + String planetDisplay = planetLabel + Localization.planetName(currentPlanet); if (isSwitchingPlanets) { - planetDisplay += " (Перелет...)"; + planetDisplay += Localization.isRu() ? " (Перелет...)" : " (Flying...)"; } font.draw(batch, planetDisplay, 20, currentY); currentY -= lineHeight; // Управление планетой font.setColor(Color.YELLOW); - font.draw(batch, "↑/↓ - сменить планету", 20, currentY); + font.draw(batch, Localization.changePlanet(), 20, currentY); currentY -= lineHeight; font.setColor(Color.LIGHT_GRAY); - font.draw(batch, "1-Земля, 2-Марс, 3-Венера", 20, currentY); + font.draw(batch, Localization.planetKeys(), 20, currentY); currentY -= lineHeight; font.setColor(Color.WHITE); @@ -67,13 +70,14 @@ public class UIRenderer { currentY -= lineHeight; // Тип здания - String[] planetBuildings = Building.BUILDING_TYPES_BY_PLANET[currentPlanet.ordinal()]; - font.draw(batch, "🏗️ Тип здания: " + planetBuildings[selectedBuildingType], 20, currentY); + String[][] buildingNames = Localization.getBuildingNames(); + String buildingLabel = Localization.isRu() ? "🏗️ Тип здания: " : "🏗️ Building: "; + font.draw(batch, buildingLabel + buildingNames[currentPlanet.ordinal()][selectedBuildingType], 20, currentY); currentY -= lineHeight; // Управление зданиями font.setColor(Color.CYAN); - font.draw(batch, "←/→ - выбрать тип здания", 20, currentY); + font.draw(batch, Localization.selectBuildingType(), 20, currentY); currentY -= lineHeight; font.setColor(Color.WHITE); @@ -99,12 +103,8 @@ public class UIRenderer { currentY -= lineHeight; // Прогресс строительства - if (currentBuilding != null) { - font.draw(batch, "📊 Прогресс: " + currentBuilding.constructionProgress + "/3 блоков", - 20, currentY); - } else { - font.draw(batch, "📊 Прогресс: 0/3 блоков", 20, currentY); - } + int progress = currentBuilding != null ? currentBuilding.constructionProgress : 0; + font.draw(batch, Localization.buildingProgress(progress, 3), 20, currentY); currentY -= lineHeight; // ==================== ПРАВАЯ КОЛОНКА ==================== @@ -131,13 +131,13 @@ public class UIRenderer { private void renderInputSection(MathProblem currentProblem, String inputText, float time) { // Фон для ввода - batch.setColor(0.3f, 0.4f, 0.5f, 0.8f); + batch.setColor(GameConfig.UI_INPUT_BG); batch.draw(whitePixel, WIDTH/2 - 250, UI_INPUT_HEIGHT - 150, 500, 130); batch.setColor(Color.WHITE); // Задача font.setColor(Color.YELLOW); - String mathProblem = "🧮 Задача: " + currentProblem.getQuestion(); + String mathProblem = Localization.task(currentProblem.getQuestion()); glyphLayout.setText(font, mathProblem); font.draw(batch, mathProblem, WIDTH/2 - glyphLayout.width/2, @@ -145,7 +145,7 @@ public class UIRenderer { // Поле ввода font.setColor(Color.WHITE); - font.draw(batch, "✏️ Введите ответ:", WIDTH/2 - 230, UI_INPUT_HEIGHT - 95); + font.draw(batch, Localization.enterAnswer(), WIDTH/2 - 230, UI_INPUT_HEIGHT - 95); // Введенный текст String inputStr = inputText.isEmpty() ? "_" : inputText; @@ -161,15 +161,15 @@ public class UIRenderer { // Подсказки font.setColor(Color.LIGHT_GRAY); font.getData().setScale(0.7f); - font.draw(batch, "⏎ Enter - отправить ответ", WIDTH/2 - 230, UI_INPUT_HEIGHT - 160); - font.draw(batch, "⎋ ESC - отмена ввода", WIDTH/2 - 230, UI_INPUT_HEIGHT - 180); - font.draw(batch, "⌫ Backspace - удалить символ", WIDTH/2 - 230, UI_INPUT_HEIGHT - 200); + font.draw(batch, Localization.enterSubmit(), WIDTH/2 - 230, UI_INPUT_HEIGHT - 160); + font.draw(batch, Localization.escCancel(), WIDTH/2 - 230, UI_INPUT_HEIGHT - 180); + font.draw(batch, Localization.backspaceDelete(), WIDTH/2 - 230, UI_INPUT_HEIGHT - 200); font.getData().setScale(1.0f); } private void renderWrongAnswerJoke(String wrongAnswerJoke) { // Фон для шутки - batch.setColor(1, 0.2f, 0.2f, 0.3f); + batch.setColor(GameConfig.UI_WRONG_ANSWER_BG); batch.draw(whitePixel, WIDTH/2 - 300, HEIGHT/2 - 50, 600, 100); batch.setColor(Color.WHITE); @@ -183,25 +183,24 @@ public class UIRenderer { font.getData().setScale(1.0f); } - // ВОТ ТОТ САМЫЙ МЕТОД, КОТОРЫЙ ВЫ СПРАШИВАЛИ: private void renderBottomPanel(Planet planet, boolean isSwitchingPlanets) { font.setColor(Color.LIGHT_GRAY); font.getData().setScale(0.6f); // Основные инструкции - String instruction = "🖱️ Кликните на поле для строительства"; + String instruction = Localization.clickToBuild(); glyphLayout.setText(font, instruction); font.draw(batch, instruction, WIDTH/2 - glyphLayout.width/2, 30); // Управление - String controls = "🗑️ Delete/Ctrl+Z - удалить здание | ⌫ Backspace - удалить блок | ⎋ ESC - меню"; + String controls = Localization.controls(); glyphLayout.setText(font, controls); font.draw(batch, controls, WIDTH/2 - glyphLayout.width/2, 15); // Индикатор планеты - font.setColor(getPlanetColor(planet)); + font.setColor(GameConfig.getPlanetUIColor(planet)); font.getData().setScale(0.8f); - String planetInfo = getPlanetEmoji(planet) + " " + planet.getName(); + String planetInfo = GameConfig.getPlanetEmoji(planet) + " " + Localization.planetName(planet); if (isSwitchingPlanets) { planetInfo += " 🚀"; } @@ -210,25 +209,6 @@ public class UIRenderer { font.getData().setScale(1.0f); } - // Вспомогательные методы для работы с планетами: - private Color getPlanetColor(Planet planet) { - switch (planet) { - case EARTH: return new Color(0.3f, 0.7f, 1.0f, 1); - case MARS: return new Color(1.0f, 0.4f, 0.3f, 1); - case VENUS: return new Color(1.0f, 0.8f, 0.3f, 1); - default: return Color.WHITE; - } - } - - private String getPlanetEmoji(Planet planet) { - switch (planet) { - case EARTH: return "🌍"; - case MARS: return "♂️"; - case VENUS: return "♀️"; - default: return "🪐"; - } - } - private void drawWrappedText(String text, float x, float y, float maxWidth) { String[] words = text.split(" "); StringBuilder line = new StringBuilder();