HandmadeHero/docs/Day 013.md

97 lines
2.9 KiB
Markdown
Raw Normal View History

2023-09-17 18:20:11 -07:00
# Day 13
Started to lifting input, not happy about my abstraction to gamepad state in hindsight. Which is kinda lead by how Casey is doing it.
The reality of how input is actually done in the games; that I've worked on; is we don't abstract the gamepad.
We just make a layout per device we decide to support (Dualsense/shock, xinput, nintendo, etc) and then just see what device is mapped to what player. This allows us to have a tailored layout to the device. Doing otherwise usually leads to some discrepancy in the UX for that layout for the user.
Casey has no concept of a player nor a device beyond xinput for this engine (at least up to this point), which is most likely fine for the scope of this project.
For the purposes of my version of Handmade I will make 3 devices that could be mapped to a `Controller` struct: `Keyboard & Mouse`, `Dualsense`, and `XInput`.
This is to retain implementation Casey is already making while also natively supporting the Dualsense controller from sony which I personally perfer to use.
From the 3 layer abstraction (platform/engine/game):
Platform will deal with the raw polling (and most likely down the line have a thread dedicated to running it as fast as possible).
It will provide the engine layer the pad states in the following struct:
```cpp
struct InputState
{
ControllerState Controllers[4];
};
```
There can only be four controllers available at a time and are equivalnet to the input aspect of a local player in Unreal.
(Sort of)
Each controller can be assigned the following:
```cpp
struct ControllerState
{
KeyboardState* Keyboard;
MousesState* Mouse;
XInputPadState* XPad;
DualsensePadState* DSPad;
};
```
If any are null that means the controller has no assignment.
Each pad state is the latest state but the platform keeps a record of the previous frame's state to compare against.
Exmaple for Dualsense:
```cpp
struct DualsensePadState
{
struct
{
AnalogStick Left;
AnalogStick Right;
} Stick;
AnalogAxis L2;
AnalogAxis R2;
union {
DigitalBtn Btns[14];
struct {
struct {
DigitalBtn Up;
DigitalBtn Down;
DigitalBtn Left;
DigitalBtn Right;
} DPad;
DigitalBtn X;
DigitalBtn Circle;
DigitalBtn Square;
DigitalBtn Triangle;
DigitalBtn Share;
DigitalBtn Options;
DigitalBtn L1;
DigitalBtn R1;
};
};
b32 using_analog()
{
return true;
};
};
```
The game layer handles mapping an input state of a controller to an action binding.
Possible action binding when we get to that point:
```cpp
struct ActionBinding
{
String InternalName;
StringCached LocalizedName;
DigitalBtnBinding* BtnBinds;
AxisBinding* AxisBinds;
StickBinding* StickBinds;
MouseBinding* MouseBinds;
};
```