Adds player spawner and greatly improves input identity handling
This commit is contained in:
parent
c3bc72fb4c
commit
875fab8c46
14 changed files with 1707 additions and 99 deletions
|
@ -51,7 +51,10 @@ set(SOURCES
|
|||
src/utilities/smart_list.h
|
||||
src/utilities/vector_utils.hpp
|
||||
src/game/world/ITrackable.h
|
||||
src/game/input/input_identity.h)
|
||||
src/game/input/input_identity.h
|
||||
src/utilities/magic_enum.hpp
|
||||
src/game/player/player_spawner.cpp
|
||||
src/game/player/player_spawner.hpp)
|
||||
|
||||
set(PHYSICS_00_SOURCES
|
||||
src/prototypes/physics_00.cpp)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <map>
|
||||
#include "game/input/"
|
||||
#include "game/input/input_device_group.h"
|
||||
|
||||
#define DEVELOPER_MODE true
|
||||
|
|
|
@ -49,7 +49,10 @@ void Game::drawFrame()
|
|||
|
||||
for (auto &gameObject: gameObjects)
|
||||
{
|
||||
gameObject->draw(window.get());
|
||||
if (gameObject->isActive)
|
||||
{
|
||||
gameObject->draw(window.get());
|
||||
}
|
||||
}
|
||||
|
||||
window->display();
|
||||
|
@ -65,28 +68,38 @@ void Game::update()
|
|||
// Basic Updates
|
||||
for (auto &gameObject: gameObjects)
|
||||
{
|
||||
gameObject->update(this);
|
||||
if (gameObject->isActive)
|
||||
{
|
||||
gameObject->update(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Late updates
|
||||
for (auto &gameObject: gameObjects)
|
||||
{
|
||||
gameObject->lateUpdate(this);
|
||||
if (gameObject->isActive)
|
||||
{
|
||||
gameObject->lateUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
InputMapper::getInstance()->updateIdentityEvents();
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> Game::getInstance()
|
||||
{
|
||||
if (singletonInstance == nullptr) {
|
||||
if (singletonInstance == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Game instance has to be initialized first.");
|
||||
}
|
||||
|
||||
return singletonInstance;
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> Game::constructInstance(const std::shared_ptr<sf::RenderWindow>& window)
|
||||
std::shared_ptr<Game> Game::constructInstance(const std::shared_ptr<sf::RenderWindow> &window)
|
||||
{
|
||||
if (singletonInstance != nullptr) {
|
||||
if (singletonInstance != nullptr)
|
||||
{
|
||||
throw std::runtime_error("Game instance has already been initialized.");
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
{}
|
||||
|
||||
TranslatedCoordinates coordinates;
|
||||
bool isActive = true;
|
||||
};
|
||||
|
||||
#endif //HOLESOME_GAME_OBJECT_H
|
||||
|
|
|
@ -14,6 +14,10 @@ HardDirection Direction::getKeyDirection(sf::Keyboard::Key key)
|
|||
map[sf::Keyboard::Down] = HardDirection::DOWN;
|
||||
map[sf::Keyboard::Left] = HardDirection::LEFT;
|
||||
map[sf::Keyboard::Right] = HardDirection::RIGHT;
|
||||
map[sf::Keyboard::I] = HardDirection::UP;
|
||||
map[sf::Keyboard::K] = HardDirection::DOWN;
|
||||
map[sf::Keyboard::J] = HardDirection::LEFT;
|
||||
map[sf::Keyboard::L] = HardDirection::RIGHT;
|
||||
|
||||
if (map.find(key) == map.end())
|
||||
return HardDirection::NONE;
|
||||
|
|
|
@ -4,20 +4,23 @@
|
|||
#include <set>
|
||||
#include "direction.h"
|
||||
#include "input_device_group.h"
|
||||
#include "key_features.hpp"
|
||||
#include "../../utilities/magic_enum.hpp"
|
||||
|
||||
|
||||
struct InputIdentity
|
||||
{
|
||||
Direction direction = Direction();
|
||||
InputDeviceGroup deviceType = InputDeviceGroup::UNKNOWN;
|
||||
InputDeviceGroup deviceGroup = InputDeviceGroup::UNKNOWN;
|
||||
unsigned int gamepadId = 0;
|
||||
unsigned int inputOrder = 0;
|
||||
bool isActive = true;
|
||||
|
||||
explicit InputIdentity(InputDeviceGroup type, unsigned int gamepad = 0)
|
||||
{
|
||||
deviceType = type;
|
||||
deviceGroup = type;
|
||||
gamepadId = gamepad;
|
||||
|
||||
LOG(INFO) << "Created input identity [" << magic_enum::enum_name(type) << ", gamepad " << gamepadId << "]";
|
||||
};
|
||||
|
||||
static InputDeviceGroup getDeviceTypeFromEvent(sf::Event event)
|
||||
|
@ -26,13 +29,7 @@ struct InputIdentity
|
|||
{
|
||||
case sf::Event::KeyPressed:
|
||||
case sf::Event::KeyReleased:
|
||||
if (wasd_keys.contains(event.key.code))
|
||||
{
|
||||
return InputDeviceGroup::KEYBOARD_WASD;
|
||||
} else
|
||||
{
|
||||
return InputDeviceGroup::KEYBOARD_ARROWS;
|
||||
}
|
||||
return KeyFeatures(event.key.code).deviceGroup;
|
||||
case sf::Event::JoystickButtonPressed:
|
||||
case sf::Event::JoystickButtonReleased:
|
||||
case sf::Event::JoystickConnected:
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
InputMapper::InputMapper()
|
||||
{
|
||||
// Initialize identities
|
||||
allIdentity = std::make_shared<InputIdentity>(InputDeviceGroup::ALL);
|
||||
keyboardIdentity = std::make_shared<InputIdentity>(InputDeviceGroup::KEYBOARD);
|
||||
gamepadIdentities = std::map<unsigned int, std::shared_ptr<InputIdentity>>();
|
||||
inputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
||||
newInputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
||||
deprecatedInputIdentities = std::set<std::shared_ptr<InputIdentity>>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,10 +32,10 @@ void InputMapper::processEvents()
|
|||
handleJoystickMovement(event.joystickMove);
|
||||
break;
|
||||
case sf::Event::JoystickConnected:
|
||||
addGamepadIdentity(event.joystickConnect.joystickId);
|
||||
getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickConnect.joystickId);
|
||||
break;
|
||||
case sf::Event::JoystickDisconnected:
|
||||
deactivateGamepadIdentity(event.joystickConnect.joystickId);
|
||||
deactivateIdentity(getInputIdentity(InputDeviceGroup::GAMEPAD, event.joystickConnect.joystickId));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -54,20 +53,21 @@ void InputMapper::handleKeyPress(sf::Event::KeyEvent event)
|
|||
}
|
||||
|
||||
// Handle directionVector
|
||||
auto direction = Direction::getKeyDirection(event.code);
|
||||
if (direction != HardDirection::NONE)
|
||||
auto feature = KeyFeatures(event.code);
|
||||
if (feature.deviceGroup != InputDeviceGroup::UNKNOWN)
|
||||
{
|
||||
getInputIdentity(InputDeviceGroup::KEYBOARD)->direction.add(direction);
|
||||
getInputIdentity(feature.deviceGroup)->direction.add(feature.hardDirection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::handleKeyRelease(sf::Event::KeyEvent event)
|
||||
{
|
||||
// Handle directionVector
|
||||
auto direction = Direction::getKeyDirection(event.code);
|
||||
if (direction != HardDirection::NONE)
|
||||
auto feature = KeyFeatures(event.code);
|
||||
if (feature.deviceGroup != InputDeviceGroup::UNKNOWN)
|
||||
{
|
||||
getInputIdentity(InputDeviceGroup::KEYBOARD)->direction.remove(direction);
|
||||
getInputIdentity(feature.deviceGroup)->direction.remove(feature.hardDirection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,43 +94,40 @@ void InputMapper::handleJoystickMovement(sf::Event::JoystickMoveEvent event)
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceGroup deviceType, unsigned int gamepadId)
|
||||
std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceGroup deviceGroup, unsigned int gamepadId)
|
||||
{
|
||||
switch (deviceType)
|
||||
if (deviceGroup == InputDeviceGroup::UNKNOWN)
|
||||
{
|
||||
case InputDeviceGroup::KEYBOARD:
|
||||
return keyboardIdentity;
|
||||
case InputDeviceGroup::GAMEPAD:
|
||||
if (!gamepadIdentities.contains(gamepadId))
|
||||
{
|
||||
// Create if it does not exist yet
|
||||
addGamepadIdentity(gamepadId);
|
||||
}
|
||||
return gamepadIdentities[gamepadId];
|
||||
default:
|
||||
return allIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::addGamepadIdentity(unsigned int gamepadId)
|
||||
{
|
||||
// Exists already?
|
||||
if (gamepadIdentities.contains(gamepadId))
|
||||
{
|
||||
gamepadIdentities[gamepadId]->isActive = true;
|
||||
return;
|
||||
throw std::invalid_argument("InputDeviceGroup cannot be UNKNOWN");
|
||||
}
|
||||
|
||||
// Does not exist yet, create new
|
||||
auto newIdentity = std::make_shared<InputIdentity>(InputDeviceGroup::GAMEPAD, gamepadId);
|
||||
gamepadIdentities[gamepadId] = newIdentity;
|
||||
for (auto &identity: inputIdentities)
|
||||
{
|
||||
// Device group must be matched, and gamepad id if it is a gamepad
|
||||
if (identity->deviceGroup == deviceGroup &&
|
||||
(deviceGroup != InputDeviceGroup::GAMEPAD ||
|
||||
identity->gamepadId == gamepadId))
|
||||
{
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
// No identity found, create new
|
||||
auto newIdentity = std::make_shared<InputIdentity>(deviceGroup, gamepadId);
|
||||
inputIdentities.insert(newIdentity);
|
||||
newInputIdentities.insert(newIdentity);
|
||||
return newIdentity;
|
||||
}
|
||||
|
||||
void InputMapper::deactivateGamepadIdentity(unsigned int gamepadId)
|
||||
void InputMapper::deactivateIdentity(const std::shared_ptr<InputIdentity> &identity)
|
||||
{
|
||||
auto gamepadIdentity = getInputIdentity(InputDeviceGroup::GAMEPAD, gamepadId);
|
||||
gamepadIdentity->isActive = false;
|
||||
LOG(INFO) << "Destroyed input identity [" << magic_enum::enum_name(identity->deviceGroup) << ", gamepad "
|
||||
<< identity->gamepadId
|
||||
<< "]";
|
||||
|
||||
identity->isActive = false;
|
||||
deprecatedInputIdentities.insert(identity);
|
||||
inputIdentities.erase(identity);
|
||||
}
|
||||
|
||||
std::shared_ptr<InputMapper> InputMapper::getInstance()
|
||||
|
@ -143,17 +140,13 @@ std::shared_ptr<InputMapper> InputMapper::getInstance()
|
|||
return singletonInstance;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<InputIdentity>> InputMapper::getAllInputIdentities()
|
||||
std::set<std::shared_ptr<InputIdentity>> InputMapper::getInputIdentities()
|
||||
{
|
||||
std::vector<std::shared_ptr<InputIdentity>> allIdentities;
|
||||
|
||||
allIdentities.push_back(allIdentity);
|
||||
allIdentities.push_back(keyboardIdentity);
|
||||
|
||||
for (auto const &[key, val]: gamepadIdentities)
|
||||
{
|
||||
allIdentities.push_back(val);
|
||||
}
|
||||
|
||||
return allIdentities;
|
||||
return inputIdentities;
|
||||
}
|
||||
|
||||
void InputMapper::updateIdentityEvents()
|
||||
{
|
||||
newInputIdentities.clear();
|
||||
deprecatedInputIdentities.clear();
|
||||
}
|
||||
|
|
|
@ -19,15 +19,20 @@ public:
|
|||
static std::shared_ptr<InputMapper> getInstance();
|
||||
|
||||
void processEvents();
|
||||
void updateIdentityEvents();
|
||||
|
||||
std::shared_ptr<InputIdentity> getInputIdentity(InputDeviceGroup deviceType, unsigned int gamepadId = 0);
|
||||
std::vector<std::shared_ptr<InputIdentity>> getAllInputIdentities();
|
||||
std::shared_ptr<InputIdentity> getInputIdentity(InputDeviceGroup deviceGroup, unsigned int gamepadId = 0);
|
||||
|
||||
std::set<std::shared_ptr<InputIdentity>> getInputIdentities();
|
||||
|
||||
public:
|
||||
std::set<std::shared_ptr<InputIdentity>> newInputIdentities;
|
||||
std::set<std::shared_ptr<InputIdentity>> deprecatedInputIdentities;
|
||||
|
||||
private:
|
||||
static inline std::shared_ptr<InputMapper> singletonInstance = nullptr;
|
||||
|
||||
std::shared_ptr<InputIdentity> keyboardIdentity;
|
||||
std::map<unsigned int, std::shared_ptr<InputIdentity>> gamepadIdentities;
|
||||
std::set<std::shared_ptr<InputIdentity>> inputIdentities;
|
||||
|
||||
void handleKeyPress(sf::Event::KeyEvent event);
|
||||
|
||||
|
@ -35,9 +40,7 @@ private:
|
|||
|
||||
void handleJoystickMovement(sf::Event::JoystickMoveEvent event);
|
||||
|
||||
void addGamepadIdentity(unsigned int gamepadId);
|
||||
|
||||
void deactivateGamepadIdentity(unsigned int gamepadId);
|
||||
void deactivateIdentity(const std::shared_ptr<InputIdentity>& identity);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define HOLESOME_KEY_FEATURES_HPP
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include "direction.h"
|
||||
#include "input_identity.h"
|
||||
#include "../../config.h"
|
||||
|
@ -13,23 +14,21 @@ struct KeyFeatures
|
|||
HardDirection hardDirection = HardDirection::NONE;
|
||||
InputDeviceGroup deviceGroup = InputDeviceGroup::UNKNOWN;
|
||||
|
||||
explicit KeyFeatures(sf::Keyboard::Key key);
|
||||
};
|
||||
|
||||
KeyFeatures::KeyFeatures(sf::Keyboard::Key key)
|
||||
{
|
||||
this->key = key;
|
||||
hardDirection = Direction::getKeyDirection(key);
|
||||
|
||||
// Determine device group
|
||||
for (const auto& groupKeys: KEY_GROUPS)
|
||||
explicit KeyFeatures(sf::Keyboard::Key key)
|
||||
{
|
||||
if (groupKeys.second.contains(key))
|
||||
this->key = key;
|
||||
hardDirection = Direction::getKeyDirection(key);
|
||||
|
||||
// Determine device group
|
||||
for (const auto &groupKeys: KEY_GROUPS)
|
||||
{
|
||||
deviceGroup = groupKeys.first;
|
||||
break;
|
||||
if (groupKeys.second.contains(key))
|
||||
{
|
||||
deviceGroup = groupKeys.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif //HOLESOME_KEY_FEATURES_HPP
|
||||
|
|
|
@ -15,6 +15,11 @@ sf::Vector2f Player::getTrackableSize() const
|
|||
|
||||
void Player::update(Game *game)
|
||||
{
|
||||
if (!input->isActive) {
|
||||
isActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto moveDirection = input->direction.asVector();
|
||||
auto moveDelta = moveDirection * 30.0f * FRAME_TIME.asSeconds();
|
||||
coordinates.move(moveDelta);
|
||||
|
|
12
src/game/player/player_spawner.cpp
Normal file
12
src/game/player/player_spawner.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "player_spawner.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
void PlayerSpawner::update(Game *game)
|
||||
{
|
||||
// Create player for new input identities
|
||||
for (auto &inputIdentity: InputMapper::getInstance()->newInputIdentities)
|
||||
{
|
||||
auto player = new Player(inputIdentity, sf::Color::Red, {0, 0});
|
||||
game->addGameObject(player);
|
||||
}
|
||||
}
|
14
src/game/player/player_spawner.hpp
Normal file
14
src/game/player/player_spawner.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef HOLESOME_PLAYER_SPAWNER_HPP
|
||||
#define HOLESOME_PLAYER_SPAWNER_HPP
|
||||
|
||||
|
||||
#include "../game_object.h"
|
||||
|
||||
class PlayerSpawner : public GameObject
|
||||
{
|
||||
public:
|
||||
void update(Game *game) override;
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_PLAYER_SPAWNER_HPP
|
11
src/main.cpp
11
src/main.cpp
|
@ -1,10 +1,9 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include "logging/easylogging++.h"
|
||||
#include "game/game_factory.hpp"
|
||||
#include "debug/grid_debug_layer.h"
|
||||
#include "game/world/world_view.h"
|
||||
#include "game/player/player.hpp"
|
||||
#include "game/player/player_spawner.hpp"
|
||||
|
||||
INITIALIZE_EASYLOGGINGPP
|
||||
|
||||
|
@ -14,12 +13,12 @@ int main(int argc, char *argv[])
|
|||
|
||||
auto game = GameFactory::createWindowed("Holesome");
|
||||
|
||||
auto player = new Player(sf::Color::Green, {0, 0});
|
||||
|
||||
game->addGameObject(new GridDebugLayer(0, 50, 0, 50));
|
||||
game->addGameObject(player);
|
||||
game->addGameObject(new Player(sf::Color::Blue, {0, 0}));
|
||||
game->addGameObject(new WorldView());
|
||||
game->addGameObject(new PlayerSpawner());
|
||||
|
||||
game->run();
|
||||
|
||||
InputMapper::getInstance().reset();
|
||||
game.reset();
|
||||
}
|
||||
|
|
1566
src/utilities/magic_enum.hpp
Normal file
1566
src/utilities/magic_enum.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue