diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 6ab887b..7935ea8 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -3,7 +3,7 @@ # # Add source to this project's executable. -add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp" "csharp/stream.cpp" "platform/gdevicemanager-dx.cpp" "platform/vertexinput-dx.cpp" "platform/shader-dx.cpp" "platform/rasterizerstate-dx.cpp" "platform/vertexbuffer-dx.cpp" "platform/indexbuffer-dx.cpp" "common/matrix.cpp" "platform/constbuffer-dx.cpp" "platform/databuffer-dx.cpp" "platform/samplerstate-dx.cpp" "platform/spritebatch-dx.cpp" "platform/spritefont-dx.cpp" "platform/depthstencilstate-dx.cpp" "platform/keyboard-dx.cpp" "platform/mouse-dx.cpp") +add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp" "csharp/stream.cpp" "platform/gdevicemanager-dx.cpp" "platform/vertexinput-dx.cpp" "platform/shader-dx.cpp" "platform/rasterizerstate-dx.cpp" "platform/vertexbuffer-dx.cpp" "platform/indexbuffer-dx.cpp" "common/matrix.cpp" "platform/constbuffer-dx.cpp" "platform/databuffer-dx.cpp" "platform/samplerstate-dx.cpp" "platform/spritebatch-dx.cpp" "platform/spritefont-dx.cpp" "platform/depthstencilstate-dx.cpp" "platform/keyboard-dx.cpp" "platform/mouse-dx.cpp" "platform/gamepad-dx.cpp") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET xna PROPERTY CXX_STANDARD 20) diff --git a/framework/common/vectors.hpp b/framework/common/vectors.hpp index 80da2f1..3688745 100644 --- a/framework/common/vectors.hpp +++ b/framework/common/vectors.hpp @@ -14,6 +14,28 @@ namespace xna { constexpr bool operator==(const Vector2& other) const { return X == other.X && Y == other.Y; } + + static constexpr Vector2 One() { + return Vector2(1, 1); + } + + static constexpr Vector2 Min(Vector2 const& value1, Vector2 const& value2) { + Vector2 vector2; + vector2.X = value1.X < value2.X ? value1.X : value2.X; + vector2.Y = value1.Y < value2.Y ? value1.Y : value2.Y; + return vector2; + } + + static constexpr Vector2 Max(Vector2 const& value1, Vector2 const& value2) { + Vector2 vector2; + vector2.X = value1.X > value2.X ? value1.X : value2.X; + vector2.Y = value1.Y > value2.Y ? value1.Y : value2.Y; + return vector2; + } + + constexpr Vector2 operator-() const { + return Vector2(-X, -Y); + } }; struct Vector3 { diff --git a/framework/enums.hpp b/framework/enums.hpp index 9e64fd5..bde7867 100644 --- a/framework/enums.hpp +++ b/framework/enums.hpp @@ -32,6 +32,34 @@ namespace xna { using BlendOperation = BlendFunction; + enum class Buttons { + A = 4096, // 0x00001000 + B = 8192, // 0x00002000 + X = 16384, // 0x00004000 + Y = 32768, // 0x00008000 + Back = 32, // 0x00000020 + Start = 16, // 0x00000010 + DPadUp = 1, + DPadDown = 2, + DPadLeft = 4, + DPadRight = 8, + LeftShoulder = 256, // 0x00000100 + RightShoulder = 512, // 0x00000200 + LeftStick = 64, // 0x00000040 + RightStick = 128, // 0x00000080 + BigButton = 2048, // 0x00000800 + LeftThumbstickLeft = 2097152, // 0x00200000 + LeftThumbstickRight = 1073741824, // 0x40000000 + LeftThumbstickDown = 536870912, // 0x20000000 + LeftThumbstickUp = 268435456, // 0x10000000 + RightThumbstickLeft = 134217728, // 0x08000000 + RightThumbstickRight = 67108864, // 0x04000000 + RightThumbstickDown = 33554432, // 0x02000000 + RightThumbstickUp = 16777216, // 0x01000000 + LeftTrigger = 8388608, // 0x00800000 + RightTrigger = 4194304, // 0x00400000 + }; + enum class ButtonState { Released, @@ -88,6 +116,27 @@ namespace xna { WireFrame, }; + enum class GamePadCapabilitiesType + { + Unknown = 0, + Gamepad, + Wheel, + ArdaceStick, + FlightStick, + DancePAd, + Guitar, + GuitarAlternate, + DrumKit, + GuitarBass = 11, + ArcadePad = 19, + }; + + enum class GamePadDeadZone { + IndependentAxes, + Circular, + None, + }; + enum class GraphicsProfile { Reach, HiDef @@ -261,6 +310,14 @@ namespace xna { Down, }; + enum class PlayerIndex + { + One, + Two, + Three, + Four, + }; + enum class PresentInterval { Default, One, diff --git a/framework/forward.hpp b/framework/forward.hpp index 6c217b2..2d39bb9 100644 --- a/framework/forward.hpp +++ b/framework/forward.hpp @@ -133,6 +133,20 @@ namespace xna { using PViewport = std::shared_ptr; //Input + class GamePad; + using PGamePad = std::shared_ptr; + struct GamePadTriggers; + using PGamePagTriggers = std::shared_ptr; + struct GamePadThumbSticks; + using PGamePadThumbSticks = std::shared_ptr; + struct GamePadDPad; + using PGamePadDPad = std::shared_ptr; + struct GamePadCapabilities; + using PGamePadCapabilities = std::shared_ptr; + struct GamePadButtons; + using PGamePadButtons = std::shared_ptr; + struct GamePadState; + using PGamePadState = std::shared_ptr; struct KeyboardState; using PKeyboardState = std::shared_ptr; struct MouseState; diff --git a/framework/input/gamepad.hpp b/framework/input/gamepad.hpp new file mode 100644 index 0000000..875c711 --- /dev/null +++ b/framework/input/gamepad.hpp @@ -0,0 +1,71 @@ +#ifndef XNA_INPUT_GAMEPAD_HPP +#define XNA_INPUT_GAMEPAD_HPP + +#include "../default.hpp" +#include "../common/vectors.hpp" + +namespace xna { + struct IGamePadTriggers { + public: + virtual float Left() const = 0; + virtual float Right() const = 0; + }; + + struct IGamePadThumbSticks { + public: + virtual Vector2 Left() const = 0; + virtual Vector2 Right() const = 0; + }; + + struct IGamePadDPad { + virtual ButtonState Up() const = 0; + virtual ButtonState Down() const = 0; + virtual ButtonState Right() const = 0; + virtual ButtonState Left() const = 0; + }; + + struct IGamePadButtons { + virtual ButtonState A() const = 0; + virtual ButtonState B() const = 0; + virtual ButtonState Back() const = 0; + virtual ButtonState X() const = 0; + virtual ButtonState Y() const = 0; + virtual ButtonState Start() const = 0; + virtual ButtonState LeftShoulder() const = 0; + virtual ButtonState LeftStick() const = 0; + virtual ButtonState RightShoulder() const = 0; + virtual ButtonState RightStick() const = 0; + virtual ButtonState BigButton() const = 0; + }; + + struct IGamePadCapabilities { + virtual GamePadCapabilitiesType GamePadType() const = 0; + virtual bool IsConnected() const = 0; + virtual String Id() const = 0; + virtual Ushort Vid() const = 0; + virtual Ushort Pid() const = 0; + }; + + struct IGamePadState { + virtual GamePadButtons Buttons() const = 0; + virtual GamePadDPad DPad() const = 0; + virtual bool IsConnected() const = 0; + virtual Ulong PacketNumber() const = 0; + virtual GamePadThumbSticks ThumbSticks() = 0; + virtual GamePadTriggers Triggers() = 0; + virtual bool IsButtonDown(xna::Buttons button) = 0; + virtual bool IsButtonUp(xna::Buttons button) = 0; + }; + + class IGamePad { + public: + virtual ~IGamePad(){} + + static GamePadState GetState(PlayerIndex index); + static GamePadState GetState(PlayerIndex index, GamePadDeadZone deadZone); + static GamePadCapabilities GetCapabilities(PlayerIndex index); + static bool SetVibration(PlayerIndex index, float leftMotor, float rightMotor, float leftTrigger = 0, float rightTrigger = 0); + }; +} + +#endif \ No newline at end of file diff --git a/framework/platform/gamepad-dx.cpp b/framework/platform/gamepad-dx.cpp new file mode 100644 index 0000000..7747809 --- /dev/null +++ b/framework/platform/gamepad-dx.cpp @@ -0,0 +1,6 @@ +#include "gamepad-dx.hpp" +#include + +namespace xna { + +} \ No newline at end of file diff --git a/framework/platform/gamepad-dx.hpp b/framework/platform/gamepad-dx.hpp new file mode 100644 index 0000000..f758d3d --- /dev/null +++ b/framework/platform/gamepad-dx.hpp @@ -0,0 +1,380 @@ +#ifndef XNA_PLATFORM_GAMEPAD_DX_HPP +#define XNA_PLATFORM_GAMEPAD_DX_HPP + +#include "../input/gamepad.hpp" +#include + +namespace xna { + struct GamePadTriggers: public IGamePadTriggers { + constexpr GamePadTriggers() = default; + + constexpr GamePadTriggers(float left, float right) : _left(left), _right(right) { + clamp(); + } + + constexpr GamePadTriggers(DirectX::GamePad::Triggers const& trigger) { + _left = trigger.left; + _right = trigger.right; + clamp(); + } + + virtual constexpr float Left() const override { + return _left; + } + + virtual constexpr float Right() const override { + return _right; + } + + constexpr bool operator==(const GamePadTriggers& other) const { + return _left == other._left && _right == other._right; + } + + public: + float _left{ 0 }; + float _right{ 0 }; + + private: + void constexpr clamp() { + _left = _left < 1.0F ? _left : 1.0F; + _left = _left > 0.0F ? _left : 0.0F; + _right = _right < 1.0F ? _right : 1.0F; + _right = _right > 0.0F ? _right : 0.0F; + } + }; + + struct GamePadThumbSticks : public IGamePadThumbSticks { + constexpr GamePadThumbSticks() = default; + + constexpr GamePadThumbSticks(Vector2 left, Vector2 right) : _left(left), _right(right) { + clamp(); + } + + constexpr GamePadThumbSticks(DirectX::GamePad::ThumbSticks const& sticks) { + _left = Vector2(sticks.leftX, sticks.leftY); + _right = Vector2(sticks.rightX, sticks.rightY); + clamp(); + } + + virtual constexpr Vector2 Left() const override { + return _left; + } + + virtual constexpr Vector2 Right() const override { + return _right; + } + + constexpr bool operator==(const GamePadThumbSticks& other) const { + return _left == other._left && _right == other._right; + } + + private: + Vector2 _left{}; + Vector2 _right{}; + + private: + constexpr void clamp() { + _left = Vector2::Min(_left, Vector2::One()); + _left = Vector2::Max(_left, -Vector2::One()); + _right = Vector2::Min(_right, Vector2::One()); + _right = Vector2::Max(_right, -Vector2::One()); + } + }; + + struct GamePadDPad : public IGamePadDPad { + constexpr GamePadDPad() = default; + + constexpr GamePadDPad(const ButtonState& up, const ButtonState& down, + const ButtonState& left, const ButtonState& right) + : _up(up), _right(right), _down(down), _left(left) { + } + + constexpr GamePadDPad(DirectX::GamePad::DPad dpad) { + _up = static_cast(dpad.up); + _right = static_cast(dpad.right); + _down = static_cast(dpad.down); + _left = static_cast(dpad.left); + } + + virtual constexpr ButtonState Up() const override { + return _up; + } + + virtual constexpr ButtonState Down() const override { + return _down; + } + + virtual constexpr ButtonState Right() const override { + return _right; + } + + virtual constexpr ButtonState Left() const override { + return _left; + } + + private: + ButtonState _up{}; + ButtonState _right{}; + ButtonState _down{}; + ButtonState _left{}; + }; + + struct GamePadButtons : public IGamePadButtons { + constexpr GamePadButtons() = default; + + constexpr GamePadButtons(Buttons buttons) { + _a = static_cast((static_cast(buttons) & static_cast(Buttons::A))) == Buttons::A ? ButtonState::Pressed : ButtonState::Released; + _b = static_cast((static_cast(buttons) & static_cast(Buttons::B))) == Buttons::B ? ButtonState::Pressed : ButtonState::Released; + _x = static_cast((static_cast(buttons) & static_cast(Buttons::X))) == Buttons::X ? ButtonState::Pressed : ButtonState::Released; + _y = static_cast((static_cast(buttons) & static_cast(Buttons::Y))) == Buttons::Y ? ButtonState::Pressed : ButtonState::Released; + _start = static_cast((static_cast(buttons) & static_cast(Buttons::Start))) == Buttons::Start ? ButtonState::Pressed : ButtonState::Released; + _back = static_cast((static_cast(buttons) & static_cast(Buttons::Back))) == Buttons::Back ? ButtonState::Pressed : ButtonState::Released; + _leftStick = static_cast((static_cast(buttons) & static_cast(Buttons::LeftStick))) == Buttons::LeftStick ? ButtonState::Pressed : ButtonState::Released; + _rightStick = static_cast((static_cast(buttons) & static_cast(Buttons::RightStick))) == Buttons::RightStick ? ButtonState::Pressed : ButtonState::Released; + _leftShoulder = static_cast((static_cast(buttons) & static_cast(Buttons::LeftShoulder))) == Buttons::LeftShoulder ? ButtonState::Pressed : ButtonState::Released; + _rightShoulder = static_cast((static_cast(buttons) & static_cast(Buttons::RightShoulder))) == Buttons::RightShoulder ? ButtonState::Pressed : ButtonState::Released; + _bigButton = static_cast((static_cast(buttons) & static_cast(Buttons::BigButton))) == Buttons::BigButton ? ButtonState::Pressed : ButtonState::Released; + } + + constexpr GamePadButtons(DirectX::GamePad::Buttons const& buttons) { + _a = static_cast(buttons.a); + _b = static_cast(buttons.b); + _x = static_cast(buttons.x); + _y = static_cast(buttons.y); + _leftStick = static_cast(buttons.leftStick); + _rightStick = static_cast(buttons.rightStick); + _leftShoulder = static_cast(buttons.leftShoulder); + _rightShoulder = static_cast(buttons.rightShoulder); + _back = static_cast(buttons.back); + _start = static_cast(buttons.start); + _bigButton = static_cast(buttons.view); + } + + virtual constexpr ButtonState A() const override { + return _a; + } + + virtual constexpr ButtonState B() const override { + return _b; + } + + virtual constexpr ButtonState Back() const override{ + return _back; + } + + virtual constexpr ButtonState X() const override { + return _x; + } + + virtual constexpr ButtonState Y() const override { + return _y; + } + + virtual constexpr ButtonState Start() const override { + return _start; + } + + virtual constexpr ButtonState LeftShoulder() const override { + return _leftShoulder; + } + + virtual constexpr ButtonState LeftStick() const override { + return _leftStick; + } + + virtual constexpr ButtonState RightShoulder() const override { + return _rightShoulder; + } + + virtual constexpr ButtonState RightStick() const override { + return _rightStick; + } + + virtual constexpr ButtonState BigButton() const override { + return _bigButton; + } + + private: + ButtonState _a{}; + ButtonState _b{}; + ButtonState _x{}; + ButtonState _y{}; + ButtonState _leftStick{}; + ButtonState _rightStick{}; + ButtonState _leftShoulder{}; + ButtonState _rightShoulder{}; + ButtonState _back{}; + ButtonState _start{}; + ButtonState _bigButton{}; + }; + + struct GamePadCapabilities : public IGamePadCapabilities { + constexpr GamePadCapabilities() = default; + + constexpr GamePadCapabilities(DirectX::GamePad::Capabilities const& capabilities) { + _type = static_cast(capabilities.gamepadType); + _connected = capabilities.connected; + _id = capabilities.id; + _vid = capabilities.vid; + _pid = capabilities.pid; + } + + virtual constexpr GamePadCapabilitiesType GamePadType() const override { + return _type; + } + + virtual constexpr bool IsConnected() const override { + return _connected; + } + + virtual String Id() const override { + return XnaHToString(_id); + } + + virtual constexpr Ushort Vid() const override { + return _vid; + } + + virtual constexpr Ushort Pid() const override { + return _pid; + } + + private: + GamePadCapabilitiesType _type{}; + bool _connected{ false }; + std::wstring _id{ 0 }; + Ushort _vid{ 0 }; + Ushort _pid{ 0 }; + }; + + struct GamePadState : public IGamePadState { + constexpr GamePadState() = default; + + constexpr GamePadState(DirectX::GamePad::State const& state) : _dxState(state){ + } + + virtual constexpr GamePadButtons Buttons() const override { + const auto buttons = _dxState.buttons; + return GamePadButtons(buttons); + }; + + virtual constexpr GamePadDPad DPad() const override { + const auto dpad = _dxState.dpad; + return GamePadDPad(dpad); + }; + + inline virtual bool IsConnected() const override{ + return _dxState.IsConnected(); + }; + + virtual constexpr Ulong PacketNumber() const override { + return _dxState.packet; + }; + + virtual constexpr GamePadThumbSticks ThumbSticks() override{ + const auto thumbs = _dxState.thumbSticks; + return GamePadThumbSticks(thumbs); + }; + + virtual GamePadTriggers Triggers() override { + const auto triggers = _dxState.triggers; + return GamePadTriggers(triggers); + }; + + virtual bool IsButtonDown(xna::Buttons button) override { + switch (button) + { + case xna::Buttons::A: + return _dxState.IsAPressed(); + case xna::Buttons::B: + return _dxState.IsBPressed(); + case xna::Buttons::X: + return _dxState.IsXPressed(); + case xna::Buttons::Y: + return _dxState.IsYPressed(); + case xna::Buttons::Back: + return _dxState.IsBackPressed(); + case xna::Buttons::Start: + return _dxState.IsStartPressed(); + case xna::Buttons::DPadUp: + return _dxState.IsDPadUpPressed(); + case xna::Buttons::DPadDown: + return _dxState.IsDPadDownPressed(); + case xna::Buttons::DPadLeft: + return _dxState.IsDPadLeftPressed(); + case xna::Buttons::DPadRight: + return _dxState.IsDPadRightPressed(); + case xna::Buttons::LeftShoulder: + return _dxState.IsLeftShoulderPressed(); + case xna::Buttons::RightShoulder: + return _dxState.IsRightShoulderPressed(); + case xna::Buttons::LeftStick: + return _dxState.IsLeftStickPressed(); + case xna::Buttons::RightStick: + return _dxState.IsRightStickPressed(); + case xna::Buttons::BigButton: + return _dxState.IsViewPressed(); + case xna::Buttons::LeftThumbstickLeft: + return _dxState.IsLeftThumbStickLeft(); + case xna::Buttons::LeftThumbstickRight: + return _dxState.IsLeftThumbStickRight(); + case xna::Buttons::LeftThumbstickDown: + return _dxState.IsLeftThumbStickDown(); + case xna::Buttons::LeftThumbstickUp: + return _dxState.IsLeftThumbStickUp(); + case xna::Buttons::RightThumbstickLeft: + return _dxState.IsRightThumbStickLeft(); + case xna::Buttons::RightThumbstickRight: + return _dxState.IsLeftThumbStickRight(); + case xna::Buttons::RightThumbstickDown: + return _dxState.IsRightThumbStickDown(); + case xna::Buttons::RightThumbstickUp: + return _dxState.IsRightThumbStickUp(); + case xna::Buttons::LeftTrigger: + return _dxState.IsLeftTriggerPressed(); + case xna::Buttons::RightTrigger: + return _dxState.IsRightTriggerPressed(); + default: + return false; + } + }; + + virtual bool IsButtonUp(xna::Buttons button) override { + return !IsButtonDown(button); + }; + + public: + DirectX::GamePad::State _dxState{}; + }; + + class GamePad : public IGamePad { + public: + inline static sptr _dxGamePad = New(); + }; + + inline GamePadState IGamePad::GetState(PlayerIndex index) { + const auto state = GamePad::_dxGamePad->GetState( + static_cast(index) + ); + return GamePadState(state); + } + + inline GamePadState IGamePad::GetState(PlayerIndex index, GamePadDeadZone deadZone) { + const auto state = GamePad::_dxGamePad->GetState( + static_cast(index), + static_cast(deadZone) + ); + return GamePadState(state); + } + + inline GamePadCapabilities IGamePad::GetCapabilities(PlayerIndex index) { + const auto capabilities = GamePad::_dxGamePad->GetCapabilities(static_cast(index)); + return GamePadCapabilities(capabilities); + } + + inline bool IGamePad::SetVibration(PlayerIndex index, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger) { + return GamePad::_dxGamePad->SetVibration(static_cast(index), leftMotor, rightMotor, leftTrigger, rightTrigger); + } +} + +#endif \ No newline at end of file diff --git a/framework/xna.cpp b/framework/xna.cpp index b82c4c9..ea10de7 100644 --- a/framework/xna.cpp +++ b/framework/xna.cpp @@ -35,29 +35,12 @@ public: } void Update(GameTime const& gameTime) override { - - const auto state = Keyboard::GetState(); - - if (state.IsKeyDown(Keys::Right)) { - position.X += 1 * gameTime.ElapsedGameTime.TotalMilliseconds(); - } - if (state.IsKeyDown(Keys::Left)) { - position.X -= 1 * gameTime.ElapsedGameTime.TotalMilliseconds(); - } - if (state.IsKeyDown(Keys::Up)) { - position.Y -= 1 * gameTime.ElapsedGameTime.TotalMilliseconds(); - } - if (state.IsKeyDown(Keys::Down)) { - position.Y += 1 * gameTime.ElapsedGameTime.TotalMilliseconds(); - } + auto state = GamePad::GetState(PlayerIndex::One); - - oldState = currentState; - currentState = Mouse::GetState(); - - if (currentState.LeftButton == ButtonState::Pressed && oldState.LeftButton == ButtonState::Released) { - points.push_back(Vector2(currentState.X, currentState.Y)); - } + if (state.IsButtonDown(Buttons::DPadRight)) + position.X += 1.0F * gameTime.ElapsedGameTime.TotalMilliseconds(); + if (state.IsButtonDown(Buttons::DPadLeft)) + position.X -= 1.0F * gameTime.ElapsedGameTime.TotalMilliseconds(); Game::Update(gameTime); } @@ -66,11 +49,7 @@ public: _graphicsDevice->Clear(Colors::CornflowerBlue); spriteBatch->Begin(); - // spriteBatch->Draw(*texture, position, nullptr, Colors::White, 0, { 0,0 }, 0.5F, SpriteEffects::None, 0); - for (size_t i = 0; i < points.size(); ++i) { - spriteBatch->Draw(*texture, points[i], nullptr, Colors::White, 0, {0,0}, 0.5F, SpriteEffects::None, 0); - } - + spriteBatch->Draw(*texture, position, nullptr, Colors::White, 0, { 0,0 }, 0.5F, SpriteEffects::None, 0); spriteBatch->End(); Game::Draw(gameTime); diff --git a/framework/xna.h b/framework/xna.h index 76967f8..c89ba24 100644 --- a/framework/xna.h +++ b/framework/xna.h @@ -17,5 +17,6 @@ #include "common/color.hpp" #include "platform/keyboard-dx.hpp" #include "platform/mouse-dx.hpp" +#include "platform/gamepad-dx.hpp" // TODO: Reference additional headers your program requires here.