Zadanie 2 WIP3

This commit is contained in:
Michał Leśniak 2021-12-07 06:33:08 +01:00
parent 5b30c6ca45
commit 93afaeb4b3
7 changed files with 148 additions and 59 deletions

View File

@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>

View File

@ -2,18 +2,30 @@
#include "Controllers.h" #include "Controllers.h"
#include "KPlayerController.h" #include "KPlayerController.h"
namespace KapitanGame {; namespace KapitanGame {
;
enum class InputState : int { enum class InputState : int {
Pressed, Pressed,
Released, Released,
Hold Hold
}; };
struct KActionBind { struct KActionBind {
KActionBind(std::string name, const InputState expectedInputState, KPlayerController* controllerObject, const KPlayerCommand command, const Controllers controller) :
Name(std::move(name)), ExpectedInputState(expectedInputState), ControllerObject(controllerObject), Command(command), Controller(controller) {}
std::string Name; std::string Name;
InputState ExpectedInputState; InputState ExpectedInputState;
KPlayerController* ControllerObject; KPlayerController* ControllerObject;
KPlayerCommand Command; KPlayerCommand Command;
Controllers Controller; Controllers Controller;
}; };
struct KAxisBind
{
KAxisBind(std::string name, KPlayerController* controllerObject, const KPlayerAxisCommand command, const Controllers controller) :
Name(std::move(name)), ControllerObject(controllerObject), AxisCommand(command), Controller(controller) {}
std::string Name;
KPlayerController* ControllerObject;
KPlayerAxisCommand AxisCommand;
Controllers Controller;
};
} }

View File

