Initial repo commit

This commit is contained in:
kirill.khorkov
2025-12-16 00:05:18 +03:00
parent 48f0f8e363
commit 59508e1ebb
85 changed files with 6838 additions and 0 deletions

15
core/build.gradle Normal file
View File

@@ -0,0 +1,15 @@
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
eclipse.project.name = appName + '-core'
dependencies {
api "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
api "com.badlogicgames.gdx:gdx-bullet:$gdxVersion"
api "com.badlogicgames.gdx:gdx:$gdxVersion"
api "com.kotcrab.vis:vis-ui:$visUiVersion"
api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
api "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
if(enableGraalNative == 'true') {
implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion"
}
}

View File

@@ -0,0 +1,557 @@
package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
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;
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;
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 SpriteBatch batch;
private ShapeRenderer shapeRenderer;
private OrthographicCamera camera;
private Viewport viewport;
private BitmapFont font;
private GlyphLayout glyphLayout;
private Texture whitePixel;
// Игровые объекты
private Array<Building> buildings;
private Building currentBuilding;
private MathProblem currentProblem;
private Random random;
private Array<Citizen> citizens;
private Array<JokeBubble> jokeBubbles;
// Переменные игры
private float time = 0;
private boolean showWrongAnswerJoke = false;
private String wrongAnswerJoke = "";
private float jokeTimer = 0;
// UI переменные
private int selectedBuildingType = 0;
private StringBuilder inputText = new StringBuilder();
private boolean isTyping = false;
private String messageText = "Добро пожаловать! Выберите здание и кликните на поле.";
private Color messageColor = Color.WHITE;
private String problemText = "Нажмите ESC для возврата в меню";
// Текстуры и рендереры
private Texture backgroundTexture;
private BuildingRenderer buildingRenderer;
private UIRenderer uiRenderer;
private MenuRenderer menuRenderer;
// Планета
private Planet currentPlanet;
private float planetSwitchTimer = 0;
private boolean isSwitchingPlanets = false;
private Planet targetPlanet;
// Состояние игры
private GameState gameState = GameState.MAIN_MENU;
private boolean wasJustClicked = false;
@Override
public void create() {
batch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
GameAssets.createFonts();
font = GameAssets.getFont();
glyphLayout = new GlyphLayout();
whitePixel = GameAssets.createWhitePixel();
camera = new OrthographicCamera();
viewport = new FitViewport(WIDTH, HEIGHT, camera);
viewport.apply();
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
random = new Random();
buildings = new Array<>();
citizens = new Array<>();
jokeBubbles = new Array<>();
// Начинаем с Земли
currentPlanet = Planet.EARTH;
try {
backgroundTexture = new Texture(Gdx.files.internal("фон4.png"));
} catch (Exception e) {
backgroundTexture = null;
}
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);
updateUI();
}
@Override
public void render() {
handleInput();
update();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
shapeRenderer.setProjectionMatrix(camera.combined);
switch (gameState) {
case MAIN_MENU:
renderMainMenu();
break;
case PLANET_SELECT:
renderPlanetSelect();
break;
case HELP:
renderHelp();
break;
case ABOUT:
renderAbout();
break;
case PLAYING:
renderGame();
break;
}
}
private void handleInput() {
// Обработка кликов мыши
boolean isClicked = Gdx.input.justTouched();
float mouseX = Gdx.input.getX();
float mouseY = HEIGHT - Gdx.input.getY(); // Инвертируем Y
// ESC для возврата в меню из игры
if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
if (gameState == GameState.PLAYING) {
if (isTyping) {
// Отмена ввода
setTyping(false);
getInputText().setLength(0);
setMessageText("Ввод отменен.");
setMessageColor(Color.YELLOW);
} else {
// Возврат в главное меню
gameState = GameState.MAIN_MENU;
setMessageText("Игра приостановлена. Нажмите ESC для продолжения.");
}
} else if (gameState != GameState.MAIN_MENU) {
// Возврат в главное меню из других состояний
gameState = GameState.MAIN_MENU;
}
}
// Обработка состояний меню
switch (gameState) {
case MAIN_MENU:
handleMainMenuInput(mouseX, mouseY, isClicked);
break;
case PLANET_SELECT:
handlePlanetSelectInput(mouseX, mouseY, isClicked);
break;
case HELP:
handleHelpInput(mouseX, mouseY, isClicked);
break;
case ABOUT:
handleAboutInput(mouseX, mouseY, isClicked);
break;
case PLAYING:
InputHandler.handleInput(this);
break;
}
wasJustClicked = isClicked;
}
private void handleMainMenuInput(float mouseX, float mouseY, boolean isClicked) {
if (isClicked) {
MenuButton clickedButton = menuRenderer.getMainMenuButtonAt(mouseX, mouseY);
if (clickedButton != null) {
String buttonText = clickedButton.getText(); // Используйте геттер
if (buttonText.contains("НОВАЯ ИГРА")) {
startNewGame();
} else if (buttonText.contains("ВЫБОР ПЛАНЕТЫ")) {
gameState = GameState.PLANET_SELECT;
} else if (buttonText.contains("ПОМОЩЬ")) {
gameState = GameState.HELP;
} else if (buttonText.contains("ОБ ИГРЕ")) {
gameState = GameState.ABOUT;
} else if (buttonText.contains("ВЫХОД")) {
Gdx.app.exit();
}
}
}
}
private void handlePlanetSelectInput(float mouseX, float mouseY, boolean isClicked) {
if (isClicked) {
MenuButton clickedButton = menuRenderer.getPlanetSelectButtonAt(mouseX, mouseY);
if (clickedButton != null) {
String buttonText = clickedButton.getText(); // Используйте геттер
if (buttonText.contains("ЗЕМЛЯ")) {
startNewGameOnPlanet(Planet.EARTH);
} else if (buttonText.contains("МАРС")) {
startNewGameOnPlanet(Planet.MARS);
} else if (buttonText.contains("ВЕНЕРА")) {
startNewGameOnPlanet(Planet.VENUS);
} else if (buttonText.contains("НАЗАД")) {
gameState = GameState.MAIN_MENU;
}
}
}
}
private void handleHelpInput(float mouseX, float mouseY, boolean isClicked) {
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) {
// Простая проверка на кнопку "Назад"
if (mouseX >= 50 && mouseX <= 250 && mouseY >= 50 && mouseY <= 110) {
gameState = GameState.MAIN_MENU;
}
}
}
private void startNewGame() {
// Очищаем всё и начинаем новую игру на Земле
buildings.clear();
citizens.clear();
jokeBubbles.clear();
currentBuilding = null;
currentProblem = null;
selectedBuildingType = 0;
inputText.setLength(0);
isTyping = false;
currentPlanet = Planet.EARTH;
isSwitchingPlanets = false;
messageText = "Добро пожаловать на Землю! Выберите здание и кликните на поле.";
messageColor = Color.GREEN;
gameState = GameState.PLAYING;
updateUI();
}
private void startNewGameOnPlanet(Planet planet) {
// Очищаем всё и начинаем новую игру на выбранной планете
buildings.clear();
citizens.clear();
jokeBubbles.clear();
currentBuilding = null;
currentProblem = null;
selectedBuildingType = 0;
inputText.setLength(0);
isTyping = false;
currentPlanet = planet;
isSwitchingPlanets = false;
messageText = "Добро пожаловать на " + planet.getName() + "! Выберите здание и кликните на поле.";
messageColor = Color.GREEN;
gameState = GameState.PLAYING;
updateUI();
}
private void update() {
float deltaTime = Gdx.graphics.getDeltaTime();
time += deltaTime;
// Обновляем меню
menuRenderer.update(deltaTime);
// Обработка плавной смены планет
if (isSwitchingPlanets) {
planetSwitchTimer += deltaTime;
if (planetSwitchTimer >= 1.0f) {
currentPlanet = targetPlanet;
isSwitchingPlanets = false;
setMessageText("Добро пожаловать на " + currentPlanet.getName() + "! 🌍");
}
}
if (gameState == GameState.PLAYING) {
for (Building b : buildings) {
b.update(deltaTime);
}
if (currentBuilding != null) {
currentBuilding.update(deltaTime);
}
// Обновляем жителей
for (Citizen citizen : citizens) {
citizen.update(deltaTime);
}
// Обновляем пузыри с шутками
for (int i = jokeBubbles.size - 1; i >= 0; i--) {
JokeBubble bubble = jokeBubbles.get(i);
bubble.update(deltaTime);
if (bubble.isExpired()) {
jokeBubbles.removeIndex(i);
}
}
// Обновляем таймер шутки
if (showWrongAnswerJoke) {
jokeTimer += deltaTime;
if (jokeTimer > 3.0f) {
showWrongAnswerJoke = false;
}
}
}
}
public void checkAnswer() {
AnswerChecker.checkAnswer(this);
}
public void startPlanetSwitch(Planet newPlanet) {
if (currentPlanet == newPlanet || isSwitchingPlanets) return;
isSwitchingPlanets = true;
targetPlanet = newPlanet;
planetSwitchTimer = 0;
// Очищаем город при смене планеты
buildings.clear();
citizens.clear();
jokeBubbles.clear();
currentBuilding = null;
currentProblem = null;
selectedBuildingType = 0;
setMessageText("Запускаем космический корабль на " + newPlanet.getName() + "! 🚀");
setMessageColor(Color.YELLOW);
updateUI();
}
public void updateUI() {
UIUpdater.updateUI(this);
}
private void renderMainMenu() {
float mouseX = Gdx.input.getX();
float mouseY = HEIGHT - Gdx.input.getY();
menuRenderer.renderMainMenu(mouseX, mouseY);
}
private void renderPlanetSelect() {
float mouseX = Gdx.input.getX();
float mouseY = HEIGHT - Gdx.input.getY();
menuRenderer.renderPlanetSelect(mouseX, mouseY);
}
private void renderHelp() {
float mouseX = Gdx.input.getX();
float mouseY = HEIGHT - Gdx.input.getY();
menuRenderer.renderHelp(mouseX, mouseY);
}
private void renderAbout() {
float mouseX = Gdx.input.getX();
float mouseY = HEIGHT - Gdx.input.getY();
menuRenderer.renderAbout(mouseX, mouseY);
}
private void renderGame() {
renderBackground();
renderBuildings();
renderCitizens();
renderJokeBubbles();
renderBuildingNames();
renderPlanetTransition();
renderUI();
}
private void renderBackground() {
batch.begin();
Color bgColor;
if (isSwitchingPlanets) {
// Плавный переход между цветами
Color fromColor = currentPlanet.getColor();
Color toColor = targetPlanet.getColor();
float progress = Math.min(planetSwitchTimer * 2, 1.0f);
bgColor = new Color(
fromColor.r + (toColor.r - fromColor.r) * progress,
fromColor.g + (toColor.g - fromColor.g) * progress,
fromColor.b + (toColor.b - fromColor.b) * progress,
1
);
} else {
bgColor = currentPlanet.getColor();
}
if (backgroundTexture != null) {
batch.setColor(bgColor);
batch.draw(backgroundTexture, 0, UI_INPUT_HEIGHT, WIDTH, HEIGHT - UI_INPUT_HEIGHT);
batch.setColor(Color.WHITE);
} else {
batch.setColor(bgColor);
batch.draw(whitePixel, 0, UI_INPUT_HEIGHT, WIDTH, HEIGHT - UI_INPUT_HEIGHT);
batch.setColor(Color.WHITE);
}
batch.end();
}
private void renderBuildings() {
buildingRenderer.renderBuildings(buildings, currentBuilding, time, currentPlanet);
}
private void renderCitizens() {
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
for (Citizen citizen : citizens) {
citizen.draw(shapeRenderer, time);
}
shapeRenderer.end();
}
private void renderJokeBubbles() {
for (JokeBubble bubble : jokeBubbles) {
bubble.draw(batch, shapeRenderer, font, glyphLayout, whitePixel);
}
}
private void renderBuildingNames() {
buildingRenderer.renderBuildingNames(buildings, currentBuilding);
}
private void renderPlanetTransition() {
if (!isSwitchingPlanets) return;
batch.begin();
// Затемнение экрана
float alpha = Math.min(planetSwitchTimer * 2, 1.0f);
batch.setColor(0, 0, 0, alpha * 0.7f);
batch.draw(whitePixel, 0, 0, WIDTH, HEIGHT);
// Текст перехода
font.setColor(1, 1, 1, alpha);
font.getData().setScale(1.5f);
String transitionText;
if (planetSwitchTimer < 0.5f) {
transitionText = "Покидаем " + currentPlanet.getName() + "...";
} else {
transitionText = "Прибываем на " + targetPlanet.getName() + "!";
}
glyphLayout.setText(font, transitionText);
font.draw(batch, transitionText,
WIDTH/2 - glyphLayout.width/2,
HEIGHT/2 + 50);
font.getData().setScale(1.0f);
batch.end();
}
private void renderUI() {
uiRenderer.renderUI(selectedBuildingType, problemText, messageText, messageColor,
isTyping, currentProblem, inputText.toString(), showWrongAnswerJoke,
wrongAnswerJoke, time, currentBuilding, currentPlanet, isSwitchingPlanets);
}
@Override
public void resize(int width, int height) {
viewport.update(width, height);
}
@Override
public void dispose() {
batch.dispose();
shapeRenderer.dispose();
font.dispose();
if (backgroundTexture != null) {
backgroundTexture.dispose();
}
if (whitePixel != null) {
whitePixel.dispose();
}
menuRenderer.dispose();
}
// Геттеры и сеттеры
public int getWIDTH() { return WIDTH; }
public int getHEIGHT() { return HEIGHT; }
public int getUI_INPUT_HEIGHT() { return UI_INPUT_HEIGHT; }
public int getSelectedBuildingType() { return selectedBuildingType; }
public void setSelectedBuildingType(int selectedBuildingType) { this.selectedBuildingType = selectedBuildingType; }
public StringBuilder getInputText() { return inputText; }
public boolean isTyping() { return isTyping; }
public void setTyping(boolean typing) { isTyping = typing; }
public String getMessageText() { return messageText; }
public void setMessageText(String messageText) { this.messageText = messageText; }
public Color getMessageColor() { return messageColor; }
public void setMessageColor(Color messageColor) { this.messageColor = messageColor; }
public String getProblemText() { return problemText; }
public void setProblemText(String problemText) { this.problemText = problemText; }
public Array<Building> getBuildings() { return buildings; }
public Building getCurrentBuilding() { return currentBuilding; }
public void setCurrentBuilding(Building currentBuilding) { this.currentBuilding = currentBuilding; }
public MathProblem getCurrentProblem() { return currentProblem; }
public void setCurrentProblem(MathProblem currentProblem) { this.currentProblem = currentProblem; }
public Random getRandom() { return random; }
public Array<Citizen> getCitizens() { return citizens; }
public Array<JokeBubble> getJokeBubbles() { return jokeBubbles; }
public boolean isShowWrongAnswerJoke() { return showWrongAnswerJoke; }
public void setShowWrongAnswerJoke(boolean showWrongAnswerJoke) { this.showWrongAnswerJoke = showWrongAnswerJoke; }
public String getWrongAnswerJoke() { return wrongAnswerJoke; }
public void setWrongAnswerJoke(String wrongAnswerJoke) { this.wrongAnswerJoke = wrongAnswerJoke; }
public float getJokeTimer() { return jokeTimer; }
public void setJokeTimer(float jokeTimer) { this.jokeTimer = jokeTimer; }
public Texture getWhitePixel() { return whitePixel; }
public BitmapFont getFont() { return font; }
public GlyphLayout getGlyphLayout() { return glyphLayout; }
public ShapeRenderer getShapeRenderer() { return shapeRenderer; }
public SpriteBatch getBatch() { return batch; }
public float getTime() { return time; }
public Planet getCurrentPlanet() { return currentPlanet; }
public void setCurrentPlanet(Planet planet) { this.currentPlanet = planet; }
public boolean isSwitchingPlanets() { return isSwitchingPlanets; }
public Planet getTargetPlanet() { return targetPlanet; }
public float getPlanetSwitchTimer() { return planetSwitchTimer; }
public GameState getGameState() { return gameState; }
public void setGameState(GameState state) { this.gameState = state; }
}

View File

@@ -0,0 +1,249 @@
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.setMessageColor(Color.RED);
return;
}
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 = "Отлично! Блок построен!";
if (game.getCurrentBuilding().isComplete()) {
successMessage = "Успех! " + planetComments[game.getRandom().nextInt(planetComments.length)];
game.getBuildings().add(game.getCurrentBuilding());
// Создаем жителей при завершении здания
game.getCurrentBuilding().createCitizensForBuilding(game.getCitizens(), game.getRandom());
// Проверяем разблокировку планет
checkPlanetUnlock(game);
game.setCurrentBuilding(null);
game.setCurrentProblem(null);
game.setTyping(false);
} else {
game.setCurrentProblem(MathProblem.generateProblem(game.getBuildings().size, game.getRandom()));
}
game.setMessageText(successMessage);
game.setMessageColor(Color.GREEN);
} else {
// Неправильный ответ
game.getCurrentBuilding().removeBlock();
String[] planetJokes = WRONG_ANSWER_JOKES_BY_PLANET[planetIndex];
String joke = planetJokes[game.getRandom().nextInt(planetJokes.length)];
game.setWrongAnswerJoke(joke);
game.setShowWrongAnswerJoke(true);
game.setJokeTimer(0);
// Создаем пузырь с шуткой
if (game.getCitizens().size > 0) {
Citizen randomCitizen = game.getCitizens().get(game.getRandom().nextInt(game.getCitizens().size));
game.getJokeBubbles().add(new JokeBubble(joke, randomCitizen.x, randomCitizen.y + 60, game.getRandom()));
}
String message;
if (game.getCurrentBuilding().constructionProgress == 0) {
message = "Здание разрушено до основания! " + joke;
game.setCurrentBuilding(null);
game.setCurrentProblem(null);
game.setTyping(false);
} else {
message = "Неверно! Блок разрушен! " + joke;
game.setCurrentProblem(MathProblem.generateProblem(game.getBuildings().size, game.getRandom()));
}
game.setMessageText(message);
game.setMessageColor(Color.RED);
}
game.updateUI();
game.getInputText().setLength(0);
} 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.setMessageColor(Color.RED);
game.getInputText().setLength(0);
}
}
private static void checkPlanetUnlock(AbsurdCityBuilder1 game) {
Planet currentPlanet = game.getCurrentPlanet();
int buildingsCount = game.getBuildings().size;
// Проверяем условия для разблокировки Марса
if (currentPlanet == Planet.EARTH && buildingsCount >= 3) {
// Марс уже разблокирован по умолчанию в нашей реализации
// Но можно добавить специальное сообщение
if (buildingsCount == 3) {
game.setMessageText(game.getMessageText() + " 🚀 Марс доступен! Нажмите ↑ для полёта!");
game.setMessageColor(Color.CYAN);
}
}
// Проверяем условия для разблокировки Венеры
if (currentPlanet == Planet.MARS && buildingsCount >= 6) {
// Венера уже разблокирована
if (buildingsCount == 6) {
game.setMessageText(game.getMessageText() + " 🔥 Венера доступна! Нажмите ↑ для полёта!");
game.setMessageColor(Color.ORANGE);
}
}
// Бонус за много построек
if (buildingsCount % 5 == 0) {
String bonusMessage = getBonusMessage(currentPlanet, buildingsCount);
game.setMessageText(game.getMessageText() + " " + bonusMessage);
}
}
private static String getBonusMessage(Planet planet, int buildingsCount) {
switch (planet) {
case EARTH:
return "🎉 Вы построили " + buildingsCount + " зданий на Земле!";
case MARS:
return "👽 Марсианская колония из " + buildingsCount + " зданий!";
case VENUS:
return "🌟 Венерианский мегаполис из " + buildingsCount + " зданий!";
default:
return "🏆 Достижение: " + buildingsCount + " зданий!";
}
}
// Метод для получения подсказки (опционально)
public static String getHint(MathProblem problem, Planet planet) {
int answer = problem.getAnswer();
String question = problem.getQuestion();
switch (planet) {
case MARS:
if (question.contains("+")) {
return "Подсказка: складывай как марсиане - от красного к красному!";
} else if (question.contains("-")) {
return "Подсказка: вычитай как улетающую ракету!";
} else if (question.contains("×")) {
return "Подсказка: умножай на количество марсоходов!";
}
break;
case VENUS:
if (question.contains("+")) {
return "Подсказка: складывай жар как на Венере!";
} else if (question.contains("-")) {
return "Подсказка: вычитай облака кислоты!";
} else if (question.contains("×")) {
return "Подсказка: умножай как давление на Венере!";
}
break;
default:
if (question.contains("+")) {
return "Подсказка: представь, что складываешь мультяшных зверюшек!";
} else if (question.contains("-")) {
return "Подсказка: убери лишние мультяшные детали!";
} else if (question.contains("×")) {
return "Подсказка: умножай как в мультике - всё становится больше!";
}
}
return "Подсказка: внимательно посчитай!";
}
}

