From e9f60180383e0e4d1dc96172a6f2e298517a14fb Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 21 Mar 2019 12:35:14 +0800 Subject: [PATCH] Add a language selection state for first runs --- src/game.cpp | 344 +++++++++++++++------------ src/game.hpp | 32 ++- src/menu.cpp | 19 +- src/states/language-select-state.cpp | 88 +++++++ src/states/loading-state.cpp | 27 +++ src/states/play-state.cpp | 42 ++++ src/states/splash-state.cpp | 53 +++++ src/states/title-state.cpp | 84 +++++++ 8 files changed, 527 insertions(+), 162 deletions(-) create mode 100644 src/states/language-select-state.cpp create mode 100644 src/states/loading-state.cpp create mode 100644 src/states/play-state.cpp create mode 100644 src/states/splash-state.cpp create mode 100644 src/states/title-state.cpp diff --git a/src/game.cpp b/src/game.cpp index 95ff21e..9d658ad 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -226,14 +226,19 @@ void Game::changeState(GameState* state) } } -std::string Game::getString(const std::string& name) const +std::string Game::getString(const std::string& name, std::optional languageIndex) const { std::string value; + if (languageIndex == std::nullopt) + { + languageIndex = currentLanguageIndex; + } + auto it = stringTableIndex.find(name); if (it != stringTableIndex.end()) { - value = (*stringTable)[it->second][languageIndex + 2]; + value = (*stringTable)[it->second][(*languageIndex) + 2]; if (value.empty()) { value = std::string("# EMPTY STRING: ") + name + std::string(" #"); @@ -257,7 +262,7 @@ void Game::changeLanguage(std::size_t nextLanguageIndex) resourceManager->unload(menuFontFilename); // Change current language index - languageIndex = nextLanguageIndex; + currentLanguageIndex = nextLanguageIndex; // Reload fonts loadFonts(); @@ -284,7 +289,7 @@ void Game::changeLanguage(std::size_t nextLanguageIndex) void Game::nextLanguage() { - changeLanguage((getLanguageIndex() + 1) % getLanguageCount()); + changeLanguage((currentLanguageIndex + 1) % languageCount); } void Game::openMenu(Menu* menu, int selectedItemIndex) @@ -366,7 +371,7 @@ void Game::selectMenuItem(int index, bool tween) // Determine target position of menu item selector Vector2 itemTranslation = currentMenuItem->getContainer()->getTranslation(); Vector2 itemDimensions = currentMenuItem->getContainer()->getDimensions(); - float spacing = currentMenuItem->getNameLabel()->getFont()->getWidth("A"); + float spacing = fontSizePX; Vector2 translation; translation.x = itemTranslation.x - menuSelectorImage->getDimensions().x - spacing; translation.y = itemTranslation.y + itemDimensions.y * 0.5f - menuSelectorImage->getDimensions().y * 0.5; @@ -483,10 +488,16 @@ void Game::setUpdateRate(double frequency) stepScheduler.setStepFrequency(frequency); } +void Game::disableNonSystemControls() +{ + controls.setCallbacksEnabled(false); + systemControls.setCallbacksEnabled(true); +} + void Game::setup() { - loadSettings(); setupDebugging(); + loadSettings(); setupLocalization(); setupWindow(); setupGraphics(); @@ -612,6 +623,11 @@ void Game::setup() } // Setup state machine states + languageSelectState = + { + std::bind(&Game::enterLanguageSelectState, this), + std::bind(&Game::exitLanguageSelectState, this) + }; splashState = { std::bind(&Game::enterSplashState, this), @@ -634,11 +650,18 @@ void Game::setup() }; // Initialize state machine - #if defined(DEBUG) - StateMachine::changeState(&titleState); - #else - StateMachine::changeState(&splashState); - #endif + if (firstRun) + { + StateMachine::changeState(&languageSelectState); + } + else + { + #if defined(DEBUG) + StateMachine::changeState(&titleState); + #else + StateMachine::changeState(&splashState); + #endif + } changeState(sandboxState); } @@ -713,7 +736,6 @@ void Game::handleEvent(const WindowResizedEvent& event) defaultRenderTarget.height = event.height; glViewport(0, 0, event.width, event.height); - camera.setPerspective(glm::radians(40.0f), static_cast(w) / static_cast(h), 0.1, 100.0f); @@ -871,13 +893,13 @@ void Game::setupLocalization() languageCount = (*stringTable)[0].size() - 2; // Match language code with language index - languageIndex = 0; + currentLanguageIndex = 0; StringTableRow* languageCodes = &(*stringTable)[1]; for (std::size_t i = 2; i < languageCodes->size(); ++i) { if (language == (*languageCodes)[i]) { - languageIndex = i - 2; + currentLanguageIndex = i - 2; break; } } @@ -918,9 +940,7 @@ void Game::setupWindow() // Set v-sync mode window->setVSync(vsync); - debugTypeface = nullptr; debugFont = nullptr; - menuTypeface = nullptr; menuFont = nullptr; } @@ -1434,8 +1454,17 @@ void Game::setupUI() blackoutImage->setVisible(false); uiRootElement->addChild(blackoutImage); - menuItemActiveColor = Vector4(Vector3(0.2f), 1.0f); - menuItemInactiveColor = Vector4(Vector3(0.2f), 0.5f); + languageSelectBGImage = new UIImage(); + languageSelectBGImage->setLayerOffset(-1); + languageSelectBGImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + languageSelectBGImage->setVisible(true); + + standardMenuActiveColor = Vector4(Vector3(0.2f), 1.0f); + standardMenuInactiveColor = Vector4(Vector3(0.2f), 0.5f); + languageMenuActiveColor = Vector4(Vector3(1.0f), 1.0f); + languageMenuInactiveColor = Vector4(Vector3(1.0f), 0.5f); + menuItemActiveColor = standardMenuActiveColor; + menuItemInactiveColor = standardMenuInactiveColor; menuItemIndex = -1; currentMenu = nullptr; @@ -1489,6 +1518,28 @@ void Game::setupUI() pauseMenuMainMenuItem = pauseMenu->addItem(); pauseMenuQuitItem = pauseMenu->addItem(); + // Build language menu + languageMenu = new Menu(); + for (std::size_t i = 0; i < languageCount; ++i) + { + MenuItem* item = languageMenu->addItem(); + item->setActivatedCallback + ( + [this, i]() + { + changeLanguage(i); + languageSelected(); + } + ); + + item->getContainer()->setTintColor(languageMenuInactiveColor); + item->getContainer()->setMouseOverCallback(std::bind(&Game::selectMenuItem, this, i, true)); + item->getContainer()->setMouseMovedCallback(std::bind(&Game::selectMenuItem, this, i, true)); + item->getContainer()->setMousePressedCallback(std::bind(&Game::activateMenuItem, this)); + + languageMenuItems.push_back(item); + } + // Setup main menu callbacks mainMenuContinueItem->setActivatedCallback(std::bind(&Game::continueGame, this)); mainMenuNewGameItem->setActivatedCallback(std::bind(&Game::newGame, this)); @@ -1644,7 +1695,7 @@ void Game::setupUI() ( [this](std::size_t id, float opacity) { - mainMenu->getContainer()->setTintColor(Vector4(opacity)); + currentMenu->getContainer()->setTintColor(Vector4(opacity)); } ); @@ -1906,7 +1957,7 @@ void Game::setupControls() } else { - loadControlProfile("default-controls"); + loadControlProfile("default-keyboard-controls"); saveControlProfile(controlProfileName); } @@ -1966,6 +2017,7 @@ void Game::loadSettings() { // Reset settings to default values resetSettings(); + firstRun = false; // Load settings table try @@ -1974,7 +2026,17 @@ void Game::loadSettings() } catch (const std::exception& e) { - settingsTable = new StringTable(); + logger->warning("No user settings found. First run assumed."); + firstRun = true; + + try + { + settingsTable = resourceManager->load("default-settings.csv"); + } + catch (const std::exception& e) + { + logger->error("Failed to load default settings."); + } } // Build settings table index @@ -2005,6 +2067,57 @@ void Game::loadStrings() void Game::loadFonts() { + // If the language selection fonts haven't been loaded + if (languageSelectionFonts.empty()) + { + // Load one font for each available language + for (std::size_t i = 0; i < languageCount; ++i) + { + // Get language name and font filename for that language + std::string languageName = getString("language-name", i); + std::string fontFilename = getString("menu-font-filename", i); + + // Check if language has a name + if (languageName.empty()) + { + logger->error("Language #" + std::to_string(i) + " has no name string."); + languageSelectionFonts.push_back(nullptr); + continue; + } + + // Check if language has a font filename + if (fontFilename.empty()) + { + logger->error("No font for language #" + std::to_string(i) + "."); + languageSelectionFonts.push_back(nullptr); + continue; + } + + // Load typeface for the font + Typeface* typeface = resourceManager->load(fontFilename); + + // Create a font at default font size + Font* font = typeface->createFont(fontSizePX); + + // Build a character set containing only the characters in the language name + std::set characterSet; + std::u32string languageNameUTF32 = toUTF32(languageName); + for (char32_t charcode: languageNameUTF32) + { + characterSet.emplace(charcode); + } + + // Load glyphs for all characters in the character set + typeface->loadCharset(font, characterSet); + + // Unload the typeface + resourceManager->unload(fontFilename); + + // Add the font to the language selection fonts + languageSelectionFonts.push_back(font); + } + } + // Get filenames of fonts std::string menuFontFilename = getString("menu-font-filename"); std::string debugFontFilename = "inconsolata-bold.ttf"; @@ -2012,21 +2125,24 @@ void Game::loadFonts() // Load debugging font if (!debugFont) { - debugTypeface = resourceManager->load(debugFontFilename); + // Load debug font typeface + Typeface* debugTypeface = resourceManager->load(debugFontFilename); + + // Create debug font debugFont = debugTypeface->createFont(fontSizePX); + + // Load basic latin characyer set debugTypeface->loadCharset(debugFont, UnicodeRange::BASIC_LATIN); - } - // Load menu typeface - menuTypeface = resourceManager->load(menuFontFilename); - menuFont = menuTypeface->createFont(fontSizePX * 1.5f); - menuTypeface->loadCharset(menuFont, UnicodeRange::BASIC_LATIN); + // Unload debug font typeface + resourceManager->unload(debugFontFilename); + } // Load menu font typeface - menuTypeface = resourceManager->load(menuFontFilename); + Typeface* menuTypeface = resourceManager->load(menuFontFilename); // Create menu font - menuFont = menuTypeface->createFont(fontSizePX * 1.5f); + menuFont = menuTypeface->createFont(fontSizePX); // Load basic latin character set menuTypeface->loadCharset(menuFont, UnicodeRange::BASIC_LATIN); @@ -2036,7 +2152,7 @@ void Game::loadFonts() for (const StringTableRow& row: *stringTable) { // Convert to UTF-8 string to UTF-32 - std::u32string string = toUTF32(row[languageIndex + 2]); + std::u32string string = toUTF32(row[currentLanguageIndex + 2]); // Add each character in the string to the charater set for (char32_t charcode: string) @@ -2047,6 +2163,9 @@ void Game::loadFonts() // Load custom character set menuTypeface->loadCharset(menuFont, characterSet); + + // Unload menu typeface + resourceManager->unload(menuFontFilename); } void Game::loadControlProfile(const std::string& profileName) @@ -2544,7 +2663,7 @@ void Game::remapControl(Control* control) void Game::resetControls() { inputRouter->reset(); - loadControlProfile("default-controls"); + loadControlProfile("default-keyboard-controls"); saveControlProfile(controlProfileName); restringUI(); } @@ -2575,6 +2694,10 @@ void Game::resizeUI(int w, int h) blackoutImage->setDimensions(Vector2(w, h)); blackoutImage->setAnchor(Anchor::CENTER); + // Resize language select background image + languageSelectBGImage->setDimensions(Vector2(w, h)); + languageSelectBGImage->setAnchor(Anchor::CENTER); + // Resize HUD float hudPadding = 20.0f; hudContainer->setDimensions(Vector2(w - hudPadding * 2.0f, h - hudPadding * 2.0f)); @@ -2847,6 +2970,26 @@ void Game::resizeUI(int w, int h) pauseMenu->resize(pauseMenuWidth, pauseMenuHeight); pauseMenu->getContainer()->setTranslation(Vector2(-pauseMenuPadding)); + // Language menu size + float languageMenuWidth = 0.0f; + float languageMenuHeight = 0.0f; + float languageMenuSpacing = 0.75f * fontSizePX; + + for (const MenuItem* item: *languageMenu->getItems()) + { + Font* font = item->getNameLabel()->getFont(); + if (font) + { + float lineHeight = font->getMetrics().getAscender() - font->getMetrics().getDescender(); + languageMenuHeight += lineHeight + languageMenuSpacing; + languageMenuWidth = std::max(languageMenuWidth, item->getNameLabel()->getDimensions().x); + } + + item->getNameLabel()->setAnchor(Vector2(0.5f, 0.0f)); + } + languageMenuHeight -= languageMenuSpacing; + languageMenu->getContainer()->setAnchor(Anchor::CENTER); + languageMenu->resize(languageMenuWidth, languageMenuHeight); } void Game::restringUI() @@ -2900,12 +3043,19 @@ void Game::restringUI() pauseMenuMainMenuItem->setName(getString("main-menu")); pauseMenuQuitItem->setName(getString("quit")); + // Language menu strings + for (std::size_t i = 0; i < languageCount; ++i) + { + languageMenuItems[i]->setName(getString("language-name", i)); + } + // Reset menu tweens uiRootElement->update(); mainMenu->getContainer()->resetTweens(); settingsMenu->getContainer()->resetTweens(); controlsMenu->getContainer()->resetTweens(); pauseMenu->getContainer()->resetTweens(); + languageMenu->getContainer()->resetTweens(); } void Game::restringControlMenuItem(MenuItem* item, const std::string& name) @@ -3073,117 +3223,16 @@ void Game::inputMapped(const InputMapping& mapping) saveControlProfile(controlProfileName); } -void Game::enterSplashState() -{ - // Show splash screen - splashBackgroundImage->setVisible(true); - splashImage->setVisible(true); - splashImage->setTintColor({1, 1, 1, 0}); - splashBackgroundImage->setTintColor({0, 0, 0, 1}); - splashImage->resetTweens(); - splashBackgroundImage->resetTweens(); - uiRootElement->update(); - - // Add splash animations to animator - animator.addAnimation(&splashFadeInAnimation); - animator.addAnimation(&splashFadeOutAnimation); - - // Play splash fade-in animation - splashFadeInAnimation.rewind(); - splashFadeInAnimation.play(); -} - -void Game::exitSplashState() -{ - // Hide splash screen - splashImage->setVisible(false); - splashBackgroundImage->setVisible(false); - uiRootElement->update(); - - // Remove splash animations from animator - animator.removeAnimation(&splashFadeInAnimation); - animator.removeAnimation(&splashFadeOutAnimation); -} - -void Game::enterLoadingState() -{} - -void Game::exitLoadingState() -{} - -void Game::enterTitleState() +void Game::languageSelected() { - // Setup scene - Vector3 antHillTranslation = {0, 0, 0}; - EntityID antHill = createInstanceOf("ant-hill"); - setTranslation(antHill, antHillTranslation); - - // Setup camera - cameraRig = orbitCam; - orbitCam->setTargetFocalPoint(antHillTranslation); - orbitCam->setTargetFocalDistance(0.0f); - orbitCam->setTargetElevation(glm::radians(80.0f)); - orbitCam->setTargetAzimuth(0.0f); - orbitCam->setFocalPoint(orbitCam->getTargetFocalPoint()); - orbitCam->setFocalDistance(orbitCam->getTargetFocalDistance()); - orbitCam->setElevation(orbitCam->getTargetElevation()); - orbitCam->setAzimuth(orbitCam->getTargetAzimuth()); - - float fov = glm::radians(30.0f); - orbitCam->getCamera()->setPerspective(fov, (float)w / (float)h, 1.0f, 1000.0f); - - // Begin fade-in - fadeIn(6.0f, {0, 0, 0}, nullptr); - - // - animator.addAnimation(&antHillZoomAnimation); - antHillZoomAnimation.rewind(); - antHillZoomAnimation.play(); - - menuFadeAnimation.rewind(); - menuFadeAnimation.play(); - menuFadeAnimation.setEndCallback(nullptr); - - // Disable play controls - cameraControls.setCallbacksEnabled(false); - - // Enable menu controls - menuControls.setCallbacksEnabled(true); - - // Change setting menu's back item to return to the main menu - settingsMenuBackItem->setActivatedCallback(std::bind(&Game::openMenu, this, mainMenu, 3)); - - #if defined(DEBUG) - // Add important entity IDs to CLI variables - cli->set("anthill", std::to_string(antHill)); - #endif - - // Open the main menu and select the first menu item - openMenu(mainMenu, 0); -} - -void Game::exitTitleState() -{ - animator.removeAnimation(&antHillZoomAnimation); -} - -void Game::enterPlayState() -{ - // Disable menu controls - menuControls.setCallbacksEnabled(false); + // Disable non-system controls + disableNonSystemControls(); // Disable UI callbacks uiRootElement->setCallbacksEnabled(false); - // Enable play controls - cameraControls.setCallbacksEnabled(true); - - // Change setting menu's back item to return to the pause menu - settingsMenuBackItem->setActivatedCallback(std::bind(&Game::openMenu, this, pauseMenu, 1)); -} - -void Game::exitPlayState() -{ + // Begin to fade out + fadeOut(0.5f, Vector3(0.0f), std::bind(&StateMachine::changeState, this, &titleState)); } void Game::skipSplash() @@ -3218,9 +3267,10 @@ void Game::togglePause() void Game::continueGame() { - // Disable play controls, menu controls, and UI callbacks - cameraControls.setCallbacksEnabled(false); - menuControls.setCallbacksEnabled(false); + // Disable non-system controls + disableNonSystemControls(); + + // Disable UI callbacks uiRootElement->setCallbacksEnabled(false); // Start fading out main menu @@ -3242,9 +3292,10 @@ void Game::continueGame() void Game::newGame() { - // Disable play controls, menu controls, and UI callbacks - cameraControls.setCallbacksEnabled(false); - menuControls.setCallbacksEnabled(false); + // Disable non-system controls + disableNonSystemControls(); + + // Disable UI callbacks uiRootElement->setCallbacksEnabled(false); // Start fading out main menu @@ -3268,9 +3319,10 @@ void Game::newGame() void Game::returnToMainMenu() { - // Disable play controls, menu controls, and UI callbacks - cameraControls.setCallbacksEnabled(false); - menuControls.setCallbacksEnabled(false); + // Disable non-system controls + disableNonSystemControls(); + + // Disable UI callbacks uiRootElement->setCallbacksEnabled(false); // Close pause menu diff --git a/src/game.hpp b/src/game.hpp index 7988859..250a491 100644 --- a/src/game.hpp +++ b/src/game.hpp @@ -29,6 +29,7 @@ using namespace Emergent; #include "resources/string-table.hpp" #include #include +#include #include #include #include @@ -98,7 +99,7 @@ public: * @param name Name of the string. * @return String in the current language. */ - std::string getString(const std::string& name) const; + std::string getString(const std::string& name, std::optional languageIndex = std::nullopt) const; /** * Changes the current language. @@ -113,7 +114,7 @@ public: std::size_t getLanguageCount() const; /// Returns the index of the current language. - std::size_t getLanguageIndex() const; + std::size_t getCurrentLanguageIndex() const; void openMenu(Menu* menu, int selectedItemIndex); void closeCurrentMenu(); @@ -127,6 +128,8 @@ public: void toggleVSync(); void setUpdateRate(double frequency); + void disableNonSystemControls(); + /** * Changes the game state. * @@ -192,6 +195,8 @@ private: void screenshot(); // State functions + void enterLanguageSelectState(); + void exitLanguageSelectState(); void enterSplashState(); void exitSplashState(); void enterLoadingState(); @@ -201,6 +206,7 @@ private: void enterPlayState(); void exitPlayState(); + void languageSelected(); void skipSplash(); void togglePause(); @@ -235,6 +241,7 @@ public: public: // Game states + StateMachine::State languageSelectState; StateMachine::State splashState; StateMachine::State loadingState; StateMachine::State titleState; @@ -249,6 +256,7 @@ public: std::string controlsPath; // Settings + bool firstRun; StringTable* settingsTable; StringTableIndex settingsTableIndex; @@ -256,7 +264,7 @@ public: StringTable* stringTable; StringTableIndex stringTableIndex; std::size_t languageCount; - std::size_t languageIndex; + std::size_t currentLanguageIndex; // Window management Window* window; @@ -320,10 +328,9 @@ public: float timestep; // UI - Typeface* debugTypeface; Font* debugFont; - Typeface* menuTypeface; Font* menuFont; + std::vector languageSelectionFonts; BillboardBatch* uiBatch; UIBatcher* uiBatcher; UIContainer* uiRootElement; @@ -352,6 +359,7 @@ public: UIImage* radialMenuImage; UIImage* radialMenuSelectorImage; UIImage* blackoutImage; + UIImage* languageSelectBGImage; UIImage* cameraFlashImage; UIContainer* antTag; UIContainer* antLabelContainer; @@ -387,8 +395,6 @@ public: Vector4 cameraReticleColor; - - // Menu selection UIImage* menuSelectorImage; Menu* currentMenu; @@ -396,9 +402,14 @@ public: MenuItem* currentMenuItem; MenuItem* previousMenuItem; int menuItemIndex; + Vector4 standardMenuActiveColor; + Vector4 standardMenuInactiveColor; + Vector4 languageMenuActiveColor; + Vector4 languageMenuInactiveColor; Vector4 menuItemActiveColor; Vector4 menuItemInactiveColor; + // Main menu Menu* mainMenu; MenuItem* mainMenuContinueItem; @@ -437,6 +448,9 @@ public: MenuItem* pauseMenuMainMenuItem; MenuItem* pauseMenuQuitItem; + Menu* languageMenu; + std::vector languageMenuItems; + // Rendering Renderer renderer; RenderTarget defaultRenderTarget; @@ -578,9 +592,9 @@ inline std::size_t Game::getLanguageCount() const return languageCount; } -inline std::size_t Game::getLanguageIndex() const +inline std::size_t Game::getCurrentLanguageIndex() const { - return languageIndex; + return currentLanguageIndex; } #endif // GAME_HPP diff --git a/src/menu.cpp b/src/menu.cpp index 60c09dd..cc07913 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -113,14 +113,19 @@ void Menu::resize(int w, int h) { container->setDimensions(Vector2(w, h)); - int spacing = h / items.size(); - int offset = 0; - - for (MenuItem* item: items) + for (std::size_t i = 0; i < items.size(); ++i) { - item->container->setTranslation(Vector2(0, offset)); - item->container->setDimensions(Vector2(w, item->getNameLabel()->getFont()->getMetrics().getHeight())); - offset += spacing; + MenuItem* item = items[i]; + Font* font = item->getNameLabel()->getFont(); + + if (font) + { + float lineHeight = font->getMetrics().getAscender() - font->getMetrics().getDescender(); + + item->container->setTranslation(Vector2(0, 0)); + item->container->setAnchor(Vector2(0, static_cast(i) / static_cast(items.size() - 1))); + item->container->setDimensions(Vector2(w, lineHeight)); + } } } diff --git a/src/states/language-select-state.cpp b/src/states/language-select-state.cpp new file mode 100644 index 0000000..90e5432 --- /dev/null +++ b/src/states/language-select-state.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "game.hpp" +#include "debug/logger.hpp" +#include "ui/ui.hpp" +#include "resources/resource-manager.hpp" +#include "menu.hpp" + +void Game::enterLanguageSelectState() +{ + // Set fonts for language menu items + for (std::size_t i = 0; i < languageCount; ++i) + { + MenuItem* item = languageMenuItems[i]; + item->setFont(languageSelectionFonts[i]); + } + + // Re-string and resie UI + restringUI(); + resizeUI(w, h); + + // Set menu font color + menuItemActiveColor = languageMenuActiveColor; + menuItemInactiveColor = languageMenuInactiveColor; + menuSelectorImage->setTintColor(menuItemActiveColor); + + // Add background image + uiRootElement->addChild(languageSelectBGImage); + + // Hide menu item selector + menuSelectorImage->setVisible(false); + + // Open language menu + openMenu(languageMenu, 0); + + // Disable non-system controls + disableNonSystemControls(); + + // Disable UI callbacks + uiRootElement->setCallbacksEnabled(false); + + // Begin fade-in + fadeIn(0.5f, {0, 0, 0}, + std::bind + ( + [this]() + { + // Enable menu controls and UI callbacks + menuControls.setCallbacksEnabled(true); + uiRootElement->setCallbacksEnabled(true); + } + )); +} + +void Game::exitLanguageSelectState() +{ + // Remove background image + uiRootElement->removeChild(languageSelectBGImage); + + // Close language select menu + closeCurrentMenu(); + + // Show menu item selector + menuSelectorImage->setVisible(false); + + // Set standard menu item colors + menuItemActiveColor = standardMenuActiveColor; + menuItemInactiveColor = standardMenuInactiveColor; + menuSelectorImage->setTintColor(menuItemActiveColor); +} + diff --git a/src/states/loading-state.cpp b/src/states/loading-state.cpp new file mode 100644 index 0000000..495b311 --- /dev/null +++ b/src/states/loading-state.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "game.hpp" + +void Game::enterLoadingState() +{} + +void Game::exitLoadingState() +{} + diff --git a/src/states/play-state.cpp b/src/states/play-state.cpp new file mode 100644 index 0000000..ed169e3 --- /dev/null +++ b/src/states/play-state.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "game.hpp" +#include "ui/ui.hpp" +#include "menu.hpp" + +void Game::enterPlayState() +{ + // Disable non-system controls + disableNonSystemControls(); + + // Enable play controls + cameraControls.setCallbacksEnabled(true); + + // Disable UI callbacks + uiRootElement->setCallbacksEnabled(false); + + // Change setting menu's back item to return to the pause menu + settingsMenuBackItem->setActivatedCallback(std::bind(&Game::openMenu, this, pauseMenu, 1)); +} + +void Game::exitPlayState() +{ +} + diff --git a/src/states/splash-state.cpp b/src/states/splash-state.cpp new file mode 100644 index 0000000..45639fb --- /dev/null +++ b/src/states/splash-state.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "game.hpp" +#include "ui/ui.hpp" + +void Game::enterSplashState() +{ + // Show splash screen + splashBackgroundImage->setVisible(true); + splashImage->setVisible(true); + splashImage->setTintColor({1, 1, 1, 0}); + splashBackgroundImage->setTintColor({0, 0, 0, 1}); + splashImage->resetTweens(); + splashBackgroundImage->resetTweens(); + uiRootElement->update(); + + // Add splash animations to animator + animator.addAnimation(&splashFadeInAnimation); + animator.addAnimation(&splashFadeOutAnimation); + + // Play splash fade-in animation + splashFadeInAnimation.rewind(); + splashFadeInAnimation.play(); +} + +void Game::exitSplashState() +{ + // Hide splash screen + splashImage->setVisible(false); + splashBackgroundImage->setVisible(false); + uiRootElement->update(); + + // Remove splash animations from animator + animator.removeAnimation(&splashFadeInAnimation); + animator.removeAnimation(&splashFadeOutAnimation); +} diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp new file mode 100644 index 0000000..d9f2933 --- /dev/null +++ b/src/states/title-state.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2017-2019 Christopher J. Howard + * + * This file is part of Antkeeper Source Code. + * + * Antkeeper Source Code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper Source Code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper Source Code. If not, see . + */ + +#include "game.hpp" +#include "ui/ui.hpp" +#include "menu.hpp" +#include "debug/command-interpreter.hpp" +#include "game/camera-rig.hpp" + +void Game::enterTitleState() +{ + // Setup scene + Vector3 antHillTranslation = {0, 0, 0}; + EntityID antHill = createInstanceOf("ant-hill"); + setTranslation(antHill, antHillTranslation); + + // Setup camera + cameraRig = orbitCam; + orbitCam->setTargetFocalPoint(antHillTranslation); + orbitCam->setTargetFocalDistance(0.0f); + orbitCam->setTargetElevation(glm::radians(80.0f)); + orbitCam->setTargetAzimuth(0.0f); + orbitCam->setFocalPoint(orbitCam->getTargetFocalPoint()); + orbitCam->setFocalDistance(orbitCam->getTargetFocalDistance()); + orbitCam->setElevation(orbitCam->getTargetElevation()); + orbitCam->setAzimuth(orbitCam->getTargetAzimuth()); + + float fov = glm::radians(30.0f); + orbitCam->getCamera()->setPerspective(fov, (float)w / (float)h, 1.0f, 1000.0f); + + // Begin fade-in + fadeIn(6.0f, {0, 0, 0}, nullptr); + + // + animator.addAnimation(&antHillZoomAnimation); + antHillZoomAnimation.rewind(); + antHillZoomAnimation.play(); + + menuFadeAnimation.rewind(); + menuFadeAnimation.play(); + menuFadeAnimation.setEndCallback(nullptr); + + // Disable non-system controls + disableNonSystemControls(); + + // Enable menu controls + menuControls.setCallbacksEnabled(true); + + // Enable UI callbacks + uiRootElement->setCallbacksEnabled(true); + + // Change setting menu's back item to return to the main menu + settingsMenuBackItem->setActivatedCallback(std::bind(&Game::openMenu, this, mainMenu, 3)); + + #if defined(DEBUG) + // Add important entity IDs to CLI variables + cli->set("anthill", std::to_string(antHill)); + #endif + + // Open the main menu and select the first menu item + openMenu(mainMenu, 0); +} + +void Game::exitTitleState() +{ + animator.removeAnimation(&antHillZoomAnimation); +} +