Implemented Level concept and scaffolding for map simulation
This commit is contained in:
parent
4dae13150f
commit
916050153a
17 changed files with 375 additions and 12 deletions
|
@ -57,7 +57,39 @@ set(SOURCES
|
|||
src/game/camera/tracking_area.h
|
||||
src/game/camera/tracking_view_options.hpp
|
||||
src/game/collectables/environment_collectable.cpp
|
||||
src/game/collectables/environment_collectable.hpp src/sprites/texture_manager.cpp src/sprites/texture_manager.hpp src/sprites/sprite_sheet.cpp src/sprites/sprite_sheet.hpp src/sprites/animated_sprite.cpp src/sprites/animated_sprite.hpp src/sprites/single_sprite.cpp src/sprites/single_sprite.hpp src/texture_config.h src/sprites/configs/sprite_config.hpp src/sprites/configs/sheet_config.hpp src/sprites/configs/animation_config.hpp src/sprites/versatile_sprite.cpp src/sprites/versatile_sprite.hpp src/sprites/sprite.hpp src/sprites/sprite_factory.cpp src/sprites/sprite_factory.hpp src/input_config.h src/game/input/button_config.hpp src/game/input/game_action.hpp src/game/input/button_config_factory.cpp src/game/input/button_config_factory.hpp src/game/input/game_action_config.hpp src/game/input/gamepad_buttons.hpp)
|
||||
src/game/collectables/environment_collectable.hpp
|
||||
src/sprites/texture_manager.cpp
|
||||
src/sprites/texture_manager.hpp
|
||||
src/sprites/sprite_sheet.cpp
|
||||
src/sprites/sprite_sheet.hpp
|
||||
src/sprites/animated_sprite.cpp
|
||||
src/sprites/animated_sprite.hpp
|
||||
src/sprites/single_sprite.cpp
|
||||
src/sprites/single_sprite.hpp
|
||||
src/texture_config.h
|
||||
src/sprites/configs/sprite_config.hpp
|
||||
src/sprites/configs/sheet_config.hpp
|
||||
src/sprites/configs/animation_config.hpp
|
||||
src/sprites/versatile_sprite.cpp
|
||||
src/sprites/versatile_sprite.hpp
|
||||
src/sprites/sprite.hpp
|
||||
src/sprites/sprite_factory.cpp
|
||||
src/sprites/sprite_factory.hpp
|
||||
src/input_config.h
|
||||
src/game/input/button_config.hpp
|
||||
src/game/input/game_action.hpp
|
||||
src/game/input/button_config_factory.cpp
|
||||
src/game/input/button_config_factory.hpp
|
||||
src/game/input/game_action_config.hpp
|
||||
src/game/input/gamepad_buttons.hpp
|
||||
src/game/physics/map_simulation.cpp
|
||||
src/game/physics/map_simulation.hpp
|
||||
src/game/physics/map_player.cpp
|
||||
src/game/physics/map_player.hpp
|
||||
src/game/level/level_config.hpp
|
||||
src/game/level/level_loader.cpp
|
||||
src/game/level/level_loader.hpp
|
||||
src/levels.hpp)
|
||||
|
||||
set(PHYSICS_00_SOURCES
|
||||
src/prototypes/physics_00.cpp)
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
#define DEF_TV_MAX_VIEW_SIZE sf::Vector2f(0, 0)
|
||||
#define DEF_TV_VIEW_SIZE_PADDING sf::Vector2f(0.5f, 0.5f)
|
||||
|
||||
// Simulations
|
||||
#define MAPSIM_PLAYER_RADIUS 2.f
|
||||
#define MAPSIM_VELOCITY_ITERATIONS 6
|
||||
#define MAPSIM_POSITION_ITERATIONS 2
|
||||
|
||||
// Directions
|
||||
#define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f
|
||||
|
||||
|
|
|
@ -3,10 +3,15 @@
|
|||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
|
||||
#include "game.h"
|
||||
#include "level/level_loader.hpp"
|
||||
#include "physics/map_simulation.hpp"
|
||||
#include "../debug/grid_debug_layer.h"
|
||||
#include "player/player_spawner.hpp"
|
||||
|
||||
Game::Game(std::shared_ptr<sf::RenderWindow> window) : window(std::move(window)),
|
||||
gameObjects(),
|
||||
views()
|
||||
views(),
|
||||
loadedLevelConfig()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -85,6 +90,11 @@ void Game::update()
|
|||
}
|
||||
|
||||
InputMapper::getInstance()->updateIdentities();
|
||||
|
||||
if (isLevelLoaded())
|
||||
{
|
||||
MapSimulation::getInstance()->updateSimulation();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> Game::getInstance()
|
||||
|
@ -113,3 +123,22 @@ void Game::registerView(TrackingView *view)
|
|||
{
|
||||
views.push_back(view);
|
||||
}
|
||||
|
||||
void Game::clearGameObjects()
|
||||
{
|
||||
for (auto &gameObject: gameObjects)
|
||||
{
|
||||
delete gameObject;
|
||||
}
|
||||
gameObjects.clear();
|
||||
}
|
||||
|
||||
void Game::setLevel(LevelConfig levelConfig)
|
||||
{
|
||||
loadedLevelConfig = std::move(levelConfig);
|
||||
}
|
||||
|
||||
bool Game::isLevelLoaded() const
|
||||
{
|
||||
return loadedLevelConfig.isValid();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "game_object.h"
|
||||
#include "input/input_mapper.h"
|
||||
#include "camera/tracking_view.h"
|
||||
#include "level/level_config.hpp"
|
||||
|
||||
class TrackingView;
|
||||
|
||||
|
@ -24,6 +25,12 @@ public:
|
|||
|
||||
void exit();
|
||||
|
||||
void clearGameObjects();
|
||||
|
||||
void setLevel(LevelConfig levelConfig);
|
||||
|
||||
bool isLevelLoaded() const;
|
||||
|
||||
void addGameObject(GameObject *gameObject);
|
||||
|
||||
void registerView(TrackingView *view);
|
||||
|
@ -34,6 +41,8 @@ private:
|
|||
static inline std::shared_ptr<Game> singletonInstance = nullptr;
|
||||
std::vector<GameObject *> gameObjects;
|
||||
|
||||
LevelConfig loadedLevelConfig;
|
||||
|
||||
void drawFrame();
|
||||
|
||||
void update();
|
||||
|
|
28
src/game/level/level_config.hpp
Normal file
28
src/game/level/level_config.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef HOLESOME_LEVEL_CONFIG_HPP
|
||||
#define HOLESOME_LEVEL_CONFIG_HPP
|
||||
|
||||
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
struct LevelConfig
|
||||
{
|
||||
std::string name;
|
||||
sf::Vector2f worldMapSize = {};
|
||||
std::vector<sf::Vector2f> playerSpawnPoints = {};
|
||||
|
||||
LevelConfig(std::string name, const sf::Vector2f &worldMapSize,
|
||||
const std::vector<sf::Vector2f> &playerSpawnPoints)
|
||||
: name(std::move(name)), worldMapSize(worldMapSize), playerSpawnPoints(playerSpawnPoints)
|
||||
{ }
|
||||
|
||||
LevelConfig() = default;
|
||||
|
||||
bool isValid() const {
|
||||
return !name.empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_LEVEL_CONFIG_HPP
|
39
src/game/level/level_loader.cpp
Normal file
39
src/game/level/level_loader.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "level_loader.hpp"
|
||||
#include "../game.h"
|
||||
#include "../physics/map_simulation.hpp"
|
||||
#include "../../debug/grid_debug_layer.h"
|
||||
#include "../player/player_spawner.hpp"
|
||||
#include "../../levels.hpp"
|
||||
|
||||
void LevelLoader::loadLevel(LevelConfig levelConfig)
|
||||
{
|
||||
Game::getInstance()->clearGameObjects();
|
||||
|
||||
LOG(INFO) << "Loading level '" << levelConfig.name << "' ...";
|
||||
|
||||
Game::getInstance()->setLevel(levelConfig);
|
||||
MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize);
|
||||
|
||||
// Add basic game objects
|
||||
if (DEVELOPER_MODE)
|
||||
{
|
||||
Game::getInstance()->addGameObject(new GridDebugLayer(0, 50, 0, 50));
|
||||
}
|
||||
|
||||
Game::getInstance()->addGameObject(new TrackingView());
|
||||
Game::getInstance()->addGameObject(new PlayerSpawner(levelConfig.playerSpawnPoints));
|
||||
|
||||
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
|
||||
}
|
||||
|
||||
void LevelLoader::loadLevel(const std::string &levelName)
|
||||
{
|
||||
// Does level exist?
|
||||
if (!LEVELS.contains(levelName))
|
||||
{
|
||||
LOG(ERROR) << "Level '" << levelName << "' not found. Could not load it.";
|
||||
throw std::invalid_argument("Could not load level.");
|
||||
}
|
||||
|
||||
LevelLoader::loadLevel(LEVELS.at(levelName));
|
||||
}
|
17
src/game/level/level_loader.hpp
Normal file
17
src/game/level/level_loader.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef HOLESOME_LEVEL_LOADER_HPP
|
||||
#define HOLESOME_LEVEL_LOADER_HPP
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include "level_config.hpp"
|
||||
|
||||
class LevelLoader
|
||||
{
|
||||
public:
|
||||
static void loadLevel(LevelConfig levelConfig);
|
||||
|
||||
static void loadLevel(const std::string &levelName);
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_LEVEL_LOADER_HPP
|
1
src/game/physics/map_player.cpp
Normal file
1
src/game/physics/map_player.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "map_player.hpp"
|
17
src/game/physics/map_player.hpp
Normal file
17
src/game/physics/map_player.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef HOLESOME_MAP_PLAYER_HPP
|
||||
#define HOLESOME_MAP_PLAYER_HPP
|
||||
|
||||
|
||||
#include <box2d/box2d.h>
|
||||
#include "../player/player.hpp"
|
||||
|
||||
struct MapPlayer
|
||||
{
|
||||
Player *player;
|
||||
b2Body *body;
|
||||
|
||||
MapPlayer(Player *player, b2Body *body) : player(player), body(body) {}
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_MAP_PLAYER_HPP
|
91
src/game/physics/map_simulation.cpp
Normal file
91
src/game/physics/map_simulation.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "map_simulation.hpp"
|
||||
#include "../../config.h"
|
||||
|
||||
MapSimulation::MapSimulation()
|
||||
{
|
||||
mapPlayersById = std::map<int, std::shared_ptr<MapPlayer>>();
|
||||
}
|
||||
|
||||
std::shared_ptr<MapSimulation> MapSimulation::getInstance()
|
||||
{
|
||||
if (singletonInstance == nullptr)
|
||||
{
|
||||
singletonInstance = std::make_shared<MapSimulation>();
|
||||
}
|
||||
return singletonInstance;
|
||||
}
|
||||
|
||||
void MapSimulation::updateSimulation()
|
||||
{
|
||||
// Get player positions
|
||||
for (auto &mapPlayer: mapPlayersById)
|
||||
{
|
||||
auto player = mapPlayer.second->player;
|
||||
auto body = mapPlayer.second->body;
|
||||
|
||||
auto coordinates = player->coordinates->world();
|
||||
b2Vec2 playerPosition = b2Vec2(coordinates.x, coordinates.y);
|
||||
body->SetTransform(playerPosition, 0);
|
||||
}
|
||||
|
||||
world->Step(FRAME_TIME.asSeconds(), MAPSIM_VELOCITY_ITERATIONS, MAPSIM_POSITION_ITERATIONS);
|
||||
|
||||
// Update player positions
|
||||
for (auto &mapPlayer: mapPlayersById)
|
||||
{
|
||||
auto player = mapPlayer.second->player;
|
||||
auto body = mapPlayer.second->body;
|
||||
|
||||
b2Vec2 playerPosition = body->GetPosition();
|
||||
player->coordinates->set(sf::Vector2f(playerPosition.x, playerPosition.y));
|
||||
}
|
||||
}
|
||||
|
||||
void MapSimulation::resetMap(sf::Vector2f worldMapSize)
|
||||
{
|
||||
// No gravity, since this a top-down view of the map
|
||||
world = std::make_shared<b2World>(b2Vec2(0.0f, 0.0f));
|
||||
mapPlayersById.clear();
|
||||
|
||||
// Create map borders
|
||||
constructSquareObstacle(-1, 0, 0, worldMapSize.y);
|
||||
constructSquareObstacle(0, -1, worldMapSize.x, 0);
|
||||
constructSquareObstacle(worldMapSize.x, 0, worldMapSize.x + 1, worldMapSize.y);
|
||||
constructSquareObstacle(0, worldMapSize.y, worldMapSize.x, worldMapSize.y + 1);
|
||||
}
|
||||
|
||||
void MapSimulation::constructSquareObstacle(float minX, float minY, float maxX, float maxY)
|
||||
{
|
||||
b2BodyDef bodyDef;
|
||||
bodyDef.type = b2_staticBody;
|
||||
bodyDef.position.Set((maxX - minX) / 2.f, (maxY - minY) / 2.f);
|
||||
b2Body *body = world->CreateBody(&bodyDef);
|
||||
|
||||
b2PolygonShape shape;
|
||||
shape.SetAsBox(maxX - minX, maxY - minY);
|
||||
|
||||
b2FixtureDef fixtureDef;
|
||||
fixtureDef.shape = &shape;
|
||||
fixtureDef.density = 1.0f;
|
||||
|
||||
body->CreateFixture(&fixtureDef);
|
||||
}
|
||||
|
||||
void MapSimulation::addPlayer(Player *player)
|
||||
{
|
||||
b2BodyDef bodyDef;
|
||||
bodyDef.type = b2_kinematicBody;
|
||||
bodyDef.position.Set(player->getTrackablePosition().x, player->getTrackablePosition().y);
|
||||
b2Body *body = world->CreateBody(&bodyDef);
|
||||
|
||||
b2CircleShape shape;
|
||||
shape.m_radius = MAPSIM_PLAYER_RADIUS;
|
||||
shape.m_p.Set(0, 0);
|
||||
|
||||
b2FixtureDef fixtureDef;
|
||||
fixtureDef.shape = &shape;
|
||||
fixtureDef.density = 1.0f;
|
||||
|
||||
body->CreateFixture(&fixtureDef);
|
||||
mapPlayersById[player->getPlayerId()] = std::make_shared<MapPlayer>(player, body);
|
||||
}
|
35
src/game/physics/map_simulation.hpp
Normal file
35
src/game/physics/map_simulation.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef HOLESOME_MAP_SIMULATION_HPP
|
||||
#define HOLESOME_MAP_SIMULATION_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <box2d/box2d.h>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include "../player/player.hpp"
|
||||
#include "map_player.hpp"
|
||||
|
||||
class MapSimulation
|
||||
{
|
||||
public:
|
||||
MapSimulation();
|
||||
|
||||
void updateSimulation();
|
||||
|
||||
void resetMap(sf::Vector2f worldMapSize);
|
||||
|
||||
static std::shared_ptr<MapSimulation> getInstance();
|
||||
|
||||
void addPlayer(Player *player);
|
||||
|
||||
|
||||
private:
|
||||
static inline std::shared_ptr<MapSimulation> singletonInstance = nullptr;
|
||||
|
||||
std::shared_ptr<b2World> world;
|
||||
std::map<int, std::shared_ptr<MapPlayer>> mapPlayersById;
|
||||
|
||||
void constructSquareObstacle(float minX, float minY, float maxX, float maxY);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_MAP_SIMULATION_HPP
|
|
@ -4,9 +4,11 @@
|
|||
#include <utility>
|
||||
|
||||
Player::Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName,
|
||||
WorldCoordinates initCoordinates)
|
||||
sf::Vector2f spawnPosition)
|
||||
{
|
||||
coordinates->set(initCoordinates);
|
||||
playerId = playerCreationCounter++;
|
||||
this->spawnPosition = spawnPosition;
|
||||
coordinates->set(spawnPosition);
|
||||
|
||||
input = std::move(assignedInput);
|
||||
|
||||
|
@ -54,3 +56,8 @@ TrackableState Player::getTrackableState() const
|
|||
return TrackableState::END_TRACKING;
|
||||
}
|
||||
}
|
||||
|
||||
int Player::getPlayerId() const
|
||||
{
|
||||
return playerId;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
class Player : public GameObject, public ITrackable
|
||||
{
|
||||
public:
|
||||
Player(std::shared_ptr<InputIdentity> assignedInput, const std::string& skinRessourceName, WorldCoordinates initCoordinates);
|
||||
Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName,
|
||||
sf::Vector2f initCoordinates);
|
||||
|
||||
~Player();
|
||||
|
||||
|
@ -23,9 +24,16 @@ public:
|
|||
|
||||
float speed = 30.0f;
|
||||
|
||||
int getPlayerId() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<InputIdentity> input;
|
||||
float width = 50;
|
||||
|
||||
sf::Vector2f spawnPosition;
|
||||
|
||||
int playerId;
|
||||
static inline int playerCreationCounter = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2,13 +2,35 @@
|
|||
#include "player.hpp"
|
||||
#include "../../texture_config.h"
|
||||
|
||||
PlayerSpawner::PlayerSpawner(const std::vector<sf::Vector2f> &spawnPoints)
|
||||
{
|
||||
this->spawnPoints = spawnPoints;
|
||||
|
||||
// Create player for existing input identities
|
||||
for (auto &inputIdentity: InputMapper::getInstance()->getInputIdentities())
|
||||
{
|
||||
spawnPlayer(inputIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSpawner::update()
|
||||
{
|
||||
// Create player for new input identities
|
||||
for (auto &inputIdentity: InputMapper::getInstance()->newInputIdentities)
|
||||
{
|
||||
auto player = new Player(inputIdentity, PLAYER_SKIN, {0, 0});
|
||||
spawnPlayer(inputIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSpawner::spawnPlayer(const std::shared_ptr<InputIdentity> &inputIdentity)
|
||||
{
|
||||
// Get proper Spawn point, if available
|
||||
sf::Vector2f spawn = spawnPoints[nextSpawnPointIndex];
|
||||
nextSpawnPointIndex = static_cast<int>((nextSpawnPointIndex + 1) % spawnPoints.size());
|
||||
|
||||
auto player = new Player(inputIdentity, PLAYER_SKIN, spawn);
|
||||
|
||||
Game::getInstance()->addGameObject(player);
|
||||
// TODO: Better view handling
|
||||
Game::getInstance()->views[0]->addTrackable(player);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,15 @@
|
|||
class PlayerSpawner : public GameObject
|
||||
{
|
||||
public:
|
||||
PlayerSpawner(const std::vector<sf::Vector2f>& spawnPoints);
|
||||
|
||||
void update() override;
|
||||
|
||||
void spawnPlayer(const std::shared_ptr<InputIdentity> &inputIdentity);
|
||||
|
||||
private:
|
||||
std::vector<sf::Vector2f> spawnPoints;
|
||||
int nextSpawnPointIndex = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
14
src/levels.hpp
Normal file
14
src/levels.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef HOLESOME_LEVELS_HPP
|
||||
#define HOLESOME_LEVELS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "game/level/level_config.hpp"
|
||||
|
||||
#define INITIAL_LEVEL "default"
|
||||
|
||||
std::map<std::string, LevelConfig> const LEVELS = {
|
||||
{"default", LevelConfig("Default", {25, 25}, {{1, 1}})}
|
||||
};
|
||||
|
||||
#endif //HOLESOME_LEVELS_HPP
|
|
@ -6,6 +6,8 @@
|
|||
#include "game/player/player_spawner.hpp"
|
||||
#include "sprites/texture_manager.hpp"
|
||||
#include "texture_config.h"
|
||||
#include "game/level/level_loader.hpp"
|
||||
#include "levels.hpp"
|
||||
|
||||
void loadAllTextures();
|
||||
|
||||
|
@ -26,9 +28,8 @@ void runGame()
|
|||
LOG(INFO) << "Starting game ...";
|
||||
auto game = GameFactory::createWindowed("Holesome");
|
||||
|
||||
game->addGameObject(new GridDebugLayer(0, 50, 0, 50));
|
||||
game->addGameObject(new TrackingView());
|
||||
game->addGameObject(new PlayerSpawner());
|
||||
// Load initial level
|
||||
LevelLoader::loadLevel(INITIAL_LEVEL);
|
||||
|
||||
game->run();
|
||||
|
||||
|
|
Loading…
Reference in a new issue