View File

@@ -0,0 +1,441 @@
package com.mygdx.game;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Rectangle;
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) // Светло-золотой
}
};
String type;
float x;
float y;
float width;
float height;
Color[] colors;
Color roofColor;
Color detailColor;
int constructionProgress;
boolean isOverlapping;
float[] cloudOffsets;
int colorThemeIndex;
boolean showName;
float namePulse;
Color nameColor;
float nameYOffset;
float wobbleOffset;
float wobbleSpeed;
float animationTimer;
float animationSpeed;
int buildingTypeIndex;
float sizeScale;
Random random;
Planet planet;
int planetIndex;
public Building(String type, float x, float y, float width, float height, Random random, Planet planet) {
this.type = type;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.random = random;
this.planet = planet;
this.planetIndex = planet.ordinal();
this.buildingTypeIndex = findBuildingTypeIndex(type, planet);
this.sizeScale = SIZE_SCALE_FACTORS_BY_PLANET[planetIndex][buildingTypeIndex];
this.colorThemeIndex = random.nextInt(3);
this.colors = BUILDING_COLOR_THEMES_BY_PLANET[planetIndex][buildingTypeIndex];
this.roofColor = ROOF_COLORS_BY_PLANET[planetIndex][buildingTypeIndex][random.nextInt(2)];
Color[] planetDetailColors = DETAIL_COLORS_BY_PLANET[planetIndex];
this.detailColor = planetDetailColors[random.nextInt(planetDetailColors.length)];
Color[] planetNameColors = GLOWING_NAME_COLORS_BY_PLANET[planetIndex];
this.nameColor = planetNameColors[random.nextInt(planetNameColors.length)];
this.constructionProgress = 0;
this.isOverlapping = false;
this.showName = false;
this.namePulse = random.nextFloat() * 100;
this.nameYOffset = 0;
this.wobbleOffset = random.nextFloat() * 100;
this.wobbleSpeed = 0.3f + random.nextFloat() * 0.7f;
this.animationTimer = random.nextFloat() * 100;
this.animationSpeed = 0.5f + random.nextFloat() * 1.0f;
this.cloudOffsets = new float[3];
for (int i = 0; i < 3; i++) {
cloudOffsets[i] = random.nextFloat() * 100;
}
}
private int findBuildingTypeIndex(String type, Planet planet) {
String[] planetBuildings = BUILDING_TYPES_BY_PLANET[planet.ordinal()];
for (int i = 0; i < planetBuildings.length; i++) {
if (planetBuildings[i].equals(type)) {
return i;
}
}
return 0;
}
public void addBlock() {
if (constructionProgress < 3) constructionProgress++;
if (isComplete()) {
showName = true;
}
}
public void removeBlock() {
if (constructionProgress > 0) constructionProgress--;
if (!isComplete()) {
showName = false;
}
}
public boolean isComplete() { return constructionProgress >= 3; }
public float getCurrentHeight() { return (height * constructionProgress) / 3.0f; }
public Rectangle getBounds() { return new Rectangle(x, y, width, getCurrentHeight()); }
public Planet getPlanet() { return planet; }
public void update(float deltaTime) {
animationTimer += deltaTime * animationSpeed;
if (showName) {
namePulse += deltaTime * 2;
nameYOffset = (float)Math.sin(namePulse * 0.5f) * 3;
}
if (isComplete()) {
wobbleOffset += deltaTime * wobbleSpeed;
}
}
public float getWobbleX() {
if (!isComplete()) return 0;
return (float)Math.sin(wobbleOffset) * 2;
}
public float getWobbleY() {
if (!isComplete()) return 0;
return (float)Math.cos(wobbleOffset * 1.5f) * 1.5f;
}
public void createCitizensForBuilding(Array<Citizen> citizens, Random random) {
int citizenCount = 2 + random.nextInt(3);
for (int i = 0; i < citizenCount; i++) {
float citizenX = x + random.nextFloat() * width;
float citizenY = y - 40;
Color clothesColor = DETAIL_COLORS_BY_PLANET[planetIndex][random.nextInt(DETAIL_COLORS_BY_PLANET[planetIndex].length)];
Citizen citizen = new Citizen(citizenX, citizenY, clothesColor, this, random, planet);
citizens.add(citizen);
}
}
public float getSizeScale() {
return sizeScale;
}
public Color getDetailColor() {
return detailColor;
}
}

View File

