Input Identities added and basic controller support
This commit is contained in:
parent
b7fca7d07a
commit
ddea927ce0
13 changed files with 175 additions and 57 deletions
|
@ -20,8 +20,8 @@ set(SOURCES
|
|||
src/main.cpp
|
||||
src/game/game_object.cpp
|
||||
src/game/game_object.h
|
||||
src/game/game.cpp
|
||||
src/game/game.h
|
||||
src/game/game.cpp
|
||||
src/logging/easylogging++.cc
|
||||
src/logging/easylogging++.h
|
||||
src/coordinates/coordinate_transformer.cpp
|
||||
|
@ -38,13 +38,20 @@ set(SOURCES
|
|||
src/config.h
|
||||
src/debug/grid_debug_layer.cpp
|
||||
src/debug/grid_debug_layer.h
|
||||
src/game/input/input_mapper.cpp
|
||||
src/game/input/input_mapper.h
|
||||
src/game/input/input_mapper.cpp
|
||||
src/game/input/direction.h
|
||||
src/game/input/direction.cpp
|
||||
src/game/player/player.cpp
|
||||
src/game/player/player.hpp
|
||||
src/game/input/game_inputs.hpp src/game/world/world_view.cpp src/game/world/world_view.h src/utilities/smart_list.cpp src/utilities/smart_list.h src/utilities/vector_utils.hpp src/game/world/ITrackable.h src/game/input/input_identity.h)
|
||||
src/game/input/game_inputs.hpp
|
||||
src/game/world/world_view.cpp
|
||||
src/game/world/world_view.h
|
||||
src/utilities/smart_list.cpp
|
||||
src/utilities/smart_list.h
|
||||
src/utilities/vector_utils.hpp
|
||||
src/game/world/ITrackable.h
|
||||
src/game/input/input_identity.h)
|
||||
|
||||
set(PHYSICS_00_SOURCES
|
||||
src/prototypes/physics_00.cpp)
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
|
||||
#define VIEW_RUBBER_FOLLOW_SPEED 0.5f
|
||||
|
||||
// Inputs
|
||||
#define JOYSTICK_DEADZONE 0.1f
|
||||
|
||||
// Directions
|
||||
#define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f
|
||||
|
||||
// DEBUG
|
||||
|
||||
#define DB_ISOPLANE_CORNER_RADIUS 2
|
||||
|
||||
#endif //HOLESOME_CONFIG_H
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
Game::Game(std::shared_ptr<sf::RenderWindow> window) : window(std::move(window)),
|
||||
gameObjects()
|
||||
{
|
||||
InputMapper::setGame(this);
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
|
@ -26,14 +25,14 @@ void Game::run()
|
|||
while (window->isOpen())
|
||||
{
|
||||
|
||||
InputMapper::processEvents();
|
||||
InputMapper::getInstance()->processEvents();
|
||||
TimeSinceLastUpdate += clock.restart();
|
||||
while (TimeSinceLastUpdate >= FRAME_TIME)
|
||||
{
|
||||
TimeSinceLastUpdate -= FRAME_TIME;
|
||||
|
||||
update();
|
||||
InputMapper::processEvents();
|
||||
InputMapper::getInstance()->processEvents();
|
||||
}
|
||||
drawFrame();
|
||||
}
|
||||
|
@ -75,3 +74,23 @@ void Game::update()
|
|||
gameObject->lateUpdate(this);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> Game::getInstance()
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (singletonInstance != nullptr) {
|
||||
throw std::runtime_error("Game instance has already been initialized.");
|
||||
}
|
||||
|
||||
singletonInstance = std::make_shared<Game>(window);
|
||||
|
||||
return singletonInstance;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ class ActionController;
|
|||
class Game
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<Game> constructInstance(const std::shared_ptr<sf::RenderWindow>& window);
|
||||
static std::shared_ptr<Game> getInstance();
|
||||
explicit Game(std::shared_ptr<sf::RenderWindow> window);
|
||||
|
||||
~Game();
|
||||
|
@ -27,6 +29,7 @@ public:
|
|||
|
||||
std::shared_ptr<sf::RenderWindow> window;
|
||||
private:
|
||||
static inline std::shared_ptr<Game> singletonInstance = nullptr;
|
||||
std::vector<GameObject *> gameObjects;
|
||||
|
||||
void drawFrame();
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Created by max on 28.04.23.
|
||||
//
|
||||
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include "game_factory.hpp"
|
||||
#include "../config.h"
|
||||
|
@ -12,7 +8,7 @@ std::shared_ptr<Game> GameFactory::createWindowed(const std::string &title, int
|
|||
sf::Style::Default,
|
||||
getAdditionalSettings());
|
||||
applyAdditionalWindowConfig(window.get());
|
||||
return std::make_shared<Game>(window);
|
||||
return Game::constructInstance(window);
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> GameFactory::createFullscreen(const std::string &title) {
|
||||
|
@ -31,7 +27,7 @@ std::shared_ptr<Game> GameFactory::createFullscreen(const std::string &title) {
|
|||
getAdditionalSettings());
|
||||
applyAdditionalWindowConfig(window.get());
|
||||
|
||||
return std::make_shared<Game>(window);
|
||||
return Game::constructInstance(window);
|
||||
}
|
||||
|
||||
sf::ContextSettings GameFactory::getAdditionalSettings() {
|
||||
|
|
|
@ -152,3 +152,15 @@ void Direction::set(sf::Vector2f direction)
|
|||
summedDirections = HardDirection::NONE;
|
||||
this->directionVector = direction;
|
||||
}
|
||||
|
||||
void Direction::setX(float value)
|
||||
{
|
||||
sf::Vector2f newDirection = {value, directionVector.y};
|
||||
set(newDirection);
|
||||
}
|
||||
|
||||
void Direction::setY(float value)
|
||||
{
|
||||
sf::Vector2f newDirection = {directionVector.x, value};
|
||||
set(newDirection);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
void remove(HardDirection direction);
|
||||
void set(HardDirection direction);
|
||||
void set(sf::Vector2f direction);
|
||||
void setX(float value);
|
||||
void setY(float value);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
|
|
@ -19,8 +19,9 @@ struct InputIdentity
|
|||
unsigned int inputOrder = 0;
|
||||
bool isActive = true;
|
||||
|
||||
explicit InputIdentity(InputDeviceType type) {
|
||||
explicit InputIdentity(InputDeviceType type, unsigned int gamepad = 0) {
|
||||
deviceType = type;
|
||||
gamepadId = gamepad;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#include "input_mapper.h"
|
||||
|
||||
|
||||
void InputMapper::setGame(Game *game)
|
||||
InputMapper::InputMapper()
|
||||
{
|
||||
InputMapper::game = game;
|
||||
|
||||
// Initialize identities
|
||||
allIdentity = std::make_shared<InputIdentity>(InputDeviceType::ALL);
|
||||
keyboardIdentity = std::make_shared<InputIdentity>(InputDeviceType::KEYBOARD);
|
||||
|
@ -15,7 +13,7 @@ void InputMapper::setGame(Game *game)
|
|||
void InputMapper::processEvents()
|
||||
{
|
||||
sf::Event event{};
|
||||
while (game->window->pollEvent(event))
|
||||
while (Game::getInstance()->window->pollEvent(event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
|
@ -26,13 +24,19 @@ void InputMapper::processEvents()
|
|||
handleKeyRelease(event.key);
|
||||
break;
|
||||
case sf::Event::Closed:
|
||||
game->exit();
|
||||
Game::getInstance()->exit();
|
||||
break;
|
||||
case sf::Event::Resized:
|
||||
break;
|
||||
case sf::Event::JoystickMoved:
|
||||
handleJoystickMovement(event.joystickMove);
|
||||
break;
|
||||
case sf::Event::JoystickConnected:
|
||||
addGamepadIdentity(event.joystickConnect.joystickId);
|
||||
break;
|
||||
case sf::Event::JoystickDisconnected:
|
||||
deactivateGamepadIdentity(event.joystickConnect.joystickId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -44,7 +48,7 @@ void InputMapper::handleKeyPress(sf::Event::KeyEvent event)
|
|||
// Close game on Escape or Q in DEV Mode
|
||||
if (DEVELOPER_MODE && (event.code == sf::Keyboard::Escape || event.code == sf::Keyboard::Q))
|
||||
{
|
||||
game->exit();
|
||||
Game::getInstance()->exit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,37 +56,44 @@ void InputMapper::handleKeyPress(sf::Event::KeyEvent event)
|
|||
auto direction = Direction::getKeyDirection(event.code);
|
||||
if (direction != HardDirection::NONE)
|
||||
{
|
||||
inputDirectionBuffer.push_back(direction);
|
||||
getInputIdentity(InputDeviceType::KEYBOARD)->direction.add(direction);
|
||||
}
|
||||
}
|
||||
|
||||
Direction InputMapper::getInputDirection()
|
||||
{
|
||||
HardDirection direction = HardDirection::NONE;
|
||||
|
||||
for (HardDirection directionPart: inputDirectionBuffer)
|
||||
{
|
||||
direction = static_cast<HardDirection>(direction | directionPart);
|
||||
}
|
||||
|
||||
return Direction(direction);
|
||||
}
|
||||
|
||||
void InputMapper::handleKeyRelease(sf::Event::KeyEvent event)
|
||||
{
|
||||
// Handle directionVector
|
||||
auto direction = Direction::getKeyDirection(event.code);
|
||||
if (direction != HardDirection::NONE)
|
||||
{
|
||||
// Remove directionVector from buffer
|
||||
inputDirectionBuffer.erase(std::remove(inputDirectionBuffer.begin(), inputDirectionBuffer.end(), direction),
|
||||
inputDirectionBuffer.end());
|
||||
getInputIdentity(InputDeviceType::KEYBOARD)->direction.remove(direction);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::handleJoystickMovement(sf::Event::JoystickMoveEvent event)
|
||||
{
|
||||
event.joystickId;
|
||||
auto gamepadIdentity = getInputIdentity(InputDeviceType::GAMEPAD, event.joystickId);
|
||||
|
||||
auto value = event.position / 100.f;
|
||||
auto axis = event.axis;
|
||||
|
||||
// Handle deadzone and joystick drift
|
||||
if (value > -JOYSTICK_DEADZONE && value < JOYSTICK_DEADZONE)
|
||||
{
|
||||
value = 0.f;
|
||||
}
|
||||
|
||||
if (axis == sf::Joystick::Axis::X ||
|
||||
axis == sf::Joystick::Axis::R ||
|
||||
axis == sf::Joystick::Axis::PovX)
|
||||
{
|
||||
gamepadIdentity->direction.setX(value);
|
||||
} else if (axis == sf::Joystick::Axis::Y ||
|
||||
axis == sf::Joystick::Axis::U ||
|
||||
axis == sf::Joystick::Axis::PovY)
|
||||
{
|
||||
gamepadIdentity->direction.setY(value);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceType deviceType, unsigned int gamepadId)
|
||||
|
@ -92,12 +103,58 @@ std::shared_ptr<InputIdentity> InputMapper::getInputIdentity(InputDeviceType dev
|
|||
case InputDeviceType::KEYBOARD:
|
||||
return keyboardIdentity;
|
||||
case InputDeviceType::GAMEPAD:
|
||||
if (gamepadIdentities.find(gamepadId) == gamepadIdentities.end())
|
||||
if (InputMapper::gamepadIdentities.contains(gamepadId))
|
||||
{
|
||||
throw std::invalid_argument("Gamepad with id " + std::to_string(gamepadId) + " not found.");
|
||||
// Create if it does not exist yet
|
||||
InputMapper::addGamepadIdentity(gamepadId);
|
||||
}
|
||||
return gamepadIdentities[gamepadId];
|
||||
return InputMapper::gamepadIdentities[gamepadId];
|
||||
default:
|
||||
return allIdentity;
|
||||
return InputMapper::allIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::addGamepadIdentity(unsigned int gamepadId)
|
||||
{
|
||||
// Exists already?
|
||||
if (InputMapper::gamepadIdentities.contains(gamepadId))
|
||||
{
|
||||
InputMapper::gamepadIdentities[gamepadId]->isActive = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Does not exist yet, create new
|
||||
auto newIdentity = std::make_shared<InputIdentity>(InputDeviceType::GAMEPAD, gamepadId);
|
||||
InputMapper::gamepadIdentities[gamepadId] = newIdentity;
|
||||
}
|
||||
|
||||
void InputMapper::deactivateGamepadIdentity(unsigned int gamepadId)
|
||||
{
|
||||
auto gamepadIdentity = getInputIdentity(InputDeviceType::GAMEPAD, gamepadId);
|
||||
gamepadIdentity->isActive = false;
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<InputMapper> InputMapper::getInstance()
|
||||
{
|
||||
if (singletonInstance == nullptr) {
|
||||
singletonInstance = std::make_shared<InputMapper>();
|
||||
}
|
||||
|
||||
return singletonInstance;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<InputIdentity>> InputMapper::getAllInputIdentities()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -7,34 +7,37 @@
|
|||
#include "direction.h"
|
||||
#include "input_identity.h"
|
||||
|
||||
class Game;
|
||||
|
||||
/**
|
||||
* Maps the inputs to actions.
|
||||
*/
|
||||
class InputMapper
|
||||
{
|
||||
|
||||
public:
|
||||
static void setGame(Game *game);
|
||||
InputMapper();
|
||||
static std::shared_ptr<InputMapper> getInstance();
|
||||
|
||||
static void processEvents();
|
||||
void processEvents();
|
||||
|
||||
static std::shared_ptr<InputIdentity> getInputIdentity(InputDeviceType deviceType, unsigned int gamepadId = 0);
|
||||
std::shared_ptr<InputIdentity> getInputIdentity(InputDeviceType deviceType, unsigned int gamepadId = 0);
|
||||
std::vector<std::shared_ptr<InputIdentity>> getAllInputIdentities();
|
||||
|
||||
private:
|
||||
static inline Game *game = nullptr;
|
||||
static inline std::shared_ptr<InputMapper> singletonInstance = nullptr;
|
||||
|
||||
static std::shared_ptr<InputIdentity> allIdentity;
|
||||
static std::shared_ptr<InputIdentity> keyboardIdentity;
|
||||
static std::map<unsigned int, std::shared_ptr<InputIdentity>> gamepadIdentities;
|
||||
std::shared_ptr<InputIdentity> allIdentity;
|
||||
std::shared_ptr<InputIdentity> keyboardIdentity;
|
||||
std::map<unsigned int, std::shared_ptr<InputIdentity>> gamepadIdentities;
|
||||
|
||||
static inline std::vector<HardDirection> inputDirectionBuffer = std::vector<HardDirection>();
|
||||
void handleKeyPress(sf::Event::KeyEvent event);
|
||||
|
||||
static void handleKeyPress(sf::Event::KeyEvent event);
|
||||
void handleKeyRelease(sf::Event::KeyEvent event);
|
||||
|
||||
static void handleKeyRelease(sf::Event::KeyEvent event);
|
||||
void handleJoystickMovement(sf::Event::JoystickMoveEvent event);
|
||||
|
||||
static void handleJoystickMovement(sf::Event::JoystickMoveEvent event);
|
||||
void addGamepadIdentity(unsigned int gamepadId);
|
||||
|
||||
void deactivateGamepadIdentity(unsigned int gamepadId);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,23 @@ sf::Vector2f Player::getTrackableSize() const
|
|||
|
||||
void Player::update(Game *game)
|
||||
{
|
||||
auto moveDirection = InputMapper::getInputDirection().asVector();
|
||||
// Get gamepad input
|
||||
std::shared_ptr<InputIdentity> gamepadIdentity = nullptr;
|
||||
for (auto inputIdentity: InputMapper::getInstance()->getAllInputIdentities())
|
||||
{
|
||||
if (inputIdentity->deviceType == InputDeviceType::GAMEPAD)
|
||||
{
|
||||
gamepadIdentity = inputIdentity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gamepadIdentity == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// auto moveDirection = InputMapper::getInstance()->getInputIdentity(InputDeviceType::KEYBOARD)->direction.asVector();
|
||||
auto moveDirection = gamepadIdentity->direction.asScreenVector();
|
||||
auto moveDelta = moveDirection * 30.0f * FRAME_TIME.asSeconds();
|
||||
coordinates.move(moveDelta);
|
||||
circle->coordinates.set(coordinates);
|
||||
|
|
|
@ -71,7 +71,7 @@ sf::Vector2f WorldView::getCenter() const
|
|||
|
||||
void WorldView::followTarget()
|
||||
{
|
||||
|
||||
// TODO
|
||||
auto closestPositionInDynamic = getClosestPositionInArea(dynamicFollowArea);
|
||||
marker->coordinates.set(IsometricCoordinates(closestPositionInDynamic));
|
||||
return;
|
||||
|
|
|
@ -3924,7 +3924,7 @@ class VersionInfo : base::StaticClass {
|
|||
/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint();
|
||||
/// @see el::base::PerformanceTracker
|
||||
/// @see el::base::PerformanceTracker::checkpoint
|
||||
// Note: Do not surround this definition with null macro because of obj instance
|
||||
// Note: Do not surround this definition with null macro because of obj singletonInstance
|
||||
#define TIMED_SCOPE_IF(obj, blockname, condition) el::base::type::PerformanceTrackerPtr obj( condition ? \
|
||||
new el::base::PerformanceTracker(blockname, ELPP_MIN_UNIT) : nullptr )
|
||||
#define TIMED_SCOPE(obj, blockname) TIMED_SCOPE_IF(obj, blockname, true)
|
||||
|
|
Loading…
Reference in a new issue