#include "Player.hpp" #include "AppConfig.hpp" #include "ScopeGuard.hpp" #include "Utils.hpp" #include #include // Keep the same number as # of fields in `struct {}` in PlayerKeyBinds constexpr int kPlayerKeyBindCount = 4; // Here be dragons: this treats consecutive fiels as an array, technically UB std::span PlayerKeyBinds::GetKeyArray() { return { &keyLeft, kPlayerKeyBindCount }; } std::span PlayerKeyBinds::GetKeyStatusArray() { return { &pressedLeft, kPlayerKeyBindCount }; } Player::Player(GameWorld* world, int id) : GameObject(world) , mId{ id } { } void Player::Awaken() { LoadFromFile(); } void Player::Resleep() { SaveToFile(); } void Player::Update() { if (keybinds.pressedLeft) { } if (keybinds.pressedRight) { } // TODO jump controller // TODO attack controller } void Player::HandleKeyInput(int key, int action) { bool pressed; if (action == GLFW_PRESS) { pressed = true; } else if (action == GLFW_REPEAT) { return; } else /* action == GLFW_RELEASE */ { pressed = false; } for (int i = 0; i < kPlayerKeyBindCount; ++i) { int kbKey = keybinds.GetKeyArray()[i]; bool& kbStatus = keybinds.GetKeyStatusArray()[i]; if (kbKey == key) { kbStatus = pressed; break; } } } #pragma macro_push("PLAYERKEYBINDS_DO_IO") #undef PLAYERKEYBINDS_DO_IO #define PLAYERKEYBINDS_DO_IO(function, fieldPrefix) \ function(file, "left=%d\n", fieldPrefix keybinds.keyLeft); \ function(file, "right=%d\n", fieldPrefix keybinds.keyRight); \ function(file, "jump=%d\n", fieldPrefix keybinds.keyJump); \ function(file, "attack=%d\n", fieldPrefix keybinds.keyAttack); static FILE* OpenPlayerConfigFile(Player* player, Utils::IoMode mode) { char path[512]; snprintf(path, sizeof(path), "%s/player%d.txt", AppConfig::dataDir.c_str(), player->GetId()); return Utils::OpenCstdioFile(path, mode); } bool Player::LoadFromFile() { auto file = OpenPlayerConfigFile(this, Utils::Read); if (!file) return false; DEFER { fclose(file); }; // TODO input validation PLAYERKEYBINDS_DO_IO(fscanf, &); return true; } bool Player::SaveToFile() { auto file = OpenPlayerConfigFile(this, Utils::WriteTruncate); if (!file) return false; DEFER { fclose(file); }; PLAYERKEYBINDS_DO_IO(fprintf, ); return true; } #pragma macro_pop("PLAYERKEYBINDS_DO_IO")