@@ -0,0 +1,112 @@
package com.mygdx.game;
import com.badlogic.gdx.math.Rectangle;
public class BuildingPlacer {
public static void startNewBuildingAt(AbsurdCityBuilder1 game, float worldX, float worldY) {
Planet planet = game.getCurrentPlanet();
String[] planetBuildings = Building.BUILDING_TYPES_BY_PLANET[planet.ordinal()];
String selectedType = planetBuildings[game.getSelectedBuildingType()];
float width, height;
// Разные размеры для разных планет
switch (planet) {
case EARTH:
switch (game.getSelectedBuildingType()) {
case 0: width = 180; height = 200; break; // Уютный Домик
case 1: width = 160; height = 180; break; // Детская Больница
case 2: width = 190; height = 170; break; // Весёлая Школа
case 3: width = 200; height = 160; break; // Игровая Площадка
case 4: width = 140; height = 180; break; // Надёжный Банк
case 5: width = 130; height = 160; break; // Здоровая Аптека
case 6: width = 190; height = 200; break; // Волшебный Театр
case 7: width = 180; height = 170; break; // КиноМир
default: width = 180; height = 200; break;
}
break;
case MARS:
// Марсианские здания (компактнее)
switch (game.getSelectedBuildingType()) {
case 0: width = 150; height = 180; break; // Марсианская База
case 1: width = 140; height = 160; break; // Красная Лаборатория
case 2: width = 170; height = 150; break; // Космопорт
case 3: width = 160; height = 170; break; // Энергокупол
case 4: width = 130; height = 160; break; // Водородный Завод
case 5: width = 120; height = 150; break; // Обсерватория
case 6: width = 140; height = 140; break; // Робо-Фабрика
case 7: width = 150; height = 160; break; // Биокупол
default: width = 150; height = 160; break;
}
break;
case VENUS:
// Венерианские здания (выше)
switch (game.getSelectedBuildingType()) {
case 0: width = 130; height = 200; break; // Вулканический Дом
case 1: width = 160; height = 190; break; // Термальная Станция
case 2: width = 180; height = 210; break; // Золотой Дворец
case 3: width = 170; height = 180; break; // Облачный Город
case 4: width = 140; height = 170; break; // Кристальная Шахта
case 5: width = 120; height = 160; break; // Теплица
case 6: width = 150; height = 190; break; // Вихревой Генератор
case 7: width = 160; height = 210; break; // Сияющая Башня
default: width = 150; height = 190; break;
}
break;
default:
width = 180; height = 200; break;
}
float x = worldX;
float y = worldY;
if (x < 10) x = 10;
if (x + width > game.getWIDTH() - 10) x = game.getWIDTH() - width - 10;
if (y + height > game.getHEIGHT()) y = game.getHEIGHT() - height;
if (y < game.getUI_INPUT_HEIGHT() + 10) y = game.getUI_INPUT_HEIGHT() + 10;
Building tempBuilding = new Building(selectedType, x, y, width, height, game.getRandom(), planet);
tempBuilding.isOverlapping = checkForOverlaps(tempBuilding, game.getBuildings());
game.setCurrentBuilding(tempBuilding);
game.setCurrentProblem(MathProblem.generateProblem(game.getBuildings().size, game.getRandom()));
game.updateUI();
game.setMessageText(tempBuilding.isOverlapping ?
"🎨 Здание пересекается с существующими! Это добавляет уникальности! 🎨" :
"🌟 Отличное место для строительства! Введите ответ: 🌟");
game.setMessageColor(tempBuilding.isOverlapping ? com.badlogic.gdx.graphics.Color.ORANGE : com.badlogic.gdx.graphics.Color.GREEN);
game.setTyping(true);
game.getInputText().setLength(0);
}
public static void handleBuildingClick(AbsurdCityBuilder1 game, float worldX, float worldY) {
if (game.getCurrentBuilding() != null) {
Rectangle buildingBounds = game.getCurrentBuilding().getBounds();
if (buildingBounds.contains(worldX, worldY)) {
game.setMessageText("🎯 Кликните вне здания для нового строительства. Ctrl+Z или Delete для удаления. 🎯");
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
} else {
if (!game.isTyping()) {
startNewBuildingAt(game, worldX, worldY);
}
}
} else {
startNewBuildingAt(game, worldX, worldY);
}
}
private static boolean checkForOverlaps(Building building, com.badlogic.gdx.utils.Array<Building> buildings) {
for (Building existing : buildings) {
if (isOverlapping(building.x, building.width, existing.x, existing.width)) {
return true;
}
}
return false;
}
private static boolean isOverlapping(float x1, float width1, float x2, float width2) {
return x1 < x2 + width2 && x1 + width1 > x2;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,203 @@
package com.mygdx.game;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import java.util.Random;
public class Citizen {
float x, y;
float targetX;
float speed;
Color clothesColor;
float walkTimer;
Building homeBuilding;
float bobOffset;
float bobSpeed;
boolean isMoving;
float size;
float emotionTimer;
boolean isHappy;
Random random;
float headSize;
Planet planet;
public Citizen(float x, float y, Color clothesColor, Building homeBuilding, Random random, Planet planet) {
this.x = x;
this.y = y;
this.targetX = x + (random.nextFloat() - 0.5f) * 300;
this.speed = 40 + random.nextFloat() * 60;
this.clothesColor = clothesColor;
this.walkTimer = random.nextFloat() * 100;
this.homeBuilding = homeBuilding;
this.bobOffset = random.nextFloat() * 100;
this.bobSpeed = 1 + random.nextFloat() * 2;
this.isMoving = random.nextBoolean();
this.size = 0.9f + random.nextFloat() * 0.3f;
this.headSize = 12 * size;
this.emotionTimer = random.nextFloat() * 5;
this.isHappy = random.nextBoolean();
this.random = random;
this.planet = planet;
}
public void update(float deltaTime) {
walkTimer += deltaTime;
bobOffset += deltaTime * bobSpeed;
emotionTimer += deltaTime;
if (emotionTimer > 3) {
isHappy = !isHappy;
emotionTimer = 0;
}
if (isMoving) {
float direction = targetX > x ? 1 : -1;
x += direction * speed * deltaTime;
if (Math.abs(x - targetX) < 10) {
targetX = homeBuilding.x + (random.nextFloat() - 0.5f) * homeBuilding.width;
isMoving = random.nextBoolean();
}
}
if (random.nextFloat() < 0.005f) {
isMoving = !isMoving;
if (isMoving) {
targetX = homeBuilding.x + (random.nextFloat() - 0.5f) * homeBuilding.width;
}
}
}
public void draw(ShapeRenderer shapeRenderer, float time) {
float currentY = y + (float)Math.sin(bobOffset) * 5;
float scale = size;
// Разный цвет кожи для разных планет
Color skinColor;
switch (planet) {
case EARTH:
skinColor = new Color(1.0f, 0.92f, 0.82f, 1);
break;
case MARS:
skinColor = new Color(0.95f, 0.7f, 0.6f, 1); // Красноватый
break;
case VENUS:
skinColor = new Color(1.0f, 0.85f, 0.7f, 1); // Золотистый
break;
default:
skinColor = new Color(1.0f, 0.92f, 0.82f, 1);
}
// Голова
shapeRenderer.setColor(skinColor);
shapeRenderer.circle(x, currentY + 25 * scale, headSize);
// Разные прически для разных планет
shapeRenderer.setColor(getHairColor());
switch (planet) {
case EARTH:
shapeRenderer.rect(x - headSize * 0.7f, currentY + 25 * scale + headSize * 0.5f,
headSize * 1.4f, headSize * 0.5f);
break;
case MARS:
// Антенны вместо волос
shapeRenderer.setColor(Color.GRAY);
shapeRenderer.rectLine(x, currentY + 25 * scale + headSize,
x, currentY + 25 * scale + headSize + 15 * scale,
3 * scale);
shapeRenderer.circle(x, currentY + 25 * scale + headSize + 15 * scale, 5 * scale);
break;
case VENUS:
// Кристаллическая "прическа"
shapeRenderer.setColor(new Color(1.0f, 0.9f, 0.3f, 1));
for (int i = 0; i < 3; i++) {
float crystalX = x - headSize * 0.5f + i * headSize * 0.5f;
shapeRenderer.triangle(crystalX - 3 * scale, currentY + 25 * scale + headSize * 0.5f,
crystalX + 3 * scale, currentY + 25 * scale + headSize * 0.5f,
crystalX, currentY + 25 * scale + headSize * 0.5f + 10 * scale);
}
break;
}
// Тело
shapeRenderer.setColor(clothesColor);
shapeRenderer.rect(x - 10 * scale, currentY, 20 * scale, 25 * scale);
// Глаза
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.circle(x - headSize * 0.3f, currentY + 25 * scale + headSize * 0.2f, headSize * 0.25f);
shapeRenderer.circle(x + headSize * 0.3f, currentY + 25 * scale + headSize * 0.2f, headSize * 0.25f);
// Зрачки
shapeRenderer.setColor(getEyeColor());
shapeRenderer.circle(x - headSize * 0.3f, currentY + 25 * scale + headSize * 0.2f, headSize * 0.1f);
shapeRenderer.circle(x + headSize * 0.3f, currentY + 25 * scale + headSize * 0.2f, headSize * 0.1f);
// Блеск в глазах
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.circle(x - headSize * 0.35f, currentY + 25 * scale + headSize * 0.25f, headSize * 0.05f);
shapeRenderer.circle(x + headSize * 0.25f, currentY + 25 * scale + headSize * 0.25f, headSize * 0.05f);
// Рот
shapeRenderer.setColor(new Color(0.8f, 0.3f, 0.4f, 1));
if (isHappy) {
shapeRenderer.arc(x, currentY + 25 * scale, headSize * 0.4f, 180, 180, 20);
} else {
shapeRenderer.rectLine(x - headSize * 0.4f, currentY + 25 * scale,
x + headSize * 0.4f, currentY + 25 * scale,
headSize * 0.08f);
}
// Руки
shapeRenderer.setColor(skinColor);
float armOffset = isMoving ? (float)Math.sin(walkTimer * 10) * 10 * scale : 0;
shapeRenderer.rectLine(x - 10 * scale, currentY + 15 * scale,
x - 20 * scale, currentY + 5 * scale - armOffset,
headSize * 0.2f);
shapeRenderer.rectLine(x + 10 * scale, currentY + 15 * scale,
x + 20 * scale, currentY + 5 * scale + armOffset,
headSize * 0.2f);
// Ноги
shapeRenderer.setColor(new Color(0.3f, 0.2f, 0.1f, 1));
float legOffset = isMoving ? (float)Math.sin(walkTimer * 10 + 3.14f) * 8 * scale : 0;
shapeRenderer.rectLine(x - 5 * scale, currentY,
x - 10 * scale, currentY - 15 * scale + legOffset,
headSize * 0.25f);
shapeRenderer.rectLine(x + 5 * scale, currentY,
x + 10 * scale, currentY - 15 * scale - legOffset,
headSize * 0.25f);
// Обувь
shapeRenderer.setColor(Color.BLACK);
shapeRenderer.rect(x - 12 * scale, currentY - 18 * scale + legOffset,
headSize * 0.4f, headSize * 0.2f);
shapeRenderer.rect(x + 8 * scale, currentY - 18 * scale - legOffset,
headSize * 0.4f, headSize * 0.2f);
// Щёки
if (isHappy) {
shapeRenderer.setColor(new Color(1.0f, 0.7f, 0.7f, 0.5f));
shapeRenderer.circle(x - headSize * 0.5f, currentY + 25 * scale, headSize * 0.15f);
shapeRenderer.circle(x + headSize * 0.5f, currentY + 25 * scale, headSize * 0.15f);
}
}
private Color getHairColor() {
switch (planet) {
case EARTH: return new Color(0.2f, 0.15f, 0.1f, 1);
case MARS: return new Color(0.7f, 0.3f, 0.2f, 1);
case VENUS: return new Color(1.0f, 0.8f, 0.3f, 1);
default: return new Color(0.2f, 0.15f, 0.1f, 1);
}
}
private Color getEyeColor() {
switch (planet) {
case EARTH: return new Color(0.1f, 0.1f, 0.3f, 1);
case MARS: return new Color(0.3f, 0.1f, 0.1f, 1);
case VENUS: return new Color(0.3f, 0.2f, 0.1f, 1);
default: return new Color(0.1f, 0.1f, 0.3f, 1);
}
}
}

View File

@@ -0,0 +1,40 @@
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
public class GameAssets {
private static BitmapFont font;
public static void createFonts() {
try {
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("DejaVuSans.ttf"));
FreeTypeFontParameter parameter = new FreeTypeFontParameter();
parameter.size = 18;
parameter.characters = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?\"'()[]{}<>:;@#$%^&*+-=×–÷/_\\|~`✦✧★☆";
font = generator.generateFont(parameter);
generator.dispose();
} catch (Exception e) {
font = new BitmapFont();
font.getData().setScale(1.1f);
}
}
public static BitmapFont getFont() {
return font;
}
public static Texture createWhitePixel() {
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(Color.WHITE);
pixmap.fill();
Texture whitePixel = new Texture(pixmap);
pixmap.dispose();
return whitePixel;
}
}

View File

@@ -0,0 +1,9 @@
package com.mygdx.game;
public enum GameState {
MAIN_MENU, // Главное меню
PLAYING, // Игровой процесс
PLANET_SELECT, // Выбор планеты
HELP, // Помощь/инструкции
ABOUT // Об игре
}

View File

@@ -0,0 +1,152 @@
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
public class InputHandler {
public static void handleInput(AbsurdCityBuilder1 game) {
// Проверяем, что мы в игровом режиме
if (game.getGameState() != GameState.PLAYING) {
return;
}
// Смена типа здания
if (Gdx.input.isKeyJustPressed(Input.Keys.LEFT)) {
if (!game.isTyping() && !game.isSwitchingPlanets()) {
int buildingCount = Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()].length;
int newType = (game.getSelectedBuildingType() - 1 + buildingCount) % buildingCount;
game.setSelectedBuildingType(newType);
game.updateUI();
game.setMessageText("Выбран: " +
Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()][newType]);
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.RIGHT)) {
if (!game.isTyping() && !game.isSwitchingPlanets()) {
int buildingCount = Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()].length;
int newType = (game.getSelectedBuildingType() + 1) % buildingCount;
game.setSelectedBuildingType(newType);
game.updateUI();
game.setMessageText("Выбран: " +
Building.BUILDING_TYPES_BY_PLANET[game.getCurrentPlanet().ordinal()][newType]);
game.setMessageColor(com.badlogic.gdx.graphics.Color.CYAN);
}
}
// Смена планеты
if (!game.isTyping() && !game.isSwitchingPlanets()) {
if (Gdx.input.isKeyJustPressed(Input.Keys.UP)) {
Planet nextPlanet = game.getCurrentPlanet().next();
game.startPlanetSwitch(nextPlanet);
}
if (Gdx.input.isKeyJustPressed(Input.Keys.DOWN)) {
Planet prevPlanet = game.getCurrentPlanet().previous();
game.startPlanetSwitch(prevPlanet);
}
// Быстрые клавиши для планет
if (Gdx.input.isKeyJustPressed(Input.Keys.NUM_1)) {
game.startPlanetSwitch(Planet.EARTH);
}
if (Gdx.input.isKeyJustPressed(Input.Keys.NUM_2)) {
game.startPlanetSwitch(Planet.MARS);
}
if (Gdx.input.isKeyJustPressed(Input.Keys.NUM_3)) {
game.startPlanetSwitch(Planet.VENUS);
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.FORWARD_DEL) ||
Gdx.input.isKeyJustPressed(Input.Keys.DEL) ||
(Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) && Gdx.input.isKeyJustPressed(Input.Keys.Z)) ||
(Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT) && Gdx.input.isKeyJustPressed(Input.Keys.Z))) {
if (!game.isTyping() && !game.isSwitchingPlanets()) {
if (game.getCurrentBuilding() != null) {
game.setCurrentBuilding(null);
game.setCurrentProblem(null);
game.setTyping(false);
game.getInputText().setLength(0);
game.setMessageText("Строительство отменено. Выберите новое место.");
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.setMessageColor(com.badlogic.gdx.graphics.Color.ORANGE);
} else {
game.setMessageText("Нет зданий для удаления.");
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
}
}
}
if (Gdx.input.justTouched()) {
if (!game.isSwitchingPlanets()) {
float touchX = Gdx.input.getX();
float touchY = Gdx.input.getY();
float worldX = touchX * (game.getWIDTH() / (float)Gdx.graphics.getWidth());
float worldY = game.getHEIGHT() - touchY * (game.getHEIGHT() / (float)Gdx.graphics.getHeight());
if (worldY > game.getUI_INPUT_HEIGHT()) {
BuildingPlacer.handleBuildingClick(game, worldX, worldY);
}
}
}
if (game.isTyping() && game.getCurrentBuilding() != null && !game.isSwitchingPlanets()) {
for (int key = Input.Keys.NUM_0; key <= Input.Keys.NUM_9; key++) {
if (Gdx.input.isKeyJustPressed(key)) {
game.getInputText().append(Input.Keys.toString(key).charAt(Input.Keys.toString(key).length() - 1));
}
}
for (int key = Input.Keys.NUMPAD_0; key <= Input.Keys.NUMPAD_9; key++) {
if (Gdx.input.isKeyJustPressed(key)) {
char numChar = (char)('0' + (key - Input.Keys.NUMPAD_0));
game.getInputText().append(numChar);
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.MINUS) || Gdx.input.isKeyJustPressed(Input.Keys.NUMPAD_SUBTRACT)) {
if (game.getInputText().length() == 0) {
game.getInputText().append('-');
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.BACKSPACE)) {
if (!Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) &&
!Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)) {
if (game.isTyping() && game.getInputText().length() > 0) {
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.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
game.updateUI();
}
}
}
if (Gdx.input.isKeyJustPressed(Input.Keys.ENTER)) {
game.checkAnswer();
}
if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
if (game.isTyping()) {
game.setTyping(false);
game.getInputText().setLength(0);
game.setMessageText("Ввод отменен. Можно продолжить строительство.");
game.setMessageColor(com.badlogic.gdx.graphics.Color.YELLOW);
}
}
}
}
}