@ -4,8 +4,8 @@
#include <SDL.h> #include <SDL.h>
namespace KapitanGame { namespace KapitanGame {
KInput::KInput() { KInput::KInput() : GamePadsCount(0), Initialized(false)
Initialized = false; {
} }
void KInput::Init() { void KInput::Init() {
@ -14,17 +14,17 @@ namespace KapitanGame {
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
const int nJoysticks = SDL_NumJoysticks(); const int nJoysticks = SDL_NumJoysticks();
GamepadsCount = 0; GamePadsCount = 0;
// Count how many controllers there are // Count how many controllers there are
for (int i = 0; i < nJoysticks; i++) for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i)) if (SDL_IsGameController(i))
GamepadsCount++; GamePadsCount++;
// If we have some controllers attached // If we have some controllers attached
if (GamepadsCount > 0) if (GamePadsCount > 0)
{ {
for (int i = 0; i < GamepadsCount; i++) for (int i = 0; i < GamePadsCount; i++)
{ {
// Open the controller and add it to our list // Open the controller and add it to our list
SDL_GameController* pad = SDL_GameControllerOpen(i); SDL_GameController* pad = SDL_GameControllerOpen(i);
@ -37,11 +37,11 @@ namespace KapitanGame {
} }
// Vectors are empty to begin with, this sets their size // Vectors are empty to begin with, this sets their size
ControllerInputs.resize(GamepadsCount); ControllerInputs.resize(GamePadsCount);
LastControllerInputs.resize(GamepadsCount); LastControllerInputs.resize(GamePadsCount);
// Set the status of the controllers to "nothing is happening" // Set the status of the controllers to "nothing is happening"
for (int i = 0; i < GamepadsCount; i++) { for (int i = 0; i < GamePadsCount; i++) {
for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) { for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
ControllerInputs[i].Axis[a] = 0; ControllerInputs[i].Axis[a] = 0;
LastControllerInputs[i].Axis[a] = 0; LastControllerInputs[i].Axis[a] = 0;
@ -59,10 +59,11 @@ namespace KapitanGame {
SDL_GameControllerClose(pad); SDL_GameControllerClose(pad);
} }
ConnectedControllers.clear(); ConnectedControllers.clear();
Actions.clear();
} }
void KInput::HandleInputPreEvents() { void KInput::HandleInputPreEvents() {
for (int i = 0; i < GamepadsCount; i++) { for (int i = 0; i < GamePadsCount; i++) {
for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) { for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
LastControllerInputs[i].Axis[a] = ControllerInputs[i].Axis[a]; LastControllerInputs[i].Axis[a] = ControllerInputs[i].Axis[a];
} }
@ -89,7 +90,7 @@ namespace KapitanGame {
// If a controller button is pressed // If a controller button is pressed
case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
// Cycle through the controllers // Cycle through the controllers
for (int i = 0; i < GamepadsCount; i++) { for (int i = 0; i < GamePadsCount; i++) {
// Looking for the button that was pressed // Looking for the button that was pressed
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) { if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
// So the relevant state can be updated // So the relevant state can be updated
@ -100,7 +101,7 @@ namespace KapitanGame {
// Do the same for releasing a button // Do the same for releasing a button
case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERBUTTONUP:
for (int i = 0; i < GamepadsCount; i++) { for (int i = 0; i < GamePadsCount; i++) {
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) { if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
ControllerInputs[i].Buttons[event.cbutton.button] = false; ControllerInputs[i].Buttons[event.cbutton.button] = false;
} }
@ -109,7 +110,7 @@ namespace KapitanGame {
// And something similar for axis motion // And something similar for axis motion
case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERAXISMOTION:
for (int i = 0; i < GamepadsCount; i++) { for (int i = 0; i < GamePadsCount; i++) {
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) { if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
ControllerInputs[i].Axis[event.caxis.axis] = event.caxis.value; ControllerInputs[i].Axis[event.caxis.axis] = event.caxis.value;
} }
@ -118,62 +119,94 @@ namespace KapitanGame {
} }
} }
void KInput::BindAction(std::string name, InputState expectedInputState, KPlayerController* controller, void KInput::BindAction(const std::string& name, InputState expectedInputState, KPlayerController* controllerObject,
KPlayerCommand command) { KPlayerCommand command, Controllers controller) {
Actions.emplace_back(name, expectedInputState, controller, command); Actions.emplace_back(name, expectedInputState, controllerObject, command, controller);
}
void KInput::BindAxis(const std::string& name, KPlayerController* controllerObject, KPlayerAxisCommand command, Controllers controller)
{
Axes.emplace_back(name, controllerObject, command, controller);
} }
bool KInput::CheckAction(const std::string& name, const InputState expectedInputState, Controllers controller) { bool KInput::CheckAction(const std::string& name, const InputState expectedInputState, Controllers controller) {
switch(expectedInputState) { const auto keyBind = KeyBinds[static_cast<int>(controller)].find(name);
const auto buttonBind = ButtonBinds[static_cast<int>(controller)].find(name);
switch (expectedInputState) {
case InputState::Pressed: case InputState::Pressed:
const auto keyBind = KeyBinds.find(name); if (keyBind != KeyBinds[static_cast<int>(controller)].end()) {
if(keyBind!=KeyBinds.end()) { if (IsKeyboardButtonPressed(keyBind->second)) {
if(IsKeyboardButtonPressed(keyBind->second)) {
return true; return true;
} }
} }
const auto buttonBind = ButtonBinds[controller].find(name);
if(buttonBind!=ButtonBinds[controller].end()) { if (buttonBind != ButtonBinds[static_cast<int>(controller)].end()) {
if(IsControllerButtonPressed(controller, buttonBind)) { if (IsControllerButtonPressed(controller, buttonBind->second)) {
return true;
}
}
return false;
case InputState::Released:
if (keyBind != KeyBinds[static_cast<int>(controller)].end()) {
if (IsKeyboardButtonReleased(keyBind->second)) {
return true;
}
}
if (buttonBind != ButtonBinds[static_cast<int>(controller)].end()) {
if (IsControllerButtonReleased(controller, buttonBind->second)) {
return true;
}
}
return false;
case InputState::Hold:
if (keyBind != KeyBinds[static_cast<int>(controller)].end()) {
if (IsKeyboardButtonHeld(keyBind->second)) {
return true;
}
}
if (buttonBind != ButtonBinds[static_cast<int>(controller)].end()) {
if (IsControllerButtonHeld(controller, buttonBind->second)) {
return true; return true;
} }
} }
return false; return false;
case InputState::Released: break;
case InputState::Hold: break;
default: return false;
} }
return false;
} }
void KInput::ProcessActions() { void KInput::ProcessActions() {
for(auto action : Actions) { for (auto &action : Actions) {
if(CheckAction(action.Name, action.ExpectedInputState, action.Controller)) { if (CheckAction(action.Name, action.ExpectedInputState, action.Controller)) {
//(action.ControllerObject->*action.Command)();
std::invoke(action.Command, action.ControllerObject); std::invoke(action.Command, action.ControllerObject);
} }
} }
} }
bool KInput::IsControllerButtonPressed(const Controllers controllerId, const SDL_GameControllerButton button) { bool KInput::IsControllerButtonPressed(const Controllers controllerId, const SDL_GameControllerButton button) const
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false; {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamePadsCount - 1)) return false;
return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && !LastControllerInputs[static_cast<int>(controllerId)].Buttons[button]; return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && !LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
} }
bool KInput::IsControllerButtonReleased(const Controllers controllerId, const SDL_GameControllerButton button) { bool KInput::IsControllerButtonReleased(const Controllers controllerId, const SDL_GameControllerButton button) const
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false; {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamePadsCount - 1)) return false;
return !ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button]; return !ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
} }
bool KInput::IsControllerButtonHeld(const Controllers controllerId, const SDL_GameControllerButton button) { bool KInput::IsControllerButtonHeld(const Controllers controllerId, const SDL_GameControllerButton button) const
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false; {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamePadsCount - 1)) return false;
return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button]; return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
} }
float KInput::GetControllerAxis(const Controllers controllerId, const SDL_GameControllerAxis axis) { float KInput::GetControllerAxis(const Controllers controllerId, const SDL_GameControllerAxis axis) const
if (controllerId <Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return 0.0; {
if (controllerId <Controllers::Controller1 || controllerId > static_cast<Controllers>(GamePadsCount - 1)) return 0.0;
const int value = ControllerInputs[static_cast<int>(controllerId)].Axis[axis]; const int value = ControllerInputs[static_cast<int>(controllerId)].Axis[axis];
if (std::abs(value) < Constants::JOYSTICK_DEAD_ZONE) return 0.0; if (std::abs(value) < Constants::JOYSTICK_DEAD_ZONE) return 0.0;
@ -181,19 +214,22 @@ namespace KapitanGame {
return static_cast<float>(value) / 32768.0f; return static_cast<float>(value) / 32768.0f;
} }
bool KInput::IsKeyboardButtonPressed(const Uint8 scanCode) { bool KInput::IsKeyboardButtonPressed(const Uint8 scanCode) const
{
if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size()) if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size())
return false; return false;
return KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode]; return KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode];
} }
bool KInput::IsKeyboardButtonReleased(const Uint8 scanCode) { bool KInput::IsKeyboardButtonReleased(const Uint8 scanCode) const
{
if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size()) if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size())
return false; return false;
return !KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode]; return !KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode];
} }
bool KInput::IsKeyboardButtonHeld(const Uint8 scanCode) { bool KInput::IsKeyboardButtonHeld(const Uint8 scanCode) const
{
if (scanCode > KeyboardInputs.size()) if (scanCode > KeyboardInputs.size())
return false; return false;
return KeyboardInputs[scanCode]; return KeyboardInputs[scanCode];

View File

@ -14,9 +14,19 @@ namespace KapitanGame {
std::vector<Uint8> KeyboardInputs; std::vector<Uint8> KeyboardInputs;
std::vector<Uint8> LastKeyboardInputs; std::vector<Uint8> LastKeyboardInputs;
std::vector<KActionBind> Actions; std::vector<KActionBind> Actions;
std::unordered_map<std::string, Uint8> KeyBinds; std::vector<KAxisBind> Axes;
int GamepadsCount; std::unordered_map<std::string, Uint8> KeyBinds[static_cast<int>(Controllers::Controller4) + 1];
std::unordered_map<std::string, SDL_GameControllerButton> ButtonBinds[static_cast<int>(Controllers::Controller4) + 1];
int GamePadsCount;
bool Initialized; bool Initialized;
bool IsControllerButtonPressed(Controllers controllerId, SDL_GameControllerButton button) const;
bool IsControllerButtonReleased(Controllers controllerId, SDL_GameControllerButton button) const;
bool IsControllerButtonHeld(Controllers controllerId, SDL_GameControllerButton button) const;
float GetControllerAxis(Controllers controllerId, SDL_GameControllerAxis axis) const;
bool IsKeyboardButtonHeld(Uint8 scanCode) const;
bool IsKeyboardButtonPressed(Uint8 scanCode) const;
bool IsKeyboardButtonReleased(Uint8 scanCode) const;
public: public:
KInput(); KInput();
void Init(); void Init();
@ -24,16 +34,11 @@ namespace KapitanGame {
void HandleInputPreEvents(); void HandleInputPreEvents();
void HandleInputPostEvents(); void HandleInputPostEvents();
void HandleEvent(const SDL_Event& event); void HandleEvent(const SDL_Event& event);
void BindAction(std::string name, InputState expectedInputState, KPlayerController* controller, KPlayerCommand command); void BindAction(const std::string& name, InputState expectedInputState, KPlayerController* controllerObject, KPlayerCommand command, Controllers
controller);
void BindAxis(const std::string& name, KPlayerController* controllerObject, KPlayerAxisCommand command, Controllers controller);
bool CheckAction(const std::string& name, InputState expectedInputState, Controllers controller); bool CheckAction(const std::string& name, InputState expectedInputState, Controllers controller);
void ProcessActions(); void ProcessActions();
bool IsControllerButtonPressed(Controllers controllerId, SDL_GameControllerButton button);
bool IsControllerButtonReleased(Controllers controllerId, SDL_GameControllerButton button);
bool IsControllerButtonHeld(Controllers controllerId, SDL_GameControllerButton button);
float GetControllerAxis(Controllers controllerId, SDL_GameControllerAxis axis);
bool IsKeyboardButtonHeld(Uint8 scanCode);
bool IsKeyboardButtonPressed(Uint8 scanCode);
bool IsKeyboardButtonReleased(Uint8 scanCode);
}; };
} }

