Browse Source

Add basic 3D level selection

master
C. J. Howard 7 years ago
parent
commit
64af255c0e
9 changed files with 438 additions and 152 deletions
  1. +2
    -0
      CMakeLists.txt
  2. +159
    -73
      src/application.cpp
  3. +25
    -11
      src/application.hpp
  4. +4
    -6
      src/configuration.hpp.in
  5. +56
    -35
      src/game/level.cpp
  6. +59
    -11
      src/game/level.hpp
  7. +86
    -0
      src/states/level-select-state.cpp
  8. +42
    -0
      src/states/level-select-state.hpp
  9. +5
    -16
      src/states/play-state.cpp

+ 2
- 0
CMakeLists.txt View File

@ -192,6 +192,8 @@ set(EXECUTABLE_SOURCES
${EXECUTABLE_SOURCE_DIR}/application-state.cpp ${EXECUTABLE_SOURCE_DIR}/application-state.cpp
${EXECUTABLE_SOURCE_DIR}/application.hpp ${EXECUTABLE_SOURCE_DIR}/application.hpp
${EXECUTABLE_SOURCE_DIR}/application.cpp ${EXECUTABLE_SOURCE_DIR}/application.cpp
${EXECUTABLE_SOURCE_DIR}/states/level-select-state.hpp
${EXECUTABLE_SOURCE_DIR}/states/level-select-state.cpp
${EXECUTABLE_SOURCE_DIR}/states/loading-state.hpp ${EXECUTABLE_SOURCE_DIR}/states/loading-state.hpp
${EXECUTABLE_SOURCE_DIR}/states/loading-state.cpp ${EXECUTABLE_SOURCE_DIR}/states/loading-state.cpp
${EXECUTABLE_SOURCE_DIR}/states/splash-state.hpp ${EXECUTABLE_SOURCE_DIR}/states/splash-state.hpp

+ 159
- 73
src/application.cpp View File

@ -25,12 +25,14 @@
#include "states/splash-state.hpp" #include "states/splash-state.hpp"
#include "states/title-state.hpp" #include "states/title-state.hpp"
#include "states/main-menu-state.hpp" #include "states/main-menu-state.hpp"
#include "states/level-select-state.hpp"
#include "states/play-state.hpp" #include "states/play-state.hpp"
#include "game/colony.hpp" #include "game/colony.hpp"
#include "ui/toolbar.hpp" #include "ui/toolbar.hpp"
#include "ui/pie-menu.hpp" #include "ui/pie-menu.hpp"
#include "debug.hpp" #include "debug.hpp"
#include "camera-controller.hpp" #include "camera-controller.hpp"
#include "configuration.hpp"
#include <algorithm> #include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
@ -322,6 +324,7 @@ Application::Application(int argc, char* argv[]):
splashState = new SplashState(this); splashState = new SplashState(this);
titleState = new TitleState(this); titleState = new TitleState(this);
mainMenuState = new MainMenuState(this); mainMenuState = new MainMenuState(this);
levelSelectState = new LevelSelectState(this);
playState = new PlayState(this); playState = new PlayState(this);
// Setup loaders // Setup loaders
@ -587,8 +590,9 @@ bool Application::loadModels()
antHillModel = modelLoader->load("data/models/ant-hill.mdl"); antHillModel = modelLoader->load("data/models/ant-hill.mdl");
nestModel = modelLoader->load("data/models/nest.mdl"); nestModel = modelLoader->load("data/models/nest.mdl");
forcepsModel = modelLoader->load("data/models/forceps.mdl"); forcepsModel = modelLoader->load("data/models/forceps.mdl");
levelPlaceholderModel = modelLoader->load("data/models/level-placeholder.mdl");
if (!antModel || !antHillModel || !nestModel)
if (!antModel || !antHillModel || !nestModel || !forcepsModel)
{ {
return false; return false;
} }
@ -600,8 +604,10 @@ bool Application::loadModels()
nestModelInstance.setModel(nestModel); nestModelInstance.setModel(nestModel);
forcepsModelInstance.setModel(forcepsModel); forcepsModelInstance.setModel(forcepsModel);
// Create terrain
terrain.create(255, 255, Vector3(50, 20, 50));
for (int i = 0; i < 5; ++i)
{
levelPlaceholderModelInstances[i].setModel(levelPlaceholderModel);
}
return true; return true;
} }
@ -984,36 +990,6 @@ bool Application::loadUI()
quitToDesktopLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2)); quitToDesktopLabel->setTranslation(Vector2(0.0f, menuFont->getMetrics().getHeight() * 2));
pauseMenuContainer->addChild(quitToDesktopLabel); pauseMenuContainer->addChild(quitToDesktopLabel);
// Create level selector elements
levelSelectorContainer = new UIContainer();
levelSelectorContainer->setDimensions(Vector2(levelActiveTexture->getWidth() * 10 + 48 * 9, levelActiveTexture->getHeight()));
levelSelectorContainer->setAnchor(Vector2(0.5f, 1.0f));
levelSelectorContainer->setTranslation(Vector2(0.0f, -levelActiveTexture->getHeight()));
levelSelectorContainer->setVisible(false);
levelSelectorContainer->setActive(false);
uiRootElement->addChild(levelSelectorContainer);
for (int i = 0; i < 10; ++i)
{
levelSelections[i] = new UIImage();
levelSelections[i]->setAnchor(Vector2(0.0f, 0.5f));
levelSelections[i]->setDimensions(Vector2(levelActiveTexture->getWidth(), levelActiveTexture->getHeight()));
levelSelections[i]->setTranslation(Vector2(i * 96.0f, 0.0f));
levelSelections[i]->setTexture(levelInactiveTexture);
levelSelections[i]->setVisible(true);
levelSelectorContainer->addChild(levelSelections[i]);
if (i < 9)
{
levelConnectors[i] = new UIImage();
levelConnectors[i]->setAnchor(Vector2(0.0f, 0.5f));
levelConnectors[i]->setDimensions(Vector2(levelConnectorTexture->getWidth(), levelConnectorTexture->getHeight()));
levelConnectors[i]->setTranslation(Vector2((i + 1) * 96.0f - 50.0f, 0.0f));
levelConnectors[i]->setTexture(levelConnectorTexture);
levelConnectors[i]->setVisible(true);
levelSelectorContainer->addChild(levelConnectors[i]);
}
}
// Create pause/play button elements // Create pause/play button elements
pauseButtonImage = new UIImage(); pauseButtonImage = new UIImage();
pauseButtonImage->setAnchor(Vector2(0.0f, 1.0f)); pauseButtonImage->setAnchor(Vector2(0.0f, 1.0f));
@ -1145,10 +1121,6 @@ bool Application::loadUI()
Vector2 menuSlideInStartTranslation = Vector2(-64.0f, 0.0f); Vector2 menuSlideInStartTranslation = Vector2(-64.0f, 0.0f);
Vector2 menuSlideInDeltaTranslation = Vector2((int)(64.0f + width / 8.0f), 0.0f); Vector2 menuSlideInDeltaTranslation = Vector2((int)(64.0f + width / 8.0f), 0.0f);
float levelSelectorSlideInDuration = 0.35f;
Vector2 levelSelectorSlideInStartTranslation = Vector2(0.0f, levelActiveTexture->getHeight());
Vector2 levelSelectorSlideInDeltaTranslation = Vector2(0.0f, -levelActiveTexture->getHeight() * 2.0f);
// Setup main menu tween // Setup main menu tween
menuFadeInTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor); menuFadeInTween = new Tween<Vector4>(EaseFunction::OUT_QUINT, 0.0f, menuFadeInDuration, menuFadeInStartColor, menuFadeInDeltaColor);
tweener->addTween(menuFadeInTween); tweener->addTween(menuFadeInTween);
@ -1157,10 +1129,6 @@ bool Application::loadUI()
menuSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation); menuSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, menuSlideInDuration, menuSlideInStartTranslation, menuSlideInDeltaTranslation);
tweener->addTween(menuSlideInTween); tweener->addTween(menuSlideInTween);
// Setup level selector tween
levelSelectorSlideInTween = new Tween<Vector2>(EaseFunction::OUT_QUINT, 0.0f, levelSelectorSlideInDuration, levelSelectorSlideInStartTranslation, levelSelectorSlideInDeltaTranslation);
tweener->addTween(levelSelectorSlideInTween);
// Title screen zoom in tween // Title screen zoom in tween
antHillZoomInTween = new Tween<float>(EaseFunction::LINEAR, 0.0f, 2.0f, 50.0f, -49.9f); antHillZoomInTween = new Tween<float>(EaseFunction::LINEAR, 0.0f, 2.0f, 50.0f, -49.9f);
antHillZoomInTween->setUpdateCallback(std::bind(&SurfaceCameraController::setTargetFocalDistance, surfaceCam, std::placeholders::_1)); antHillZoomInTween->setUpdateCallback(std::bind(&SurfaceCameraController::setTargetFocalDistance, surfaceCam, std::placeholders::_1));
@ -1176,6 +1144,10 @@ bool Application::loadUI()
playButtonFadeTween->setEndCallback(std::bind(&UIElement::setVisible, playButtonImage, false)); playButtonFadeTween->setEndCallback(std::bind(&UIElement::setVisible, playButtonImage, false));
tweener->addTween(playButtonFadeTween); tweener->addTween(playButtonFadeTween);
// Camera translation tween
cameraTranslationTween = new Tween<Vector3>(EaseFunction::OUT_CUBIC, 0.0f, 0.0f, Vector3(0.0f), Vector3(0.0f));
tweener->addTween(cameraTranslationTween);
// Build menu system // Build menu system
selectedMenuItemIndex = 0; selectedMenuItemIndex = 0;
mainMenu = new Menu(); mainMenu = new Menu();
@ -1286,20 +1258,6 @@ bool Application::loadUI()
selectedMenuItemIndex = 0; selectedMenuItemIndex = 0;
selectMenuItem(selectedMenuItemIndex); selectMenuItem(selectedMenuItemIndex);
currentLevel = 0;
levelSelectorMenu = new Menu();
for (int i = 0; i < 10; ++i)
{
MenuItem* levelSelectionItem = levelSelectorMenu->addItem();
levelSelectionItem->setSelectedCallback(std::bind(&UIImage::setTexture, levelSelections[i], levelActiveTexture));
levelSelectionItem->setDeselectedCallback(std::bind(&UIImage::setTexture, levelSelections[i], levelInactiveTexture));
levelSelectionItem->setActivatedCallback(std::bind(&Application::loadLevel, this));
levelSelections[i]->setMouseOverCallback(std::bind(&Application::selectLevel, this, levelSelectionItem->getIndex()));
levelSelections[i]->setMouseMovedCallback(std::bind(&Application::selectLevel, this, levelSelectionItem->getIndex()));
levelSelections[i]->setMousePressedCallback(std::bind(&Application::activateLevel, this, levelSelectionItem->getIndex()));
}
// Setup UI batch // Setup UI batch
uiBatch = new BillboardBatch(); uiBatch = new BillboardBatch();
uiBatch->resize(512); uiBatch->resize(512);
@ -1395,17 +1353,25 @@ bool Application::loadControls()
bool Application::loadGame() bool Application::loadGame()
{ {
// Load biosphere // Load biosphere
biosphere.load("data/biomes/"); biosphere.load("data/biomes/");
// Load campaign // Load campaign
campaign.load("data/levels/"); campaign.load("data/levels/");
currentWorld = 1;
currentLevel = 1;
currentWorldIndex = 0;
currentLevelIndex = 0;
for (int i = 0; i < 5; ++i)
{
previewLevelIndices[i] = oldPreviewLevelIndices[i] = i;
}
simulationPaused = false; simulationPaused = false;
// Allocate levels and initialize pointers
for (int i = 0; i < 5; ++i)
{
previewLevels[i] = new Level();
}
// Create colony // Create colony
colony = new Colony(); colony = new Colony();
colony->setAntModel(antModel); colony->setAntModel(antModel);
@ -1502,19 +1468,15 @@ void Application::enterLevelSelection()
{ {
exitMenu(0); exitMenu(0);
currentWorld = 1;
currentLevel = 1;
// Reset world and level indices
currentWorldIndex = 0;
currentLevelIndex = 0;
// Start menu slide-in tween
levelSelectorSlideInTween->setUpdateCallback(std::bind(&UIElement::setTranslation, levelSelectorContainer, std::placeholders::_1));
levelSelectorSlideInTween->reset();
levelSelectorSlideInTween->start();
// Make menu visible and active
levelSelectorContainer->setVisible(true);
levelSelectorContainer->setActive(true);
// Change to level select state
changeState(levelSelectState);
} }
/*
void Application::selectLevel(std::size_t index) void Application::selectLevel(std::size_t index)
{ {
if (index > levelSelectorMenu->getItemCount()) if (index > levelSelectorMenu->getItemCount())
@ -1543,7 +1505,130 @@ void Application::activateLevel(std::size_t index)
//levelSelectorMenu->getItem(currentLevel - 1)->deselect(); //levelSelectorMenu->getItem(currentLevel - 1)->deselect();
levelSelectorMenu->getItem(currentLevel - 1)->activate(); levelSelectorMenu->getItem(currentLevel - 1)->activate();
} }
*/
// Level count: 16
// Max loaded levels: 5
// 0: [ 0] 1 2 3 4
// 1: 0 [ 1] 2 3 4
// 2: 0 1 [ 2] 3 4
// 3: 5 1 2 [ 3] 4
// 4: 5 6 2 3 [ 4]
// 5: [ 5] 6 7 3 4
// 6: 5 [ 6] 7 8 4
// 7: 5 6 [ 7] 8 9
// 8: 10 6 7 [ 8] 9
// 9: 10 11 7 8 [ 9]
//10: [10] 11 12 8 9
//11: 10 [11] 12 13 9
//12: 10 11 [12] 13 14
//13: 15 11 12 [13] 14
//14: 15 11 12 13 [14]
//15: [15] 11 12 13 14
// pointer index = currentLevel % 5;
void Application::selectLevel(std::size_t index)
{
// Set current level
currentLevelIndex = static_cast<int>(index);
// Calculate index of current loaded level
currentPreviewIndex = (currentLevelIndex % 5);
// Get total number of levels in the current world
int levelCount = campaign.getLevelCount(currentWorldIndex);
// Calculate indices of level previews
previewLevelIndices[(currentPreviewIndex + 3) % 5] = (currentLevelIndex <= 2) ? ((currentLevelIndex + 3) % 5) : currentLevelIndex - 2;
previewLevelIndices[(currentPreviewIndex + 4) % 5] = (currentLevelIndex <= 2) ? ((currentLevelIndex + 4) % 5) : currentLevelIndex - 1;
previewLevelIndices[(currentPreviewIndex + 0) % 5] = currentLevelIndex;
previewLevelIndices[(currentPreviewIndex + 1) % 5] = (currentLevelIndex >= levelCount - 1) ? (((currentLevelIndex + 1) % (levelCount - 1)) + ((levelCount - 1) - 5)) : currentLevelIndex + 1;
previewLevelIndices[(currentPreviewIndex + 2) % 5] = (currentLevelIndex >= levelCount - 2) ? (((currentLevelIndex + 2) % (levelCount - 1)) + ((levelCount - 1) - 5)) : currentLevelIndex + 2;
// Load unloaded previews
for (int i = 0; i < 5; ++i)
{
if (oldPreviewLevelIndices[i] != previewLevelIndices[i])
{
std::cout << "Unloaded level " << oldPreviewLevelIndices[i] << std::endl;
std::cout << "Loaded level " << previewLevelIndices[i] << std::endl;
}
}
// Load unloaded previews
for (int i = 0; i < 5; ++i)
{
if (oldPreviewLevelIndices[i] != previewLevelIndices[i])
{
oldPreviewLevelIndices[i] = previewLevelIndices[i];
// Load preview
}
if (currentPreviewIndex == i)
{
std::cout << " [" << previewLevelIndices[i] << "] ";
}
else
{
std::cout << " " << previewLevelIndices[i] << " ";
}
}
std::cout << std::endl;
// Perform tweening
for (int i = 0; i < 5; ++i)
{
levelPlaceholderModelInstances[i].setTranslation(Vector3(4.0f, 0.0f, 0.0f) * static_cast<float>(previewLevelIndices[i]));
}
}
void Application::selectNextLevel()
{
if (currentLevelIndex < campaign.getLevelCount(currentWorldIndex) - 1)
{
selectLevel(currentLevelIndex + 1);
// Setup camera tween
cameraTranslationTween->setTime(0.0f);
cameraTranslationTween->setDuration(0.125f);
cameraTranslationTween->setStartValue(camera.getTranslation());
cameraTranslationTween->setDeltaValue(Vector3(4.0f, 0.0f, 0.0f));
cameraTranslationTween->setUpdateCallback(std::bind(&SceneObject::setTranslation, &camera, std::placeholders::_1));
cameraTranslationTween->start();
}
}
void Application::selectPreviousLevel()
{
if (currentLevelIndex > 0)
{
selectLevel(currentLevelIndex - 1);
// Setup camera tween
cameraTranslationTween->setTime(0.0f);
cameraTranslationTween->setDuration(0.125f);
cameraTranslationTween->setStartValue(camera.getTranslation());
cameraTranslationTween->setDeltaValue(Vector3(-4.0f, 0.0f, 0.0f));
cameraTranslationTween->setUpdateCallback(std::bind(&SceneObject::setTranslation, &camera, std::placeholders::_1));
cameraTranslationTween->start();
}
}
void Application::enterSelectedLevel()
{
}
/*
void Application::loadLevel() void Application::loadLevel()
{ {
if (currentLevel < 1 || currentLevel >= campaign.levels[currentWorld].size()) if (currentLevel < 1 || currentLevel >= campaign.levels[currentWorld].size())
@ -1552,8 +1637,8 @@ void Application::loadLevel()
return; return;
} }
const Level* level = &campaign.levels[currentWorld][currentLevel];
const Biome* biome = &biosphere.biomes[level->biome];
const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorld, currentLevel);
const Biome* biome = &biosphere.biomes[levelParams->biome];
soilPass.setHorizonOTexture(biome->soilHorizonO); soilPass.setHorizonOTexture(biome->soilHorizonO);
soilPass.setHorizonATexture(biome->soilHorizonA); soilPass.setHorizonATexture(biome->soilHorizonA);
@ -1561,13 +1646,14 @@ void Application::loadLevel()
soilPass.setHorizonCTexture(biome->soilHorizonC); soilPass.setHorizonCTexture(biome->soilHorizonC);
std::string heightmap = std::string("data/textures/") + level->heightmap; std::string heightmap = std::string("data/textures/") + level->heightmap;
terrain.load(heightmap);
currentLevelTerrain->load(heightmap);
// Set skybox // Set skybox
skyboxPass.setCubemap(biome->specularCubemap); skyboxPass.setCubemap(biome->specularCubemap);
changeState(playState);
//changeState(playState);
} }
*/
void Application::pauseSimulation() void Application::pauseSimulation()
{ {

+ 25
- 11
src/application.hpp View File

@ -43,6 +43,7 @@ class SplashState;
class TitleState; class TitleState;
class MainMenuState; class MainMenuState;
class PlayState; class PlayState;
class LevelSelectState;
class CameraController; class CameraController;
class SurfaceCameraController; class SurfaceCameraController;
class TunnelCameraController; class TunnelCameraController;
@ -92,11 +93,15 @@ public:
void activateMenuItem(std::size_t index); void activateMenuItem(std::size_t index);
void selectLevel(std::size_t index); void selectLevel(std::size_t index);
void activateLevel(std::size_t index);
void selectNextLevel();
void selectPreviousLevel();
void enterSelectedLevel();
//void activateLevel(std::size_t index);
void enterLevelSelection(); void enterLevelSelection();
void loadLevel();
void pauseSimulation(); void pauseSimulation();
void unpauseSimulation(); void unpauseSimulation();
@ -135,6 +140,7 @@ public:
SplashState* splashState; SplashState* splashState;
TitleState* titleState; TitleState* titleState;
MainMenuState* mainMenuState; MainMenuState* mainMenuState;
LevelSelectState* levelSelectState;
PlayState* playState; PlayState* playState;
// Scene // Scene
@ -154,6 +160,7 @@ public:
ModelInstance antModelInstance; ModelInstance antModelInstance;
ModelInstance antHillModelInstance; ModelInstance antHillModelInstance;
ModelInstance nestModelInstance; ModelInstance nestModelInstance;
ModelInstance levelPlaceholderModelInstances[5];
// Graphics // Graphics
Renderer renderer; Renderer renderer;
@ -290,9 +297,6 @@ public:
UILabel* pausedSettingsLabel; UILabel* pausedSettingsLabel;
UILabel* returnToMainMenuLabel; UILabel* returnToMainMenuLabel;
UILabel* quitToDesktopLabel; UILabel* quitToDesktopLabel;
UIContainer* levelSelectorContainer;
UIImage* levelSelections[10];
UIImage* levelConnectors[9];
UIImage* pauseButtonImage; UIImage* pauseButtonImage;
UIImage* playButtonImage; UIImage* playButtonImage;
UIImage* rectangularPaletteImage; UIImage* rectangularPaletteImage;
@ -320,12 +324,13 @@ public:
Tween<Vector4>* menuFadeInTween; Tween<Vector4>* menuFadeInTween;
Tween<Vector4>* menuFadeOutTween; Tween<Vector4>* menuFadeOutTween;
Tween<Vector2>* menuSlideInTween; Tween<Vector2>* menuSlideInTween;
Tween<Vector2>* levelSelectorSlideInTween;
Tween<float>* antHillZoomInTween; Tween<float>* antHillZoomInTween;
Tween<Vector4>* antHillFadeOutTween; Tween<Vector4>* antHillFadeOutTween;
Tween<Vector4>* playButtonFadeTween; Tween<Vector4>* playButtonFadeTween;
Tween<Vector3>* cameraTranslationTween;
// Menus // Menus
std::size_t menuCount; std::size_t menuCount;
Menu** menus; Menu** menus;
@ -337,20 +342,29 @@ public:
Menu* challengeMenu; Menu* challengeMenu;
Menu* experimentMenu; Menu* experimentMenu;
Menu* settingsMenu; Menu* settingsMenu;
Menu* levelSelectorMenu;
// Models // Models
Model* antModel; Model* antModel;
Model* antHillModel; Model* antHillModel;
Model* nestModel; Model* nestModel;
Model* forcepsModel; Model* forcepsModel;
Model* levelPlaceholderModel;
// Game variables // Game variables
Campaign campaign;
int currentWorld;
int currentLevel;
Biosphere biosphere; Biosphere biosphere;
Terrain terrain;
Campaign campaign;
int currentWorldIndex;
int currentLevelIndex;
int currentPreviewIndex;
int previewLevelIndices[5];
int oldPreviewLevelIndices[5];
Level* previewLevels[5];
Level* currentLevel;
Colony* colony; Colony* colony;
SurfaceCameraController* surfaceCam; SurfaceCameraController* surfaceCam;
TunnelCameraController* tunnelCam; TunnelCameraController* tunnelCam;

+ 4
- 6
src/configuration.hpp.in View File

@ -26,11 +26,9 @@
#define ANTKEEPER_VERSION_STRING "@ANTKEEPER_VERSION@" #define ANTKEEPER_VERSION_STRING "@ANTKEEPER_VERSION@"
#cmakedefine ANTKEEPER_DEBUG #cmakedefine ANTKEEPER_DEBUG
#if defined(ANTKEEPER_DEBUG)
#define ANTKEEPER_FIRST_WORLD_INDEX 0
#else
#define ANTKEEPER_FIRST_WORLD_INDEX 1
#endif
#define ANTKEEPER_FIRST_LEVEL_INDEX 1
// Terrain dimensions
const float ANTKEEPER_TERRAIN_WIDTH = 50.0f;
const float ANTKEEPER_TERRAIN_BASE_HEIGHT = 35.7f;
const float ANTKEEPER_TERRAIN_DEPTH = 50.0f;
#endif // CONFIGURATION_HPP #endif // CONFIGURATION_HPP

+ 56
- 35
src/game/level.cpp View File

@ -1,20 +1,21 @@
#include "level.hpp" #include "level.hpp"
#include "../settings.hpp" #include "../settings.hpp"
#include "../configuration.hpp"
#include <dirent.h> #include <dirent.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
Level::Level():
worldIndex(-1),
levelIndex(-1)
LevelParameterSet::LevelParameterSet()
{} {}
Level::~Level()
LevelParameterSet::~LevelParameterSet()
{} {}
bool Level::load()
bool LevelParameterSet::load(const std::string& filename)
{ {
this->filename = filename;
ParameterDict parameters; ParameterDict parameters;
if (!parameters.load(filename)) if (!parameters.load(filename))
{ {
@ -27,6 +28,37 @@ bool Level::load()
return true; return true;
} }
Level::Level()
{
terrain.create(255, 255, Vector3(ANTKEEPER_TERRAIN_WIDTH, ANTKEEPER_TERRAIN_BASE_HEIGHT, ANTKEEPER_TERRAIN_DEPTH));
}
Level::~Level()
{}
bool Level::load(const LevelParameterSet& params)
{
// Load terrain from heightmap
std::string heightmapFilename = std::string("data/textures/") + params.heightmap;
if (!terrain.load(heightmapFilename))
{
std::cerr << "Failed to load terrain from heightmap file \"" << heightmapFilename << "\" for level \"" << params.filename << "\"" << std::endl;
return false;
}
//application->currentLevelTerrain->getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl");
// Setup terrain surface model instance
terrainSurface.setModel(terrain.getSurfaceModel());
terrainSurface.setTranslation(Vector3(0, 0, 0));
// Setup terrain subsurface model instance
terrainSubsurface.setModel(terrain.getSubsurfaceModel());
terrainSubsurface.setTranslation(Vector3(0, 0, 0));
return true;
}
Campaign::Campaign() Campaign::Campaign()
{} {}
@ -72,57 +104,46 @@ bool Campaign::load(const std::string& directory)
std::stringstream stream; std::stringstream stream;
stream << worldIndexString; stream << worldIndexString;
stream >> worldIndex; stream >> worldIndex;
worldIndex -= 1;
stream.str(std::string()); stream.str(std::string());
stream.clear(); stream.clear();
stream << levelIndexString; stream << levelIndexString;
stream >> levelIndex; stream >> levelIndex;
levelIndex -= 1;
if (worldIndex < 0 || levelIndex < 0) if (worldIndex < 0 || levelIndex < 0)
{ {
std::cout << "Invalid level \"" << filename << "\"" << std::endl;
std::cout << "Invalid level parameters file \"" << filename << "\"" << std::endl;
continue; continue;
} }
// Resize vector to accommodate maximum world index // Resize vector to accommodate maximum world index
if (worldIndex >= static_cast<int>(levels.size()))
if (worldIndex >= static_cast<int>(levelParameterSets.size()))
{ {
levels.resize(worldIndex + 1);
levelParameterSets.resize(worldIndex + 1);
} }
// Resize vector to accommodate maximum level index
if (levelIndex >= static_cast<int>(levels[worldIndex].size()))
// Resize vector to accommodate maximum level file index
if (levelIndex >= static_cast<int>(levelParameterSets[worldIndex].size()))
{ {
levels[worldIndex].resize(levelIndex + 1);
levelParameterSets[worldIndex].resize(levelIndex + 1);
} }
// Add level
Level* level = &levels[worldIndex][levelIndex];
level->filename = directory + filename;
level->worldIndex = worldIndex;
level->levelIndex = levelIndex;
// Load level parameters
LevelParameterSet* levelParams = &levelParameterSets[worldIndex][levelIndex];
if (!levelParams->load(directory + filename))
{
std::cout << "Failed to load parameters for level " << (worldIndex + 1) << "-" << (levelIndex + 1) << std::endl;
}
else
{
std::cout << "Loaded level parameters for level " << (worldIndex + 1) << "-" << (levelIndex + 1) << std::endl;
}
} }
// Close levels directory // Close levels directory
closedir(dir); closedir(dir);
// Load levels
for (std::size_t i = ANTKEEPER_FIRST_WORLD_INDEX; i < levels.size(); ++i)
{
for (std::size_t j = ANTKEEPER_FIRST_LEVEL_INDEX; j < levels[i].size(); ++j)
{
Level* level = &levels[i][j];
if (!level->load())
{
std::cout << "Failed to load level " << i << "-" << j << std::endl;
}
else
{
std::cout << "Loaded level " << i << "-" << j << std::endl;
}
}
}
return true; return true;
}
}

+ 59
- 11
src/game/level.hpp View File

@ -1,35 +1,83 @@
#ifndef LEVEL_SELECTOR_HPP
#define LEVEL_SELECTOR_HPP
#ifndef LEVEL_HPP
#define LEVEL_HPP
#include "../configuration.hpp" #include "../configuration.hpp"
#include "terrain.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
class Level
/**
* Contains the parameters required to load a level.
*/
class LevelParameterSet
{ {
public: public:
Level();
~Level();
LevelParameterSet();
~LevelParameterSet();
bool load();
// Loads level parameters from a .lvl file
bool load(const std::string& filename);
std::string filename; std::string filename;
int worldIndex;
int levelIndex;
std::string biome; std::string biome;
std::string heightmap; std::string heightmap;
}; };
/**
* A level.
*/
class Level
{
public:
Level();
~Level();
// Loads a level from a level file
bool load(const LevelParameterSet& params);
Terrain terrain;
ModelInstance terrainSurface;
ModelInstance terrainSubsurface;
};
/**
* A collection of level parameters which constitute a campaign.
*/
class Campaign class Campaign
{ {
public: public:
Campaign(); Campaign();
~Campaign(); ~Campaign();
// Loads all level parameter sets in a directory with the file name pattern `<world>-<level>.lvl`
bool load(const std::string& directory); bool load(const std::string& directory);
std::vector<std::vector<Level>> levels;
// Returns the number of worlds in the campaign
std::size_t getWorldCount() const;
// Returns the number of levels in a world
std::size_t getLevelCount(std::size_t worldIndex) const;
// Returns the file for the level with the specified indices
const LevelParameterSet* getLevelParams(std::size_t worldIndex, std::size_t levelIndex) const;
private:
std::vector<std::vector<LevelParameterSet>> levelParameterSets;
}; };
#endif // LEVEL_SELECTOR_HPP
inline std::size_t Campaign::getWorldCount() const
{
return levelParameterSets.size();
}
inline std::size_t Campaign::getLevelCount(std::size_t worldIndex) const
{
return levelParameterSets[worldIndex].size();
}
inline const LevelParameterSet* Campaign::getLevelParams(std::size_t worldIndex, std::size_t levelIndex) const
{
return &levelParameterSets[worldIndex][levelIndex];
}
#endif // LEVEL_HPP

+ 86
- 0
src/states/level-select-state.cpp View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
*/
#include "level-select-state.hpp"
#include "../application.hpp"
LevelSelectState::LevelSelectState(Application* application):
ApplicationState(application)
{}
LevelSelectState::~LevelSelectState()
{}
void LevelSelectState::enter()
{
for (int i = 0; i < 5; ++i)
{
ModelInstance* instance = &application->levelPlaceholderModelInstances[i];
application->defaultLayer->addObject(instance);
}
application->camera.lookAt(Vector3(0, 10, 20), Vector3(0, 1, 0), Vector3(0, 1, 0));
application->selectLevel(0);
levelRotation = 0.0f;
}
void LevelSelectState::execute()
{
// Navigate menu
if (application->menuLeft.isTriggered() && !application->menuLeft.wasTriggered())
{
application->selectPreviousLevel();
}
else if (application->menuRight.isTriggered() && !application->menuRight.wasTriggered())
{
application->selectNextLevel();
}
if (application->menuDown.isTriggered() && !application->menuDown.wasTriggered())
{
}
else if (application->menuUp.isTriggered() && !application->menuUp.wasTriggered())
{
}
if (application->menuSelect.isTriggered() && !application->menuSelect.wasTriggered())
{
application->enterSelectedLevel();
}
else if (application->menuCancel.isTriggered() && !application->menuCancel.wasTriggered())
{
}
// Rotate levels
levelRotation += glm::radians(5.0f) * application->dt;
for (int i = 0; i < 5; ++i)
{
ModelInstance* instance = &application->levelPlaceholderModelInstances[i];
instance->setRotation(glm::angleAxis(levelRotation, Vector3(0, 1, 0)));
}
}
void LevelSelectState::exit()
{
}

+ 42
- 0
src/states/level-select-state.hpp View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
*/
#ifndef LEVEL_SELECT_STATE_HPP
#define LEVEL_SELECT_STATE_HPP
#include "../application-state.hpp"
#include <emergent/emergent.hpp>
using namespace Emergent;
class LevelSelectState: public ApplicationState
{
public:
LevelSelectState(Application* application);
virtual ~LevelSelectState();
virtual void enter();
virtual void execute();
virtual void exit();
private:
float levelRotation;
};
#endif // LEVEL_SELECT_STATE_HPP

+ 5
- 16
src/states/play-state.cpp View File

@ -34,10 +34,6 @@ PlayState::~PlayState()
void PlayState::enter() void PlayState::enter()
{ {
// Hide level selector
application->levelSelectorContainer->setVisible(false);
application->levelSelectorContainer->setActive(false);
// Setup HUD // Setup HUD
application->pauseButtonImage->setVisible(false); application->pauseButtonImage->setVisible(false);
application->pauseButtonImage->setActive(false); application->pauseButtonImage->setActive(false);
@ -55,22 +51,15 @@ void PlayState::enter()
//application->backgroundLayer->addObject(&application->bgCamera); //application->backgroundLayer->addObject(&application->bgCamera);
//application->backgroundLayer->addObject(&application->bgBatch); //application->backgroundLayer->addObject(&application->bgBatch);
// 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 // Add terrain to scene
application->defaultLayer->addObject(&terrainSurface);
application->defaultLayer->addObject(&terrainSubsurface);
application->defaultLayer->addObject(&application->currentLevel->terrainSurface);
application->defaultLayer->addObject(&application->currentLevel->terrainSubsurface);
// Add forceps to scene // Add forceps to scene
application->defaultLayer->addObject(&application->forcepsModelInstance); application->defaultLayer->addObject(&application->forcepsModelInstance);
// Spawn ants // Spawn ants
Navmesh* navmesh = application->terrain.getSurfaceNavmesh();
Navmesh* navmesh = application->currentLevel->terrain.getSurfaceNavmesh();
for (int i = 0; i < 50; ++i) for (int i = 0; i < 50; ++i)
{ {
Navmesh::Triangle* triangle = (*navmesh->getTriangles())[0]; Navmesh::Triangle* triangle = (*navmesh->getTriangles())[0];
@ -178,7 +167,7 @@ void PlayState::execute()
pickingRay.direction = glm::normalize(mouseFar - mouseNear); pickingRay.direction = glm::normalize(mouseFar - mouseNear);
std::list<Navmesh::Triangle*> triangles; std::list<Navmesh::Triangle*> triangles;
application->terrain.getSurfaceOctree()->query(pickingRay, &triangles);
application->currentLevel->terrain.getSurfaceOctree()->query(pickingRay, &triangles);
auto result = intersects(pickingRay, triangles); auto result = intersects(pickingRay, triangles);
if (std::get<0>(result)) if (std::get<0>(result))
@ -186,7 +175,7 @@ void PlayState::execute()
pick = pickingRay.extrapolate(std::get<1>(result)); pick = pickingRay.extrapolate(std::get<1>(result));
std::size_t triangleIndex = std::get<3>(result); std::size_t triangleIndex = std::get<3>(result);
pickTriangle = (*application->terrain.getSurfaceNavmesh()->getTriangles())[triangleIndex];
pickTriangle = (*application->currentLevel->terrain.getSurfaceNavmesh()->getTriangles())[triangleIndex];
float forcepsDistance = (application->forcepsClosed) ? 0.0f : 0.5f; float forcepsDistance = (application->forcepsClosed) ? 0.0f : 0.5f;

Loading…
Cancel
Save