View File

@@ -0,0 +1,87 @@
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;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import java.util.Random;
public class JokeBubble {
String text;
float x, y;
float timer;
Color bubbleColor;
float floatOffset;
float scale;
Random random;
public JokeBubble(String text, float x, float y, Random random) {
this.text = text;
this.x = x;
this.y = y;
this.timer = 0;
this.random = random;
this.bubbleColor = new Color(
random.nextFloat() * 0.3f + 0.7f,
random.nextFloat() * 0.3f + 0.7f,
random.nextFloat() * 0.3f + 0.7f,
0.9f
);
this.floatOffset = random.nextFloat() * 100;
this.scale = 0.9f + random.nextFloat() * 0.2f;
}
public void update(float deltaTime) {
timer += deltaTime;
floatOffset += deltaTime * 2;
}
public boolean isExpired() {
return timer > 3.0f;
}
public void draw(SpriteBatch batch, ShapeRenderer shapeRenderer, BitmapFont font,
GlyphLayout glyphLayout, Texture whitePixel) {
batch.begin();
float currentY = y + (float)Math.sin(floatOffset) * 8;
// Пузырь
font.getData().setScale(0.8f * scale);
glyphLayout.setText(font, text);
float bubbleWidth = glyphLayout.width + 25;
float bubbleHeight = glyphLayout.height + 20;
// Рисуем пузырь с закругленными краями
batch.setColor(bubbleColor);
// Основная часть пузыря
batch.draw(whitePixel, x - bubbleWidth/2, currentY, bubbleWidth, bubbleHeight);
// Закругленные углы (эмулируем кругами)
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(bubbleColor);
shapeRenderer.circle(x - bubbleWidth/2, currentY + bubbleHeight/2, bubbleHeight/2);
shapeRenderer.circle(x + bubbleWidth/2, currentY + bubbleHeight/2, bubbleHeight/2);
shapeRenderer.end();
// Текст
font.setColor(Color.BLACK);
font.draw(batch, text, x - glyphLayout.width/2, currentY + bubbleHeight/2 + glyphLayout.height/2);
// Хвостик пузыря
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(bubbleColor);
shapeRenderer.triangle(
x - 8, currentY,
x + 8, currentY,
x, currentY - 15
);
shapeRenderer.end();
font.getData().setScale(1.0f);
batch.end();
}
}