View File

@ -1,5 +1,27 @@
#include "KPlayerController.h" #include "KPlayerController.h"
#include "KInput.h"
namespace KapitanGame { namespace KapitanGame {
void KPlayerController::SetupInputBindings(KInput& input)
{
input.BindAxis("MoveYAxis", this, &KPlayerController::MoveYAxis, Controller);
input.BindAxis("MoveXAxis", this, &KPlayerController::MoveXAxis, Controller);
}
void KPlayerController::MoveYAxis(const float axis)
{
Input.Y += axis;
}
void KPlayerController::MoveXAxis(const float axis)
{
Input.X += axis;
}
void KPlayerController::Update(float deltaTime)
{
Input.Normalize();
Pawn->AddMovementInput(Input);
Input = KVector2D(0.f, 0.f);
}
} }

View File

@ -1,15 +1,29 @@
#pragma once #pragma once
#include "Controllers.h"
#include "KShape.h" #include "KShape.h"
#include "KVector2d.h" #include "KVector2d.h"
namespace KapitanGame { namespace KapitanGame {
class KInput;
class KPlayerController class KPlayerController
{ {
public:
explicit KPlayerController(const Controllers controller) : Input(0.f, 0.f), Controller(controller)
{
}
void SetupInputBindings(KInput& input);
void MoveYAxis(float axis);
void MoveXAxis(float axis);
void Update(float deltaTime);
private: private:
KVector2D Input; KVector2D Input;
KShape Shape; Controllers Controller;
KPawn Pawn;
}; };
typedef void (KPlayerController::* KPlayerCommand)(); typedef void (KPlayerController::* KPlayerCommand)();
typedef void (KPlayerController::* KPlayerAxisCommand)(float input);
} }

View File

@ -63,7 +63,7 @@ namespace KapitanGame {
void Normalize() { void Normalize() {
const float l = Length(); const float l = Length();
if (l > 0) { if (l > 1.f) {
(*this) *= 1 / l; (*this) *= 1 / l;
} }
} }