Compare commits

3 Commits

Author SHA1 Message Date
kirill.khorkov
e0ad1b8de3 Fix Localization for game. 2025-12-16 01:18:11 +03:00
kirill.khorkov
d2a9b1d4ce Fix commit format 2025-12-16 01:00:26 +03:00
kirill.khorkov
cbd5bb8b42 feat: добавлены сохранения, достижения и локализация
- GameConfig: вынесены общие константы и цвета
- GameSave: система сохранения/загрузки через LibGDX Preferences
- Achievement/Achievements: система достижений (10 ачивок)
- AchievementPopup: всплывающие уведомления о достижениях
- Localization: поддержка RU/EN с переключением в меню
- MenuRenderer: обновлено меню (Продолжить, Достижения, смена языка)
- UIRenderer: локализованные строки
- AnswerChecker: интеграция с сохранениями и достижениями
- Building: использует GameConfig для констант
2025-12-16 00:56:13 +03:00
16 changed files with 2282 additions and 615 deletions

View File

@@ -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,14 +262,10 @@ 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;
}
}
}
}
private void handleAboutInput(float mouseX, float mouseY, boolean isClicked) {
if (isClicked) {
@@ -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();

View File

@@ -0,0 +1,92 @@
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;
}
}

View File

@@ -0,0 +1,120 @@
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();
}
}

View File

@@ -0,0 +1,184 @@
package com.mygdx.game;
import java.util.HashSet;
import java.util.Set;
// Менеджер достижений - проверка условий и разблокировка.
public class Achievements {
private static Set<Achievement> 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<Achievement> getUnlocked() {
return new HashSet<>(unlocked);
}
// Получить все достижения
public static Achievement[] getAll() {
return Achievement.values();
}
}

View File