View File

@@ -0,0 +1,59 @@
package com.mygdx.game;
import java.util.Random;
public class MathProblem {
String question;
int answer;
public MathProblem(String question, int answer) {
this.question = question;
this.answer = answer;
}
public static MathProblem generateProblem(int difficulty, Random random) {
int a, b, c;
String question;
int answer;
if (difficulty < 2) {
a = 1 + random.nextInt(20);
b = 1 + random.nextInt(20);
if (random.nextBoolean()) {
question = a + " + " + b + " = ?";
answer = a + b;
} else {
if (a < b) {
int temp = a;
a = b;
b = temp;
}
question = a + " - " + b + " = ?";
answer = a - b;
}
} else if (difficulty < 4) {
a = 2 + random.nextInt(9);
b = 2 + random.nextInt(9);
question = a + " × " + b + " = ?";
answer = a * b;
} else if (difficulty < 6) {
a = 1 + random.nextInt(10);
b = 1 + random.nextInt(10);
c = 2 + random.nextInt(8);
question = "(" + a + " + " + b + ") × " + c + " = ?";
answer = (a + b) * c;
} else {
b = 2 + random.nextInt(4);
c = 2 + random.nextInt(4);
int multiplication = b * c;
a = multiplication + random.nextInt(10) + 5;
question = a + " - " + b + " × " + c + " = ?";
answer = a - multiplication;
}
return new MathProblem(question, answer);
}
public String getQuestion() { return question; }
public int getAnswer() { return answer; }
}

View File

@@ -0,0 +1,87 @@
package com.mygdx.game;
import com.badlogic.gdx.graphics.Color;
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.Texture;
public class MenuButton {
private float x, y, width, height;
private String text;
private Color normalColor;
private Color hoverColor;
private Color textColor;
private boolean isHovered;
private Runnable action;
private String icon;
public MenuButton(float x, float y, float width, float height, String text,
Color normalColor, Color hoverColor, Runnable action) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.text = text;
this.normalColor = normalColor;
this.hoverColor = hoverColor;
this.textColor = Color.WHITE;
this.isHovered = false;
this.action = action;
this.icon = "";
}
public MenuButton withIcon(String icon) {
this.icon = icon;
return this;
}
public String getText() {
return text;
}
public MenuButton withTextColor(Color color) {
this.textColor = color;
return this;
}
public void update(float mouseX, float mouseY, boolean isClicked) {
isHovered = mouseX >= x && mouseX <= x + width &&
mouseY >= y && mouseY <= y + height;
if (isHovered && isClicked && action != null) {
action.run();
}
}
public void render(SpriteBatch batch, BitmapFont font, GlyphLayout layout, Texture whitePixel) {
// Рисуем кнопку
batch.setColor(isHovered ? hoverColor : normalColor);
batch.draw(whitePixel, x, y, width, height);
// Рамка
batch.setColor(new Color(1, 1, 1, 0.3f));
batch.draw(whitePixel, x, y, width, 2); // Верх
batch.draw(whitePixel, x, y + height - 2, width, 2); // Низ
batch.draw(whitePixel, x, y, 2, height); // Левая
batch.draw(whitePixel, x + width - 2, y, 2, height); // Правая
// Текст
font.setColor(textColor);
if (!icon.isEmpty()) {
font.draw(batch, icon + " " + text, x + 20, y + height/2 + 10);
} else {
layout.setText(font, text);
font.draw(batch, text, x + width/2 - layout.width/2, y + height/2 + 10);
}
// Эффект при наведении
if (isHovered) {
batch.setColor(new Color(1, 1, 1, 0.1f));
batch.draw(whitePixel, x, y, width, height);
}
}
public boolean contains(float px, float py) {
return px >= x && px <= x + width && py >= y && py <= y + height;
}
}

View File

