From 88243f4c31f96a5a6db3a34033d6aa3ca0115870 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Fri, 7 Jul 2017 00:06:24 +0800 Subject: [PATCH] Add pause and play buttons --- data | 2 +- src/application.cpp | 86 ++++++++++++++++++++++++--- src/application.hpp | 10 ++++ src/render-passes.cpp | 3 +- src/render-passes.hpp | 8 ++- src/states/main-menu-state.cpp | 2 + src/states/play-state.cpp | 102 ++++++++++++++++++++++++++++++++- src/states/play-state.hpp | 4 ++ src/states/title-state.cpp | 16 ------ src/states/title-state.hpp | 6 -- 10 files changed, 203 insertions(+), 36 deletions(-) diff --git a/data b/data index bca60d7..c11a70b 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit bca60d7e0fe476dcf32de8ab4f17d08326ed37b9 +Subproject commit c11a70bf013de27252281cbbd80788ad3a1b5eaf diff --git a/src/application.cpp b/src/application.cpp index d796025..a86d322 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -26,6 +26,7 @@ #include "states/title-state.hpp" #include "states/main-menu-state.hpp" #include "states/play-state.hpp" +#include "game/colony.hpp" #include "debug.hpp" #include "camera-controller.hpp" #include @@ -349,6 +350,7 @@ int Application::execute() t = 0.0f; dt = 1.0f / 60.0f; float accumulator = 0.0f; + float maxFrameTime = 0.25f; int performanceSampleSize = 15; // Number of frames to sample int performanceSampleFrame = 0; // Current sample frame @@ -364,7 +366,7 @@ int Application::execute() frameTimer.reset(); // Add frame time (in seconds) to accumulator - accumulator += frameTime / 1000.0f; + accumulator += std::min(frameTime / 1000.0f, maxFrameTime); // If the user tried to close the application if (inputManager->wasClosed() || escape.isTriggered()) @@ -433,11 +435,15 @@ int Application::execute() performanceSampleFrame = 0; // Update frame time label - std::string frameTimeString; - std::stringstream stream; - stream << meanFrameTime; - stream >> frameTimeString; - frameTimeLabel->setText(frameTimeString); + if (frameTimeLabel->isVisible()) + { + std::string frameTimeString; + std::stringstream stream; + stream.precision(2); + stream << std::fixed << meanFrameTime; + stream >> frameTimeString; + frameTimeLabel->setText(frameTimeString); + } } // Update UI @@ -586,6 +592,9 @@ bool Application::loadModels() antHillModelInstance.setRotation(glm::angleAxis(glm::radians(90.0f), Vector3(1, 0, 0))); nestModelInstance.setModel(nestModel); + // Create terrain + terrain.create(255, 255, Vector3(50, 20, 50)); + return true; } @@ -623,9 +632,12 @@ bool Application::loadScene() lightingPass.setRenderTarget(&defaultRenderTarget); lightingPass.setShadowMap(0); lightingPass.setShadowCamera(&camera); - lightingPass.setModelLoader(modelLoader); defaultCompositor.addPass(&lightingPass); + // Setup debug pass + debugPass.setRenderTarget(&defaultRenderTarget); + defaultCompositor.addPass(&debugPass); + // Load compositor defaultCompositor.load(nullptr); @@ -678,6 +690,8 @@ bool Application::loadUI() levelActiveTexture = textureLoader->load("data/textures/ui-level-active.png"); levelInactiveTexture = textureLoader->load("data/textures/ui-level-inactive.png"); levelConnectorTexture = textureLoader->load("data/textures/ui-level-connector.png"); + pauseButtonTexture = textureLoader->load("data/textures/pause-button.png"); + playButtonTexture = textureLoader->load("data/textures/play-button.png"); // Get strings std::string pressAnyKeyString; @@ -781,6 +795,10 @@ bool Application::loadUI() frameTimeLabel->setText(""); uiRootElement->addChild(frameTimeLabel); + bool frameTimeLabelVisible = false; + settings.get("show_frame_time", &frameTimeLabelVisible); + frameTimeLabel->setVisible(frameTimeLabelVisible); + // Create "Press any key" element anyKeyLabel = new UILabel(); anyKeyLabel->setAnchor(Vector2(0.5f, 1.0f)); @@ -958,6 +976,25 @@ bool Application::loadUI() } } + // Create pause/play button elements + pauseButtonImage = new UIImage(); + pauseButtonImage->setAnchor(Vector2(0.0f, 1.0f)); + pauseButtonImage->setDimensions(Vector2(pauseButtonTexture->getWidth(), pauseButtonTexture->getHeight())); + pauseButtonImage->setTranslation(Vector2(16.0f, -16.0f)); + pauseButtonImage->setTexture(pauseButtonTexture); + pauseButtonImage->setVisible(false); + pauseButtonImage->setActive(false); + uiRootElement->addChild(pauseButtonImage); + + playButtonImage = new UIImage(); + playButtonImage->setAnchor(Vector2(0.0f, 1.0f)); + playButtonImage->setDimensions(Vector2(playButtonTexture->getWidth(), playButtonTexture->getHeight())); + playButtonImage->setTranslation(Vector2(16.0f, -16.0f)); + playButtonImage->setTexture(playButtonTexture); + playButtonImage->setVisible(false); + playButtonImage->setActive(false); + uiRootElement->addChild(playButtonImage); + // Create tweener tweener = new Tweener(); @@ -1047,6 +1084,11 @@ bool Application::loadUI() antHillFadeOutTween->setEndCallback(std::bind(Application::changeState, this, mainMenuState)); tweener->addTween(antHillFadeOutTween); + playButtonFadeTween = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f)); + playButtonFadeTween->setUpdateCallback(std::bind(UIElement::setTintColor, playButtonImage, std::placeholders::_1)); + playButtonFadeTween->setEndCallback(std::bind(UIElement::setVisible, playButtonImage, false)); + tweener->addTween(playButtonFadeTween); + // Build menu system selectedMenuItemIndex = 0; mainMenu = new Menu(); @@ -1241,6 +1283,7 @@ bool Application::loadControls() gameControlProfile->registerControl("walk-back", &walkBack); gameControlProfile->registerControl("turn-left", &turnLeft); gameControlProfile->registerControl("turn-right", &turnRight); + gameControlProfile->registerControl("toggle-pause", &togglePause); cameraMoveForward.bindKey(keyboard, SDL_SCANCODE_W); cameraMoveBack.bindKey(keyboard, SDL_SCANCODE_S); @@ -1258,6 +1301,7 @@ bool Application::loadControls() walkBack.bindKey(keyboard, SDL_SCANCODE_DOWN); turnLeft.bindKey(keyboard, SDL_SCANCODE_LEFT); turnRight.bindKey(keyboard, SDL_SCANCODE_RIGHT); + togglePause.bindKey(keyboard, SDL_SCANCODE_SPACE); return true; } @@ -1273,6 +1317,11 @@ bool Application::loadGame() campaign.load("data/levels/"); currentWorld = 1; currentLevel = 1; + simulationPaused = false; + + // Create colony + colony = new Colony(); + colony->setAntModel(antModel); return true; } @@ -1426,4 +1475,27 @@ void Application::loadLevel() std::string heightmap = std::string("data/textures/") + level->heightmap; terrain.load(heightmap); + + changeState(playState); +} + +void Application::pauseSimulation() +{ + simulationPaused = true; + playButtonImage->setVisible(false); + playButtonImage->setActive(false); + pauseButtonImage->setVisible(true); + pauseButtonImage->setActive(true); + playButtonFadeTween->stop(); +} + +void Application::unpauseSimulation() +{ + simulationPaused = false; + pauseButtonImage->setVisible(false); + pauseButtonImage->setActive(false); + playButtonImage->setTintColor(Vector4(1.0f)); + playButtonImage->setVisible(true); + playButtonImage->setActive(true); + playButtonFadeTween->start(); } \ No newline at end of file diff --git a/src/application.hpp b/src/application.hpp index c4ad93b..6a53a98 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -96,6 +96,9 @@ public: void loadLevel(); + void pauseSimulation(); + void unpauseSimulation(); + private: ApplicationState* state; ApplicationState* nextState; @@ -202,6 +205,7 @@ public: Control walkBack; Control turnLeft; Control turnRight; + Control togglePause; Arcball arcball; // Misc @@ -223,6 +227,8 @@ public: Texture* levelActiveTexture; Texture* levelInactiveTexture; Texture* levelConnectorTexture; + Texture* pauseButtonTexture; + Texture* playButtonTexture; // UI elements Vector4 selectedColor; @@ -266,6 +272,8 @@ public: UIContainer* levelSelectorContainer; UIImage* levelSelections[10]; UIImage* levelConnectors[9]; + UIImage* pauseButtonImage; + UIImage* playButtonImage; // Animation Tweener* tweener; @@ -287,6 +295,7 @@ public: Tween* antHillZoomInTween; Tween* antHillFadeOutTween; + Tween* playButtonFadeTween; // Menus std::size_t menuCount; @@ -318,6 +327,7 @@ public: bool cameraOverheadView; bool cameraNestView; int toolIndex; + bool simulationPaused; // Debug LineBatcher* lineBatcher; diff --git a/src/render-passes.cpp b/src/render-passes.cpp index 5bc4fa9..7ba9c1e 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -295,7 +295,6 @@ void SoilRenderPass::render(const RenderContext* renderContext) LightingRenderPass::LightingRenderPass(): shadowMap(0), shadowCamera(nullptr), - modelLoader(nullptr), treeShadow(nullptr), diffuseCubemap(nullptr) { @@ -1021,6 +1020,7 @@ void DebugRenderPass::render(const RenderContext* renderContext) { const Camera& camera = *(renderContext->camera); + /* // Bind framebuffer and setup viewport glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); glViewport(0, 0, renderTarget->width, renderTarget->height); @@ -1034,6 +1034,7 @@ void DebugRenderPass::render(const RenderContext* renderContext) glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); + */ // Disable backface culling glDisable(GL_CULL_FACE); diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 68a9e38..ceeaf4e 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -126,7 +126,6 @@ public: inline void setShadowMap(GLuint shadowMap) { this->shadowMap = shadowMap; } inline void setShadowCamera(const Camera* camera) { this->shadowCamera = camera; } - inline void setModelLoader(ModelLoader* modelLoader) { this->modelLoader = modelLoader; } private: bool loadShader(const RenderOperation& operation); @@ -158,8 +157,6 @@ private: Texture* specularCubemap; const Camera* shadowCamera; float time; - - ModelLoader* modelLoader; }; /** @@ -173,6 +170,11 @@ public: virtual void unload(); virtual void render(const RenderContext* renderContext); + //void setDrawBounds(bool enabled); + //void setDrawSkeletons(bool enabled); + //void setDrawCameras(bool enabled); + //void setDrawLights(bool enabled); + private: ShaderParameterSet parameterSet; const ShaderParameter* modelViewProjectionParam; diff --git a/src/states/main-menu-state.cpp b/src/states/main-menu-state.cpp index e8d9b2a..f942bf8 100644 --- a/src/states/main-menu-state.cpp +++ b/src/states/main-menu-state.cpp @@ -277,6 +277,8 @@ void MainMenuState::execute() void MainMenuState::exit() { + // Remove nest + application->defaultLayer->removeObject(&application->nestModelInstance); } void MainMenuState::mouseButtonPressed(int button, int x, int y) diff --git a/src/states/play-state.cpp b/src/states/play-state.cpp index 9f2766e..a0ef114 100644 --- a/src/states/play-state.cpp +++ b/src/states/play-state.cpp @@ -19,6 +19,9 @@ #include "play-state.hpp" #include "../application.hpp" +#include "../camera-controller.hpp" +#include "../game/colony.hpp" +#include "../game/ant.hpp" PlayState::PlayState(Application* application): ApplicationState(application) @@ -29,12 +32,107 @@ PlayState::~PlayState() void PlayState::enter() { - // Start fade-in - application->fadeInTween->start(); + // Hide level selector + application->levelSelectorContainer->setVisible(false); + application->levelSelectorContainer->setActive(false); + + // Setup HUD + application->pauseButtonImage->setVisible(false); + application->pauseButtonImage->setActive(false); + application->playButtonImage->setVisible(false); + application->playButtonImage->setActive(false); + + // Create terrain model instances + application->terrain.getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl"); + terrainSurface.setModel(application->terrain.getSurfaceModel()); + terrainSurface.setTranslation(Vector3(0, 0, 0)); + terrainSubsurface.setModel(application->terrain.getSubsurfaceModel()); + terrainSubsurface.setTranslation(Vector3(0, 0, 0)); + + // Add terrain to scene + application->defaultLayer->addObject(&terrainSurface); + application->defaultLayer->addObject(&terrainSubsurface); + + // Spawn ants + Navmesh* navmesh = application->terrain.getSurfaceNavmesh(); + for (int i = 0; i < 50; ++i) + { + Navmesh::Triangle* triangle = (*navmesh->getTriangles())[0]; + + Ant* ant = application->colony->spawn(navmesh, triangle, normalize_barycentric(Vector3(0.5f))); + + Vector3 forward = glm::normalize(triangle->edge->vertex->position - triangle->edge->next->vertex->position); + Vector3 up = triangle->normal; + ant->setOrientation(forward, up); + + application->defaultLayer->addObject(ant->getModelInstance()); + ant->setState(Ant::State::WANDER); + } + + // Setup camera controller + application->surfaceCam->setCamera(&application->camera); + application->surfaceCam->setFocalPoint(Vector3(0.0f)); + application->surfaceCam->setFocalDistance(250.0f); + application->surfaceCam->setElevation(glm::radians(35.0f)); + application->surfaceCam->setAzimuth(glm::radians(-45.0f)); + application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint()); + application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance()); + application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation()); + application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); + application->surfaceCam->update(0.0f); + + application->simulationPaused = false; } void PlayState::execute() { + // Update colony + if (!application->simulationPaused) + { + application->colony->update(application->dt); + } + + // Move camera + Vector2 movementVector(0.0f); + if (application->cameraMoveLeft.isTriggered()) + movementVector.x -= application->cameraMoveLeft.getCurrentValue(); + if (application->cameraMoveRight.isTriggered()) + movementVector.x += application->cameraMoveRight.getCurrentValue(); + if (application->cameraMoveForward.isTriggered()) + movementVector.y -= application->cameraMoveForward.getCurrentValue(); + if (application->cameraMoveBack.isTriggered()) + movementVector.y += application->cameraMoveBack.getCurrentValue(); + if (movementVector.x != 0.0f || movementVector.y != 0.0f) + { + movementVector *= 0.005f * application->surfaceCam->getFocalDistance() * application->dt / (1.0f / 60.0f); + application->surfaceCam->move(movementVector); + + Vector3 focal = application->surfaceCam->getFocalPoint(); + } + + // Zoom camera + float zoomFactor = application->surfaceCam->getFocalDistance() / 20.0f * application->dt / (1.0f / 60.0f); + if (application->cameraZoomIn.isTriggered()) + application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue()); + if (application->cameraZoomOut.isTriggered()) + application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue()); + application->surfaceCam->update(application->dt); + + // Update camera + application->surfaceCam->update(application->dt); + + // Pause simulation + if (application->togglePause.isTriggered() && !application->togglePause.wasTriggered()) + { + if (application->simulationPaused) + { + application->unpauseSimulation(); + } + else + { + application->pauseSimulation(); + } + } } void PlayState::exit() diff --git a/src/states/play-state.hpp b/src/states/play-state.hpp index dcfa490..e4c853a 100644 --- a/src/states/play-state.hpp +++ b/src/states/play-state.hpp @@ -38,6 +38,10 @@ public: virtual void mouseButtonPressed(int button, int x, int y); virtual void mouseButtonReleased(int button, int x, int y); + +private: + ModelInstance terrainSurface; + ModelInstance terrainSubsurface; }; #endif // PLAY_STATE_HPP \ No newline at end of file diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index 7cc5afd..fd17832 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -52,22 +52,6 @@ void TitleState::enter() // Title ant hill application->defaultLayer->addObject(&application->antHillModelInstance); - // Create terrain - application->terrain.create(255, 255, Vector3(50, 20, 50)); - application->terrain.getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl"); - terrainSurface.setModel(application->terrain.getSurfaceModel()); - terrainSurface.setTranslation(Vector3(0, 0, 0)); - terrainSubsurface.setModel(application->terrain.getSubsurfaceModel()); - terrainSubsurface.setTranslation(Vector3(0, 0, 0)); - //application->defaultLayer->addObject(&terrainSurface); - //application->defaultLayer->addObject(&terrainSubsurface); - navmesh = application->terrain.getSurfaceNavmesh(); - - // Load level - application->loadLevel(); - - - application->inputManager->addWindowObserver(this); windowResized(application->width, application->height); diff --git a/src/states/title-state.hpp b/src/states/title-state.hpp index d44d44f..1f47bf0 100644 --- a/src/states/title-state.hpp +++ b/src/states/title-state.hpp @@ -50,12 +50,6 @@ private: bool fadeIn; bool fadeOut; int substate; - - Colony colony; - Ant* ant; - Navmesh* navmesh; - ModelInstance terrainSurface; - ModelInstance terrainSubsurface; }; #endif // TITLE_STATE_HPP \ No newline at end of file