Implemented procedural world generation
This commit is contained in:
parent
f50a346e22
commit
851e591c3c
11 changed files with 223 additions and 7 deletions
|
@ -138,7 +138,7 @@ set(SOURCES
|
|||
src/typography/font_manager.cpp
|
||||
src/typography/font_manager.hpp
|
||||
src/screens/winner_screen.cpp
|
||||
src/screens/winner_screen.hpp src/screens/screen.cpp src/screens/screen.hpp src/screens/join_screen.cpp src/screens/join_screen.hpp)
|
||||
src/screens/winner_screen.hpp src/screens/screen.cpp src/screens/screen.hpp src/screens/join_screen.cpp src/screens/join_screen.hpp src/game/level/level_generator.cpp src/game/level/level_generator.hpp src/screens/loading_screen.cpp src/screens/loading_screen.hpp)
|
||||
|
||||
set(PHYSICS_00_SOURCES
|
||||
src/prototypes/physics_00.cpp)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
// World
|
||||
#define WORLD_GRAVITY b2Vec2(0.f, -9.8f)
|
||||
#define SKY_HEIGHT_SCALE 2.f
|
||||
#define SKY_HEIGHT_SCALE 5.f
|
||||
#define CONSIDER_COLLECTABLE_DEPTH_MOVEMENT false // Might cost perfomance and is currently not in use
|
||||
|
||||
// FPS
|
||||
|
@ -47,7 +47,7 @@
|
|||
#define DEF_TV_MIN_VIEW_SIZE sf::Vector2f(6, 6) * WORLD_TO_ISO_SCALE
|
||||
#define DEF_TV_MAX_VIEW_SIZE sf::Vector2f(0, 0)
|
||||
#define DEF_TV_IS_ABSOLUTE_VIEW_SIZE_PADDING false
|
||||
#define DEF_TV_VIEW_SIZE_PADDING sf::Vector2f(3.5f, 3.5f)
|
||||
#define DEF_TV_VIEW_SIZE_PADDING sf::Vector2f(2.f, 2.f)
|
||||
#define MP_VIEW_ADD_NEW_PLAYERS true
|
||||
#define MP_VIEW_REMOVE_DISCONNECTED_PLAYERS true
|
||||
#define MP_VIEW_BORDER_COLOR sf::Color::Black
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "player/player_collection.hpp"
|
||||
#include "../screens/winner_screen.hpp"
|
||||
#include "../screens/join_screen.hpp"
|
||||
#include "level/level_generator.hpp"
|
||||
#include "../screens/loading_screen.hpp"
|
||||
|
||||
Game::Game(std::shared_ptr<sf::RenderWindow> window) : window(std::move(window))
|
||||
{
|
||||
|
@ -223,3 +225,26 @@ void Game::showJoinScreen()
|
|||
addGameObject(GlobalLayer::getInstance());
|
||||
addGameObject(PlayerCollection::getInstance());
|
||||
}
|
||||
|
||||
void Game::generateNewLevel()
|
||||
{
|
||||
showLoadingScreen("Generating new level ...");
|
||||
|
||||
LevelConfig newLevel = LevelGenerator::generateLevel("Procedural Level");
|
||||
LevelLoader::loadLevel(newLevel);
|
||||
}
|
||||
|
||||
void Game::showLoadingScreen(const std::string &message)
|
||||
{
|
||||
GlobalLayer::getInstance()->clear();
|
||||
clearGameObjects();
|
||||
|
||||
auto loadingScreen = std::make_shared<LoadingScreen>(message);
|
||||
GlobalLayer::getInstance()->add(loadingScreen);
|
||||
|
||||
addGameObject(GlobalLayer::getInstance());
|
||||
|
||||
// Mini loop
|
||||
update();
|
||||
drawFrame();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
|
||||
void showJoinScreen();
|
||||
|
||||
void generateNewLevel();
|
||||
|
||||
private:
|
||||
static inline std::shared_ptr<Game> singletonInstance = nullptr;
|
||||
std::vector<std::shared_ptr<GameObject>> gameObjects = {};
|
||||
|
@ -58,6 +60,8 @@ private:
|
|||
std::shared_ptr<Player> checkForWinner();
|
||||
|
||||
void handleWinning();
|
||||
|
||||
void showLoadingScreen(const std::string &message = "Loading...");
|
||||
};
|
||||
|
||||
|
||||
|
|
134
src/game/level/level_generator.cpp
Normal file
134
src/game/level/level_generator.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
#include "level_generator.hpp"
|
||||
|
||||
LevelConfig LevelGenerator::generateLevel(const std::string &name)
|
||||
{
|
||||
int levelSize = 50;
|
||||
|
||||
TileMapConfig map = generateRandomMap(levelSize, levelSize);
|
||||
std::vector<CollectableInLevel> collectables = generateRandomCollectables(levelSize, levelSize);
|
||||
|
||||
return LevelConfig(name,
|
||||
120,
|
||||
{
|
||||
{1, 2},
|
||||
{2, 1},
|
||||
{0, 3},
|
||||
{3, 0}
|
||||
},
|
||||
collectables,
|
||||
{
|
||||
// Blues
|
||||
sf::Color(2, 100, 234),
|
||||
sf::Color(2, 100, 234),
|
||||
sf::Color(2, 100, 234),
|
||||
sf::Color(2, 195, 234),
|
||||
|
||||
// Neutral
|
||||
sf::Color::White,
|
||||
|
||||
// Browns
|
||||
sf::Color(163, 128, 68),
|
||||
sf::Color(100, 80, 40),
|
||||
sf::Color(20, 18, 11),
|
||||
sf::Color::Black
|
||||
},
|
||||
map
|
||||
);
|
||||
}
|
||||
|
||||
TileMapConfig LevelGenerator::generateRandomMap(int width, int height)
|
||||
{
|
||||
int tileVariants = 6 * 2;
|
||||
std::vector<std::vector<int>> tiles;
|
||||
for (int h = 0; h < height; h++)
|
||||
{
|
||||
std::vector<int> row;
|
||||
for (int w = 0; w < width; w++)
|
||||
{
|
||||
row.push_back(rand() % tileVariants);
|
||||
}
|
||||
tiles.push_back(row);
|
||||
}
|
||||
|
||||
return TileMapConfig("iso-tiles", tiles);
|
||||
}
|
||||
|
||||
std::vector<CollectableInLevel> LevelGenerator::generateRandomCollectables(int width, int height)
|
||||
{
|
||||
std::vector<CollectableInLevel> collectables;
|
||||
|
||||
// Add rose fields
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
// Random coordinates for center of rose field with enough distance from edges
|
||||
int x = rand() % int(width - 2 * roseFieldRadius) + roseFieldRadius;
|
||||
int y = rand() % int(height - 2 * roseFieldRadius) + roseFieldRadius;
|
||||
|
||||
GridCoordinates fieldCenter = GridCoordinates(x, y);
|
||||
|
||||
// Add rose field by creating a dense field of roses around the center
|
||||
int roseCount = rand() % 15 + 5;
|
||||
for (int j = 0; j < roseCount; j++)
|
||||
{
|
||||
// Use cosine distribution to get a more dense field around the center
|
||||
float angle = rand() % 360;
|
||||
float radius = rand() % 1000 / 1000.f;
|
||||
|
||||
// Skew radius to avoid too dense at center
|
||||
radius = pow(radius, 0.3f) * roseFieldRadius;
|
||||
|
||||
float xOffset = radius * cos(angle);
|
||||
float yOffset = radius * sin(angle);
|
||||
|
||||
GridCoordinates roseCoordinates = GridCoordinates(fieldCenter.x + xOffset, fieldCenter.y + yOffset);
|
||||
collectables.push_back(CollectableInLevel("rose", roseCoordinates));
|
||||
}
|
||||
}
|
||||
|
||||
// Place rows of lanterns
|
||||
int rowCount = rand() % 3 + 2;
|
||||
int heightDelta = height / (rowCount + 1);
|
||||
int stepSize = 7;
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
int y = (i + 1) * heightDelta;
|
||||
for (int j = stepSize; j < width; j += stepSize)
|
||||
{
|
||||
collectables.push_back(CollectableInLevel("lantern", GridCoordinates(j, y)));
|
||||
}
|
||||
}
|
||||
|
||||
// Place random bikes
|
||||
int bikeCount = rand() % 5 + 5;
|
||||
for (int i = 0; i < bikeCount; i++)
|
||||
{
|
||||
int x = rand() % width;
|
||||
int y = rand() % height;
|
||||
collectables.push_back(CollectableInLevel("bike", GridCoordinates(x, y)));
|
||||
}
|
||||
|
||||
// Place random rose bushes
|
||||
int roseBushCount = rand() % 40 + 40;
|
||||
for (int i = 0; i < roseBushCount; i++)
|
||||
{
|
||||
int x = rand() % width;
|
||||
int y = rand() % height;
|
||||
collectables.push_back(CollectableInLevel("rose-bush", GridCoordinates(x, y)));
|
||||
}
|
||||
|
||||
// Place random stones
|
||||
int stoneCount = rand() % 20 + 20;
|
||||
for (int i = 0; i < stoneCount; i++)
|
||||
{
|
||||
int x = rand() % width;
|
||||
int y = rand() % height;
|
||||
collectables.push_back(CollectableInLevel("stone", GridCoordinates(x, y)));
|
||||
}
|
||||
|
||||
// Place a single tree
|
||||
int x = rand() % width;
|
||||
int y = rand() % height;
|
||||
collectables.push_back(CollectableInLevel("small-tree", GridCoordinates(x, y)));
|
||||
|
||||
return collectables;
|
||||
}
|
21
src/game/level/level_generator.hpp
Normal file
21
src/game/level/level_generator.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef HOLESOME_LEVEL_GENERATOR_HPP
|
||||
#define HOLESOME_LEVEL_GENERATOR_HPP
|
||||
|
||||
|
||||
#include "level_config.hpp"
|
||||
|
||||
class LevelGenerator
|
||||
{
|
||||
public:
|
||||
static LevelConfig generateLevel(const std::string& name);
|
||||
|
||||
static TileMapConfig generateRandomMap(int width, int height);
|
||||
|
||||
static std::vector<CollectableInLevel> generateRandomCollectables(int width, int height);
|
||||
|
||||
private:
|
||||
static const inline float roseFieldRadius = 3.f;
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_LEVEL_GENERATOR_HPP
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
std::map<std::string, LevelConfig> const all_levels = {
|
||||
{"default", LevelConfig("Default",
|
||||
5,
|
||||
120,
|
||||
{
|
||||
{0, 0},
|
||||
{18, 18},
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../game/player/player_collection.hpp"
|
||||
#include "../levels.hpp"
|
||||
#include "../game/level/level_loader.hpp"
|
||||
#include "../game/game.h"
|
||||
|
||||
JoinScreen::JoinScreen()
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ void JoinScreen::update()
|
|||
if (input->isPerformingAction(GameAction::CONFIRM))
|
||||
{
|
||||
// Start game
|
||||
LevelLoader::loadLevel(INITIAL_LEVEL);
|
||||
Game::getInstance()->generateNewLevel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
17
src/screens/loading_screen.cpp
Normal file
17
src/screens/loading_screen.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <SFML/Graphics/Text.hpp>
|
||||
#include "loading_screen.hpp"
|
||||
#include "../typography/font_manager.hpp"
|
||||
#include "../config.h"
|
||||
|
||||
LoadingScreen::LoadingScreen(const std::string &message)
|
||||
{
|
||||
auto text = std::make_shared<sf::Text>();
|
||||
text->setString(message);
|
||||
text->setFont(*FontManager::getInstance()->getDefaultFont());
|
||||
text->setCharacterSize(24);
|
||||
text->setStyle(sf::Text::Italic);
|
||||
text->setFillColor(sf::Color::White);
|
||||
text->setPosition(REFERENCE_SIZE.x / 2.f - text->getGlobalBounds().width / 2.f,
|
||||
REFERENCE_SIZE.y / 2.f - text->getGlobalBounds().height / 2.f);
|
||||
add(text);
|
||||
}
|
14
src/screens/loading_screen.hpp
Normal file
14
src/screens/loading_screen.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef HOLESOME_LOADING_SCREEN_HPP
|
||||
#define HOLESOME_LOADING_SCREEN_HPP
|
||||
|
||||
|
||||
#include "screen.hpp"
|
||||
|
||||
class LoadingScreen : public Screen
|
||||
{
|
||||
public:
|
||||
explicit LoadingScreen(const std::string &message = "Loading...");
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_LOADING_SCREEN_HPP
|
|
@ -9,7 +9,7 @@
|
|||
#include "sprites/tiling/tileset_config.hpp"
|
||||
#include "sprites/configs/masked_sprite_config.hpp"
|
||||
|
||||
#define PLAYER_SKINS std::vector<std::string> { "player-0", "player-1", "player-2", "player-3" }
|
||||
#define PLAYER_SKINS std::vector<std::string> { "player", "player-1", "player-2", "player-3" }
|
||||
|
||||
/**
|
||||
* All textures used in the game.
|
||||
|
@ -91,7 +91,7 @@ std::map<std::string, MaskedSpriteConfig> const all_masked_sprites = {
|
|||
* The key is the name of the tileset, the value is the tileset config.
|
||||
*/
|
||||
std::map<std::string, TileSetConfig> const all_tilesets = {
|
||||
{"iso-tiles", TileSetConfig("custom-grass-tiles", {0, 1, 2, 3, 4, 5})}
|
||||
{"iso-tiles", TileSetConfig("custom-grass-tiles", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11})}
|
||||
};
|
||||
|
||||
#endif //HOLESOME_TEXTURE_CONFIG_H
|
||||
|
|
Loading…
Reference in a new issue