@@ -0,0 +1,447 @@
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;
import java.util.ArrayList;
import java.util.List;
public class MenuRenderer {
private final SpriteBatch batch;
private BitmapFont titleFont;
private BitmapFont font;
private GlyphLayout layout;
private Texture whitePixel;
private int width, height;
private List<MenuButton> mainMenuButtons;
private List<MenuButton> planetSelectButtons;
private List<MenuButton> helpButtons;
private float titlePulse = 0;
private float starTimer = 0;
public MenuRenderer(SpriteBatch batch, BitmapFont font, GlyphLayout layout,
Texture whitePixel, int width, int height) {
this.batch = batch;
this.font = font;
this.layout = layout;
this.whitePixel = whitePixel;
this.width = width;
this.height = height;
// Создаем увеличенный шрифт для заголовка
this.titleFont = new BitmapFont();
this.titleFont.getData().setScale(2.5f);
createMainMenuButtons();
createPlanetSelectButtons();
createHelpButtons();
}
private void createMainMenuButtons() {
mainMenuButtons = new ArrayList<>();
float buttonWidth = 400;
float buttonHeight = 70;
float startY = height/2 - 50;
float spacing = 85;
// Кнопка "Новая игра"
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),
() -> {}
).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),
() -> {}
));
// Кнопка "Помощь"
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),
() -> {}
));
// Кнопка "Выход"
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),
() -> System.exit(0)
));
}
private void createPlanetSelectButtons() {
planetSelectButtons = new ArrayList<>();
float buttonWidth = 350;
float buttonHeight = 100;
float startY = height/2 + 50;
float spacing = 120;
// Земля
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),
() -> {}
).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),
() -> {}
));
// Венера
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),
() -> {}
));
// Кнопка "Назад"
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),
() -> {}
));
}
private void createHelpButtons() {
helpButtons = new ArrayList<>();
// Кнопка "Назад"
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),
() -> {}
));
}
public void update(float deltaTime) {
titlePulse += deltaTime * 2;
starTimer += deltaTime;
}
public void renderMainMenu(float mouseX, float mouseY) {
batch.begin();
// Космический фон
renderSpaceBackground();
// Заголовок
renderTitle();
// Подзаголовок
font.setColor(new Color(0.8f, 0.9f, 1.0f, 0.8f));
font.getData().setScale(1.2f);
String subtitle = "Строй абсурдные города на разных планетах!";
layout.setText(font, subtitle);
font.draw(batch, subtitle, width/2 - layout.width/2, height - 150);
font.getData().setScale(1.0f);
// Кнопки
for (MenuButton button : mainMenuButtons) {
button.render(batch, font, layout, whitePixel);
}
// Автор
font.setColor(new Color(1, 1, 1, 0.5f));
font.getData().setScale(0.8f);
font.draw(batch, "© 2024 Absurd City Builder", width - 250, 30);
font.getData().setScale(1.0f);
batch.end();
}
public void renderPlanetSelect(float mouseX, float mouseY) {
batch.begin();
// Космический фон
renderSpaceBackground();
// Заголовок
titleFont.setColor(new Color(1, 1, 1, 0.9f));
String title = "🪐 ВЫБОР ПЛАНЕТЫ";
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 = "Выберите планету для строительства:";
layout.setText(font, desc);
font.draw(batch, desc, width/2 - layout.width/2, height - 170);
font.getData().setScale(1.0f);
// Описания планет
font.setColor(Color.LIGHT_GRAY);
font.getData().setScale(0.9f);
// Земля
String earthText = "Мультяшные здания\ркие цвета\nМилые жители";
layout.setText(font, earthText);
font.draw(batch, earthText, width/2 - 380, height/2 - 50);
// Марс
String marsText = "Технологичные постройки\nКрасный пейзаж\nМарсианские роботы";
layout.setText(font, marsText);
font.draw(batch, marsText, width/2 + 30, height/2 - 50);
// Венера
String venusText = "Вулканические здания\nРаскаленная атмосфера\nКристаллические формы";
layout.setText(font, venusText);
font.draw(batch, venusText, width/2 - 175, height/2 - 200);
font.getData().setScale(1.0f);
// Кнопки
for (MenuButton button : planetSelectButtons) {
button.render(batch, font, layout, whitePixel);
}
batch.end();
}
public void renderHelp(float mouseX, float mouseY) {
batch.begin();
// Фон
batch.setColor(new Color(0.1f, 0.1f, 0.2f, 0.95f));
batch.draw(whitePixel, 0, 0, width, height);
batch.setColor(Color.WHITE);
// Заголовок
titleFont.setColor(Color.YELLOW);
String title = "❓ ПОМОЩЬ И УПРАВЛЕНИЕ";
layout.setText(titleFont, title);
titleFont.draw(batch, title, width/2 - layout.width/2, height - 100);
// Инструкции
font.setColor(Color.WHITE);
font.getData().setScale(1.1f);
float textY = height - 200;
float lineHeight = 35;
String[] instructions = {
"🎮 ОСНОВНОЕ УПРАВЛЕНИЕ:",
"• ЛКМ - кликнуть на поле для строительства",
"• ←/→ - выбрать тип здания",
"• Enter - отправить ответ на задачу",
"• Backspace - удалить блок/символ",
"• Delete/Ctrl+Z - удалить здание",
"• ESC - отмена ввода",
"",
"🪐 УПРАВЛЕНИЕ ПЛАНЕТАМИ:",
"• ↑/↓ - переключить планету",
"• 1 - Земля, 2 - Марс, 3 - Венера",
"",
"🎯 КАК ИГРАТЬ:",
"1. Выберите тип здания",
"2. Кликните на игровом поле",
"3. Решите математическую задачу",
"4. Постройте 3 блока для завершения",
"5. Стройте разные здания на разных планетах!"
};
for (String line : instructions) {
if (line.startsWith("🎮") || line.startsWith("🪐") || line.startsWith("🎯")) {
font.setColor(Color.CYAN);
} else if (line.startsWith("")) {
font.setColor(Color.LIGHT_GRAY);
} else {
font.setColor(Color.WHITE);
}
font.draw(batch, line, 100, textY);
textY -= lineHeight;
}
font.getData().setScale(1.0f);
// Кнопки
for (MenuButton button : helpButtons) {
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.draw(whitePixel, 0, 0, width, height);
// Звезды
batch.setColor(Color.WHITE);
for (int i = 0; i < 50; i++) {
float starX = (float)Math.sin(starTimer + i) * width + width/2;
float starY = (float)Math.cos(starTimer * 0.5f + i) * height/2 + height/2;
float size = 1 + (float)Math.sin(starTimer * 2 + i) * 2;
batch.draw(whitePixel, starX, starY, size, size);
}
batch.setColor(Color.WHITE);
// Заголовок
titleFont.setColor(new Color(0.8f, 0.4f, 1.0f, 1));
String title = "✨ ОБ ИГРЕ";
layout.setText(titleFont, title);
titleFont.draw(batch, title, width/2 - layout.width/2, height - 100);
// Описание игры
font.setColor(new Color(0.9f, 0.9f, 1.0f, 0.9f));
font.getData().setScale(1.2f);
String[] aboutText = {
"Absurd City Builder - это уникальная игра,",
"где вы строите безумные города на разных планетах!",
"",
"Особенности игры:",
"• 3 уникальные планеты с разными зданиями",
"• Забавные математические задачи",
"• Мультяшная графика и анимации",
"• Динамичные жители и шутки",
"• Бесконечные возможности для творчества!",
"",
"Разработано с ❤️ для любителей абсурда и математики.",
"",
"Версия 1.0"
};
float textY = height - 200;
for (String line : aboutText) {
layout.setText(font, line);
font.draw(batch, line, width/2 - layout.width/2, textY);
textY -= 40;
}
font.getData().setScale(1.0f);
// Кнопка "Назад"
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),
() -> {}
);
backButton.render(batch, font, layout, whitePixel);
batch.end();
}
private void renderSpaceBackground() {
// Темный космический фон
batch.setColor(new Color(0.05f, 0.05f, 0.1f, 1));
batch.draw(whitePixel, 0, 0, width, height);
// Звезды
batch.setColor(Color.WHITE);
for (int i = 0; i < 100; i++) {
float starX = (i * 37.3f) % width;
float starY = (i * 23.7f) % height;
float twinkle = 0.5f + 0.5f * (float)Math.sin(starTimer * 3 + i);
batch.setColor(new Color(1, 1, 1, twinkle));
float size = 1 + (i % 3);
batch.draw(whitePixel, starX, starY, size, size);
}
batch.setColor(Color.WHITE);
// Планеты на заднем фоне
batch.setColor(new Color(0.3f, 0.6f, 0.9f, 0.3f));
batch.draw(whitePixel, width - 200, 100, 150, 150);
batch.setColor(new Color(0.8f, 0.3f, 0.2f, 0.3f));
batch.draw(whitePixel, 100, height - 200, 120, 120);
batch.setColor(new Color(1.0f, 0.7f, 0.2f, 0.3f));
batch.draw(whitePixel, width - 150, height - 150, 100, 100);
}
private void renderTitle() {
// Пульсирующий заголовок
float pulse = 0.8f + 0.2f * (float)Math.sin(titlePulse);
titleFont.setColor(new Color(1, pulse, 0.5f, 1));
String title = "✨ ABSURD CITY BUILDER ✨";
layout.setText(titleFont, title);
titleFont.draw(batch, title, width/2 - layout.width/2, height - 100);
// Блестки вокруг заголовка
batch.setColor(new Color(1, 1, 0.5f, 0.3f));
for (int i = 0; i < 8; i++) {
float angle = titlePulse + i * 0.785f;
float sparkleX = width/2 + (float)Math.cos(angle) * 200;
float sparkleY = height - 100 + (float)Math.sin(angle) * 50;
float size = 5 + (float)Math.sin(titlePulse * 2 + i) * 3;
batch.draw(whitePixel, sparkleX, sparkleY, size, size);
}
}
public MenuButton getMainMenuButtonAt(float x, float y) {
for (MenuButton button : mainMenuButtons) {
if (button.contains(x, y)) {
return button;
}
}
return null;
}
public MenuButton getPlanetSelectButtonAt(float x, float y) {
for (MenuButton button : planetSelectButtons) {
if (button.contains(x, y)) {
return button;
}
}
return null;
}
public MenuButton getHelpButtonAt(float x, float y) {
for (MenuButton button : helpButtons) {
if (button.contains(x, y)) {
return button;
}
}
return null;
}
public void dispose() {
titleFont.dispose();
}
}

View File