@@ -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();
String[] planetComments = FUNNY_COMMENTS_BY_PLANET[planetIndex];
String successMessage = "Отлично! Блок построен!";
// Увеличиваем счетчик серии правильных ответов
GameSave.addCorrectAnswer();
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);
@@ -115,7 +57,10 @@ public class AnswerChecker {
// Неправильный ответ
game.getCurrentBuilding().removeBlock();
String[] planetJokes = WRONG_ANSWER_JOKES_BY_PLANET[planetIndex];
// Сбрасываем счетчик серии
GameSave.resetCorrectStreak();
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,6 +132,7 @@ public class AnswerChecker {
}
private static String getBonusMessage(Planet planet, int buildingsCount) {
if (Localization.isRu()) {
switch (planet) {
case EARTH:
return "🎉 Вы построили " + buildingsCount + " зданий на Земле!";
@@ -208,13 +143,25 @@ public class AnswerChecker {
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();
if (Localization.isRu()) {
switch (planet) {
case MARS:
if (question.contains("+")) {
@@ -243,7 +190,37 @@ public class AnswerChecker {
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!";
}
}
}

View File

@@ -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;

View File

@@ -73,8 +73,8 @@ public class BuildingPlacer {
game.updateUI();
game.setMessageText(tempBuilding.isOverlapping ?
"🎨 Здание пересекается с существующими! Это добавляет уникальности! 🎨" :
"🌟 Отличное место для строительства! Введите ответ: 🌟");
Localization.buildingOverlaps() :
Localization.greatPlace());
game.setMessageColor(tempBuilding.isOverlapping ? com.badlogic.gdx.graphics.Color.ORANGE : com.badlogic.gdx.graphics.Color.GREEN);
game.setTyping(true);
@@ -85,7 +85,7 @@ public class BuildingPlacer {
if (game.getCurrentBuilding() != null) {
Rectangle buildingBounds = game.getCurrentBuilding().getBounds();
if (buildingBounds.contains(worldX, worldY)) {
game.setMessageText("🎯 Кликните вне здания для нового строительства. Ctrl+Z или Delete для удаления. 🎯");
game.setMessageText(Localization.clickOutside());
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
} else {
if (!game.isTyping()) {

View File

@@ -1226,7 +1226,8 @@ public class BuildingRenderer {
font.setColor(pulseColor);
font.getData().setScale(1.1f * building.getSizeScale());
glyphLayout.setText(font, building.type);
String localizedName = Localization.getBuildingName(building);
glyphLayout.setText(font, localizedName);
float textWidth = glyphLayout.width;
// Фон с закругленными краями
@@ -1241,7 +1242,7 @@ public class BuildingRenderer {
batch.draw(whitePixel, x - textWidth/2 - 15, y + 10, textWidth + 30, 5); // Низ
batch.setColor(Color.WHITE);
font.draw(batch, building.type, x - textWidth/2, y);
font.draw(batch, localizedName, x - textWidth/2, y);
font.getData().setScale(1.0f);
}
@@ -1252,9 +1253,8 @@ public class BuildingRenderer {
font.setColor(Color.YELLOW);
font.getData().setScale(0.9f * building.getSizeScale());
String cleanType = building.type.replace("", "").replace("🏥", "").replace("🎒", "")
.replace("🎪", "").replace("💰", "").replace("💊", "")
.replace("🎭", "").replace("🎬", "").trim();
String localizedName = Localization.getBuildingName(building);
String cleanType = localizedName.replaceAll("[✨🏥🎒🎪💰💊🎭🎬🚀🔴🛰️⚡💧🌌🤖🧪🌋🔥🌅☁️💎🌡️🌀]", "").trim();
String progressText = cleanType + " (" + building.constructionProgress + "/3)";
glyphLayout.setText(font, progressText);
float textWidth = glyphLayout.width;
@@ -1274,10 +1274,9 @@ public class BuildingRenderer {
font.setColor(Color.YELLOW);
font.getData().setScale(1.0f * building.getSizeScale());
String cleanType = building.type.replace("", "").replace("🏥", "").replace("🎒", "")
.replace("🎪", "").replace("💰", "").replace("💊", "")
.replace("🎭", "").replace("🎬", "").trim();
String prefix = building.constructionProgress == 0 ? "Место для: " : "Строится: ";
String localizedName = Localization.getBuildingName(building);
String cleanType = localizedName.replaceAll("[✨🏥🎒🎪💰💊🎭🎬🚀🔴🛰️⚡💧🌌🤖🧪🌋🔥🌅☁️💎🌡️🌀]", "").trim();
String prefix = building.constructionProgress == 0 ? Localization.placeFor() : Localization.constructing();
String progressText = prefix + cleanType + " (" + building.constructionProgress + "/3)";
glyphLayout.setText(font, progressText);
float textWidth = glyphLayout.width;
@@ -1291,7 +1290,7 @@ public class BuildingRenderer {
if (building.isOverlapping) {
font.setColor(Color.RED);
font.getData().setScale(0.8f * building.getSizeScale());
String warning = "⚠ Пересечение! ⚠";
String warning = Localization.overlapWarning();
glyphLayout.setText(font, warning);
font.draw(batch, warning, x - glyphLayout.width/2, y - 25);
font.getData().setScale(1.0f);

View File

@@ -0,0 +1,250 @@
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 "🪐";
}
}
}

View File

@@ -0,0 +1,345 @@
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<Building> 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<Building> buildings, Array<Citizen> 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;
}
}

View File

@@ -5,5 +5,6 @@ public enum GameState {
PLAYING, // Игровой процесс
PLANET_SELECT, // Выбор планеты
HELP, // Помощь/инструкции
ABOUT // Об игре
ABOUT, // Об игре
ACHIEVEMENTS // Достижения
}

View File

@@ -18,8 +18,8 @@ public class InputHandler {
game.setSelectedBuildingType(newType);
game.updateUI();
game.setMessageText("Выбран: " +
Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()][newType]);
game.setMessageText(Localization.selected() + ": " +
Localization.getBuildingName(game.getCurrentPlanet(), newType));
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
}
}
@@ -31,8 +31,8 @@ public class InputHandler {
game.setSelectedBuildingType(newType);
game.updateUI();
game.setMessageText("Выбран: " +
Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()][newType]);
game.setMessageText(Localization.selected() + ": " +
Localization.getBuildingName(game.getCurrentPlanet(), newType));
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
}
}
@@ -72,15 +72,15 @@ public class InputHandler {
game.setCurrentProblem(null);
game.setTyping(false);
game.getInputText().setLength(0);
game.setMessageText("Строительство отменено. Выберите новое место.");
game.setMessageText(Localization.constructionCancelled());
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
game.updateUI();
} else if (game.getBuildings().size > 0) {
game.getBuildings().removeIndex(game.getBuildings().size - 1);
game.setMessageText("Последнее здание удалено.");
game.setMessageText(Localization.lastBuildingRemoved());
game.setMessageColor(com.badlogic.gdx.graphics.Color.ORANGE);
} else {
game.setMessageText("Нет зданий для удаления.");
game.setMessageText(Localization.noBuildingsToRemove());
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
}
}
@@ -128,7 +128,7 @@ public class InputHandler {
game.getInputText().deleteCharAt(game.getInputText().length() - 1);
} else if (!game.isTyping() && game.getCurrentBuilding() != null && game.getCurrentBuilding().constructionProgress > 0) {
game.getCurrentBuilding().removeBlock();
game.setMessageText("Блок удален! Текущий прогресс: " + game.getCurrentBuilding().constructionProgress + "/3");
game.setMessageText(Localization.blockRemoved(game.getCurrentBuilding().constructionProgress));
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
game.updateUI();
}
@@ -143,7 +143,7 @@ public class InputHandler {
if (game.isTyping()) {
game.setTyping(false);
game.getInputText().setLength(0);
game.setMessageText("Ввод отменен. Можно продолжить строительство.");
game.setMessageText(Localization.inputCancelled());
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
}
}

View File

@@ -0,0 +1,685 @@
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 selected() {
return isRu() ? "Выбран" : "Selected";
}
public static String overlapping() {
return isRu() ? "(пересекается!)" : "(overlapping!)";
}
public static String colorTheme() {
return isRu() ? "Цвет: Тема" : "Color: Theme";
}
public static String building() {
return isRu() ? "Строим" : "Building";
}
public static String planet() {
return isRu() ? "Планета" : "Planet";
}
public static String buildingType() {
return isRu() ? "Тип здания" : "Building type";
}
public static String arrowsToSelect() {
return isRu() ? "(←/→ для выбора, кликните для строительства)" : "(←/→ to select, click to build)";
}
public static String menu() {
return isRu() ? "меню" : "menu";
}
public static String flyingTo() {
return isRu() ? "Перелет на" : "Flying to";
}
public static String placeFor() {
return isRu() ? "Место для: " : "Place for: ";
}
public static String constructing() {
return isRu() ? "Строится: " : "Building: ";
}
public static String overlapWarning() {
return isRu() ? "⚠ Пересечение! ⚠" : "⚠ Overlap! ⚠";
}
public static String buildingOverlaps() {
return isRu()
? "🎨 Здание пересекается с существующими! Это добавляет уникальности! 🎨"
: "🎨 Building overlaps with existing ones! This adds uniqueness! 🎨";
}
public static String greatPlace() {
return isRu()
? "🌟 Отличное место для строительства! Введите ответ: 🌟"
: "🌟 Great place to build! Enter your answer: 🌟";
}
public static String clickOutside() {
return isRu()
? "🎯 Кликните вне здания для нового строительства. Ctrl+Z или Delete для удаления. 🎯"
: "🎯 Click outside building for new construction. Ctrl+Z or Delete to remove. 🎯";
}
public static String constructionCancelled() {
return isRu()
? "Строительство отменено. Выберите новое место."
: "Construction cancelled. Select a new place.";
}
public static String lastBuildingRemoved() {
return isRu() ? "Последнее здание удалено." : "Last building removed.";
}
public static String inputCancelled() {
return isRu()
? "Ввод отменен. Можно продолжить строительство."
: "Input cancelled. You can continue building.";
}
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 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;
}
// Получить локализованное название здания по индексам
public static String getBuildingName(Planet planet, int typeIndex) {
return getBuildingNames()[planet.ordinal()][typeIndex];
}
// Получить локализованное название для Building объекта
public static String getBuildingName(Building building) {
return getBuildingNames()[building.planetIndex][building.buildingTypeIndex];
}
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";
}
}

View File

@@ -20,6 +20,7 @@ public class MenuRenderer {
private List<MenuButton> mainMenuButtons;
private List<MenuButton> planetSelectButtons;
private List<MenuButton> helpButtons;
private List<MenuButton> achievementsButtons;
private float titlePulse = 0;
private float starTimer = 0;
@@ -40,61 +41,79 @@ 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 +124,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 +164,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 +201,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 +232,61 @@ 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 +295,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 +312,21 @@ public class MenuRenderer {
font.getData().setScale(0.9f);
// Земля
String earthText = "Мультяшные здания\ркие цвета\nМилые жители";
layout.setText(font, earthText);
String earthText = Localization.isRu()
? "Мультяшные здания\ркие цвета\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 +342,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 +359,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 +376,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 +419,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 +511,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 +519,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 +527,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 +561,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 +573,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 +604,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 +620,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 +652,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();
}

View File

@@ -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();

View File

@@ -7,27 +7,26 @@ public class UIUpdater {
}
Planet planet = game.getCurrentPlanet();
String[] planetBuildings = Building.BUILDING_TYPES_BY_PLANET[planet.ordinal()];
if (game.getCurrentBuilding() != null && game.getCurrentProblem() != null) {
String overlapText = game.getCurrentBuilding().isOverlapping ? " (пересекается!)" : "";
String overlapText = game.getCurrentBuilding().isOverlapping ? " " + Localization.overlapping() : "";
String colorInfo = "";
if (game.getCurrentBuilding().isComplete()) {
colorInfo = String.format(" [Цвет: Тема %d]", game.getCurrentBuilding().colorThemeIndex + 1);
colorInfo = String.format(" [%s %d]", Localization.colorTheme(), game.getCurrentBuilding().colorThemeIndex + 1);
}
String fullText = "Строим " + game.getCurrentBuilding().type +
String fullText = Localization.building() + " " + Localization.getBuildingName(game.getCurrentBuilding()) +
" (" + game.getCurrentBuilding().constructionProgress + "/3)" + colorInfo +
": " + game.getCurrentProblem().getQuestion() + overlapText;
game.setProblemText(fullText);
} else {
String planetText = game.isSwitchingPlanets() ?
"Перелет на " + game.getTargetPlanet().getName() + "..." :
"Планета: " + planet.getName();
Localization.flyingTo() + " " + Localization.planetName(game.getTargetPlanet()) + "..." :
Localization.planet() + ": " + Localization.planetName(planet);
game.setProblemText(planetText +
" | Тип здания: " + planetBuildings[game.getSelectedBuildingType()] +
" (←/→ для выбора, кликните на поле для строительства)" +
" | ESC - меню");
" | " + Localization.buildingType() + ": " + Localization.getBuildingName(planet, game.getSelectedBuildingType()) +
" " + Localization.arrowsToSelect() +
" | ESC - " + Localization.menu());
}
}
}