Initial commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shweetandClaude Opus 5.5 committed 2026-11-08 01:30:33 -05:00
commit 2007fb7edc
200 files changed
+27710

No files matched your search

+198
View File
@@ -0,0 +1,198 @@
#pragma once
#include "common.h"
#include <vector>
struct Game;
struct SDL_Gamepad;
struct SDL_Joystick;
constexpr int KEY_COUNT = 512;
constexpr int TYPED_LENGTH = 64;
enum Control
{
CONTROL_LEFT,
CONTROL_RIGHT,
CONTROL_UP,
CONTROL_DOWN,
CONTROL_JUMP,
CONTROL_ATTACK,
CONTROL_CHARGE,
CONTROL_LEVEL_DOWN,
CONTROL_LEVEL_UP,
CONTROL_READY,
CONTROL_NEXT_WEAPON,
CONTROL_PREVIOUS_WEAPON,
CONTROL_MENU,
CONTROL_CHAT,
CONTROL_COUNT
};
// What each control is called in the Controls settings, and its key in settings.txt.
constexpr const char* CONTROL_NAMES[CONTROL_COUNT] = {
"Move Left", "Move Right", "Up", "Down", "Jump", "Attack", "Charge", "Level Down", "Level Up", "Ready",
"Next Weapon", "Previous Weapon", "Menu", "Chat"};
constexpr const char* CONTROL_KEYS[CONTROL_COUNT] = {
"left", "right", "up", "down", "jump", "attack", "charge", "level_down", "level_up", "ready",
"next_weapon", "previous_weapon", "menu", "chat"};
// One tick of a fighter's intent, from the keyboard, a gamepad or a bot. Buttons holds a bit per Control held this
// tick, cursor is the world point it aims at, slot is a weapon slot to switch to (-1 for none), and edit a change to
// its loadout or settings made from the menu this tick (see edit_encode, -1 for none).
struct Controls
{
Vec2 cursor;
Uint16 buttons = 0;
int edit = -1;
int slot = -1;
};
constexpr int EDIT_QUEUE = 16;
enum MouseButton
{
MOUSE_LEFT,
MOUSE_RIGHT,
MOUSE_MIDDLE,
MOUSE_COUNT
};
// A control's two bindings: one on the keyboard side (a key's scancode, or past the keys a mouse button or wheel
// direction) and one on the gamepad (a button, or past the buttons a stick or trigger direction). -1 is unbound.
struct Binding
{
int key = -1;
int pad = -1;
};
constexpr int PAD_MAX = 4;
constexpr int DEVICE_NONE = -1;
constexpr int DEVICE_KEYBOARD = 0;
constexpr int DEVICE_COUNT = PAD_MAX + 1;
constexpr int PAD_AXES = 6;
// Menu navigation directions, as bits.
enum Nav
{
NAV_UP = 1,
NAV_DOWN = 2,
NAV_LEFT = 4,
NAV_RIGHT = 8
};
// One step of the test gamepad script: at time seconds, pad's button (or axis) index goes to value.
struct PadEvent
{
float time = 0;
float value = 0;
int index = 0;
int pad = 0;
bool isAxis = false;
};
// One way of playing: the keyboard and mouse, or a gamepad. Previous is what its controls were last tick (for
// presses), stick the last way its right stick leaned, pick a Choice pick and ready a Ready click waiting for the next
// tick, presses the gamepad buttons pressed since the last poll (for menus) and taps those pressed since the last
// tick (held for it, however quick). Nav is the menu directions pressed since the last poll (D-pad, left stick or
// arrow keys, repeating while held), held the D-pad and left stick directions held, and repeat when they next repeat.
// Down and axes are the gamepad's buttons held and sticks and triggers (-1 to 1) as of the last poll, which bindings
// read so a replayed tick sees the gamepad as it was.
struct Device
{
SDL_Gamepad* pad = nullptr;
Vec2 stick = {1, 0};
Uint64 repeat = 0;
float axes[PAD_AXES] = {};
Uint32 down = 0;
Uint32 presses = 0;
Uint32 taps = 0;
int held = 0;
int nav = 0;
// Edits waiting to go out, one per tick, oldest first.
int edits[EDIT_QUEUE] = {};
int editCount = 0;
bool previous[CONTROL_COUNT] = {};
bool isAiming = false;
bool isClaimed = false;
bool isReady = false;
};
// Per-frame keyboard, mouse and gamepad state. Edges persist until a tick consumes them with tick_end. Menus read it
// directly, and gameplay only sees it turned into Controls through the bindings, per device: the keyboard and mouse
// (which also take any gamepad no one has claimed), or a claimed gamepad. Mouse is in canvas pixels. Widgets drawn
// every frame use the per-frame parts instead: whether the left button was clicked since the last poll, and while a
// text field has the keyboard, the text typed, backspaces and whether Enter or Escape ended it, and scroll, the wheel
// turned since the last poll (wheel is the same for ticks, kept until one ends), whether the mouse moved, and whether
// Enter was pressed outside typing (confirming in menus). Play request is the menu's Play button, waiting for the next
// tick to start the game. Clicks, keys and buttons come from
// press events too, so one let go quicker than a frame or tick still counts. Typing hides every key from the game. F
// toggles fullscreen whenever nothing is being typed. A gamepad's right stick aims while it's in use (for the
// keyboard's device, until the mouse moves). Capture listens for the next input on one side of a control's binding
// (Escape cancels), which then doesn't count as pressed. RPG_TEST_PADS names a script of virtual gamepad presses for
// testing ("seconds pad button|axis index value" a line).
class Input
{
public:
Binding bindings[CONTROL_COUNT];
Device devices[DEVICE_COUNT];
Vec2 mouse;
char typed[TYPED_LENGTH] = {};
float scroll = 0;
float wheel = 0;
int captureControl = -1;
int erases = 0;
int slotPressed = -1;
bool isBindingChanged = false;
bool isCaptureGamepad = false;
bool isClicked = false;
bool isConfirmed = false;
bool isMouseMoved = false;
bool isPlayRequested = false;
bool isRightClicked = false;
bool isQuit = false;
bool isSubmitted = false;
// Whether the text being typed was given up on (Escape) rather than entered.
bool isCancelled = false;
Input();
void poll(Game& game);
void tick_end();
void bindings_reset();
Controls controls_get(int device, Vec2 camera, Vec2 origin, int slot, bool isMenuOpen);
void edit_send(int device, int edit);
Vec2 aim_get(int device, Vec2 camera, Vec2 origin);
bool is_down(int scancode);
bool is_pressed(int scancode);
bool is_control_pressed(Control control);
bool is_key_control_pressed(Control control);
bool is_pad_pressed(int device, int button);
Uint32 pad_presses_get(int device);
bool is_pad_tapped(int button);
int nav_get(int device);
bool is_mouse_down(MouseButton button);
bool is_mouse_pressed(MouseButton button);
bool is_mouse_released(MouseButton button);
void binding_name_get(int binding, bool isGamepad, char* text, int size);
bool is_control_down(int device, Control control);
private:
std::vector<PadEvent> script;
std::vector<SDL_Joystick*> virtualPads;
bool buttons[MOUSE_COUNT] = {};
bool buttonsPrevious[MOUSE_COUNT] = {};
bool keys[KEY_COUNT] = {};
bool keysPrevious[KEY_COUNT] = {};
bool keysTapped[KEY_COUNT] = {};
bool presses[MOUSE_COUNT] = {};
bool pressesUnticked[MOUSE_COUNT] = {};
bool isSwallowed = false;
bool wasTyping = false;
bool is_key_binding_down(int binding);
bool is_pad_binding_down(Device& device, int binding);
void capture_take(int binding);
void script_load();
void script_play(Game& game);
};