@@ -0,0 +1,42 @@
package com.mygdx.game;
import com.badlogic.gdx.graphics.Color;
public enum Planet {
EARTH("Земля", 0.68f, 0.85f, 0.9f, 1.0f),
MARS("Марс", 0.8f, 0.4f, 0.3f, 0.9f),
VENUS("Венера", 1.0f, 0.7f, 0.4f, 1.0f);
private final String name;
private final float r, g, b, a;
Planet(String name, float r, float g, float b, float a) {
this.name = name;
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
public String getName() { return name; }
public float getR() { return r; }
public float getG() { return g; }
public float getB() { return b; }
public float getA() { return a; }
public Color getColor() {
return new Color(r, g, b, a);
}
public Planet next() {
Planet[] planets = values();
int nextIndex = (this.ordinal() + 1) % planets.length;
return planets[nextIndex];
}
public Planet previous() {
Planet[] planets = values();
int prevIndex = (this.ordinal() - 1 + planets.length) % planets.length;
return planets[prevIndex];
}
}

View File

@@ -0,0 +1,254 @@
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 UIRenderer {
private SpriteBatch batch;
private BitmapFont font;
private GlyphLayout glyphLayout;
private Texture whitePixel;
private int WIDTH;
private int HEIGHT;
private int UI_INPUT_HEIGHT;
public UIRenderer(SpriteBatch batch, BitmapFont font, GlyphLayout glyphLayout,
Texture whitePixel, int width, int height, int uiInputHeight) {
this.batch = batch;
this.font = font;
this.glyphLayout = glyphLayout;
this.whitePixel = whitePixel;
this.WIDTH = width;
this.HEIGHT = height;
this.UI_INPUT_HEIGHT = uiInputHeight;
}
public void renderUI(int selectedBuildingType, String problemText, String messageText, Color messageColor,
boolean isTyping, MathProblem currentProblem, String inputText,
boolean showWrongAnswerJoke, String wrongAnswerJoke, float time,
Building currentBuilding, Planet currentPlanet, boolean isSwitchingPlanets) {
batch.begin();
batch.setColor(0.2f, 0.3f, 0.4f, 0.95f);
batch.draw(whitePixel, 0, 0, WIDTH, UI_INPUT_HEIGHT);
batch.setColor(Color.WHITE);
batch.setColor(0.4f, 0.6f, 0.8f, 1);
batch.draw(whitePixel, 0, UI_INPUT_HEIGHT, WIDTH, 3);
batch.setColor(Color.WHITE);
font.setColor(Color.WHITE);
int lineHeight = 28;
int currentY = UI_INPUT_HEIGHT - 30;
// ==================== ЛЕВАЯ КОЛОНКА ====================
// Отображение текущей планеты
String planetDisplay = "🌍 Планета: " + currentPlanet.getName();
if (isSwitchingPlanets) {
planetDisplay += " (Перелет...)";
}
font.draw(batch, planetDisplay, 20, currentY);
currentY -= lineHeight;
// Управление планетой
font.setColor(Color.YELLOW);
font.draw(batch, "↑/↓ - сменить планету", 20, currentY);
currentY -= lineHeight;
font.setColor(Color.LIGHT_GRAY);
font.draw(batch, "1-Земля, 2-Марс, 3-Венера", 20, currentY);
currentY -= lineHeight;
font.setColor(Color.WHITE);
font.draw(batch, "───────────────", 20, currentY);
currentY -= lineHeight;
// Тип здания
String[] planetBuildings = Building.BUILDING_TYPES_BY_PLANET[currentPlanet.ordinal()];
font.draw(batch, "🏗️ Тип здания: " + planetBuildings[selectedBuildingType], 20, currentY);
currentY -= lineHeight;
// Управление зданиями
font.setColor(Color.CYAN);
font.draw(batch, "←/→ - выбрать тип здания", 20, currentY);
currentY -= lineHeight;
font.setColor(Color.WHITE);
font.draw(batch, "───────────────", 20, currentY);
currentY -= lineHeight;
// Отображение задачи
String displayText = problemText;
if (problemText.length() > 40) {
int splitIndex = problemText.lastIndexOf(" ", 40);
if (splitIndex > 0) {
String line1 = problemText.substring(0, splitIndex);
String line2 = problemText.substring(splitIndex + 1);
font.draw(batch, line1, 20, currentY);
currentY -= lineHeight;
font.draw(batch, line2, 20, currentY);
} else {
font.draw(batch, displayText, 20, currentY);
}
} else {
font.draw(batch, displayText, 20, currentY);
}
currentY -= lineHeight;
// Прогресс строительства
if (currentBuilding != null) {
font.draw(batch, "📊 Прогресс: " + currentBuilding.constructionProgress + "/3 блоков",
20, currentY);
} else {
font.draw(batch, "📊 Прогресс: 0/3 блоков", 20, currentY);
}
currentY -= lineHeight;
// ==================== ПРАВАЯ КОЛОНКА ====================
// Сообщения игры
font.setColor(messageColor);
float messageX = WIDTH - 500;
drawWrappedText(messageText, messageX, UI_INPUT_HEIGHT - 40, 480);
// ==================== ЦЕНТРАЛЬНАЯ ЧАСТЬ ====================
if (isTyping && currentProblem != null) {
renderInputSection(currentProblem, inputText, time);
}
// Шутка при неправильном ответе
if (showWrongAnswerJoke) {
renderWrongAnswerJoke(wrongAnswerJoke);
}
// ==================== НИЖНЯЯ ПАНЕЛЬ ====================
renderBottomPanel(currentPlanet, isSwitchingPlanets);
batch.end();
}
private void renderInputSection(MathProblem currentProblem, String inputText, float time) {
// Фон для ввода
batch.setColor(0.3f, 0.4f, 0.5f, 0.8f);
batch.draw(whitePixel, WIDTH/2 - 250, UI_INPUT_HEIGHT - 150, 500, 130);
batch.setColor(Color.WHITE);
// Задача
font.setColor(Color.YELLOW);
String mathProblem = "🧮 Задача: " + currentProblem.getQuestion();
glyphLayout.setText(font, mathProblem);
font.draw(batch, mathProblem,
WIDTH/2 - glyphLayout.width/2,
UI_INPUT_HEIGHT - 60);
// Поле ввода
font.setColor(Color.WHITE);
font.draw(batch, "✏️ Введите ответ:", WIDTH/2 - 230, UI_INPUT_HEIGHT - 95);
// Введенный текст
String inputStr = inputText.isEmpty() ? "_" : inputText;
font.draw(batch, inputStr, WIDTH/2 - 230, UI_INPUT_HEIGHT - 130);
// Мигающий курсор
if ((int)(time * 2) % 2 == 0 && inputText.isEmpty()) {
font.setColor(Color.YELLOW);
font.draw(batch, "_", WIDTH/2 - 230, UI_INPUT_HEIGHT - 130);
font.setColor(Color.WHITE);
}
// Подсказки
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.getData().setScale(1.0f);
}
private void renderWrongAnswerJoke(String wrongAnswerJoke) {
// Фон для шутки
batch.setColor(1, 0.2f, 0.2f, 0.3f);
batch.draw(whitePixel, WIDTH/2 - 300, HEIGHT/2 - 50, 600, 100);
batch.setColor(Color.WHITE);
// Шутка
font.setColor(Color.RED);
font.getData().setScale(1.3f);
glyphLayout.setText(font, wrongAnswerJoke);
font.draw(batch, wrongAnswerJoke,
WIDTH/2 - glyphLayout.width/2,
HEIGHT/2 + 10);
font.getData().setScale(1.0f);
}
// ВОТ ТОТ САМЫЙ МЕТОД, КОТОРЫЙ ВЫ СПРАШИВАЛИ:
private void renderBottomPanel(Planet planet, boolean isSwitchingPlanets) {
font.setColor(Color.LIGHT_GRAY);
font.getData().setScale(0.6f);
// Основные инструкции
String instruction = "🖱️ Кликните на поле для строительства";
glyphLayout.setText(font, instruction);
font.draw(batch, instruction, WIDTH/2 - glyphLayout.width/2, 30);
// Управление
String controls = "🗑️ Delete/Ctrl+Z - удалить здание | ⌫ Backspace - удалить блок | ⎋ ESC - меню";
glyphLayout.setText(font, controls);
font.draw(batch, controls, WIDTH/2 - glyphLayout.width/2, 15);
// Индикатор планеты
font.setColor(getPlanetColor(planet));
font.getData().setScale(0.8f);
String planetInfo = getPlanetEmoji(planet) + " " + planet.getName();
if (isSwitchingPlanets) {
planetInfo += " 🚀";
}
font.draw(batch, planetInfo, WIDTH - 150, 25);
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();
float currentY = y;
for (String word : words) {
String testLine = line.length() > 0 ? line.toString() + " " + word : word;
glyphLayout.setText(font, testLine);
if (glyphLayout.width > maxWidth && line.length() > 0) {
font.draw(batch, line.toString(), x, currentY);
line = new StringBuilder(word);
currentY -= 25;
} else {
line = new StringBuilder(testLine);
}
}
if (line.length() > 0) {
font.draw(batch, line.toString(), x, currentY);
}
}
}

View File

@@ -0,0 +1,33 @@
package com.mygdx.game;
public class UIUpdater {
public static void updateUI(AbsurdCityBuilder1 game) {
if (game.getGameState() != GameState.PLAYING) {
return;
}
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 colorInfo = "";
if (game.getCurrentBuilding().isComplete()) {
colorInfo = String.format(" [Цвет: Тема %d]", game.getCurrentBuilding().colorThemeIndex + 1);
}
String fullText = "Строим " + game.getCurrentBuilding().type +
" (" + game.getCurrentBuilding().constructionProgress + "/3)" + colorInfo +
": " + game.getCurrentProblem().getQuestion() + overlapText;
game.setProblemText(fullText);
} else {
String planetText = game.isSwitchingPlanets() ?
"Перелет на " + game.getTargetPlanet().getName() + "..." :
"Планета: " + planet.getName();
game.setProblemText(planetText +
" | Тип здания: " + planetBuildings[game.getSelectedBuildingType()] +
" (←/→ для выбора, кликните на поле для строительства)" +
" | ESC - меню");
}
}
}