입력 처리 시스템 구조
개요
게임 내 입력을 관리하는 입력 처리 시스템은 CInputManager와 CInputComponent로 구성되며, 키보드/마우스 입력 상태와 이를 바인딩하는 구조체를 통해 동작합니다. 각 오브젝트는 자신에게 필요한 입력을 바인딩하고, 발생한 입력에 따라 연결된 콜백 함수를 실행합니다.
이 시스템의 주요 장점은 여러 콜백 함수에 대해 키보드와 마우스의 다양한 입력 조건(입력값 + 입력상태)을 조합해 처리할 수 있어, 입력 방식을 유연하게 설계하고 확장할 수 있다는 점입니다.
입력 시스템 작동 구조 | 자세히 보기
/Block-References/01_Game-Projcets/Self-Made-Game-Framework/Source/Input-System-Architecture-Diagram_Kor.png)
- 실행 순서:
Initialization→Update - 본 설계도는 입력 매니저(CInputManager)와 입력 컴포넌트(CInputComponent) 두 클래스 간의 연계성을 간단히 보여줍니다.
InputUtils.h 구성 요소 및 설명 | 저장소 보기
키보드와 마우스의 입력값, 입력상태, 이벤트 바인딩을 관리하며, 게임 내 입력 처리를 위해 필요한 공통 자료형과 구조체들을 정의하는 유틸 항목입니다.
1. EKeyAction 열거형 클래스
enum class EKeyAction : unsigned char { PRESS, HOLD, RELEASE, MAX };
- 키 입력타입을 구분하기 위한 열거형 클래스입니다.
2. FKeyState 구조체
struct FKeyState { bool Press = false; bool Hold = false; bool Release = false; };
- 단일 키의 현재 입력상태를 저장하는 구조체입니다.
3. FBindFunction 구조체
struct FBindFunction { void* obj = nullptr; std::function<void()> func; };
- 오브젝트 포인터와 함수(콜백)을 한 쌍으로 보관하는 구조체입니다.
4. FBinder 구조체
struct FBinder { std::vector<std::pair<SDL_Scancode, EKeyAction>> Keys; std::vector<std::pair<Uint8, EKeyAction>> Mouses; std::vector<FBindFunction*> Functions; };
- 키보드와 마우스 입력을 조합하고, 해당 입력에 대한 동작(콜백 함수)을 함께 묶어주는 구조체입니다.
클래스 목록 및 설명
1. CInputManager 클래스 | 저장소 보기
class CInputManager { friend class CEngine; private: CInputManager(); ~CInputManager(); private: static CInputManager* mInst; // for keyboard std::unordered_map<SDL_Scancode, FKeyState> mKeys; // for mouse std::unordered_map<Uint8, FKeyState> mMouses; FVector2D mMousePos = FVector2D::ZERO; private: bool Init(); bool RegisterKey(SDL_Scancode keyCode); bool RegisterMouse(Uint8 button); void Update(); void UpdateInputState(); void HandleInputState(bool& press, bool& hold, bool& release, bool isPressed); public: bool GetKeyState(SDL_Scancode keyCode, EKeyAction action); bool GetMouseButtonState(Uint8 button, EKeyAction action); const FVector2D& GetMousePos() const { return mMousePos; } public: static CInputManager* GetInst() { if (!mInst) mInst = new CInputManager; return mInst; } static void DestroyInst() { SAFE_DELETE(mInst); } };
- 역할:
- 등록된 키보드와 마우스 입력상태를 관리하는 싱글톤입니다.
- 매 프레임마다 등록된 키보드와 마우스 입력을 감지하고, 입력상태를 업데이트합니다.
- 핵심 변수들:
mKeys:- 등록된 키보드 키들의 입력값과 입력상태를 저장합니다.
mMouses:- 등록된 마우스 버튼들의 입력값과 입력상태를 저장합니다.
- 핵심 함수들:
- bool RegisterKey(SDL_Scancode keyCode):
- 사용할 키보드 키를
mKeys에 등록합니다.
- 사용할 키보드 키를
- bool RegisterMouse(Uint8 button):
- 사용할 마우스 버튼을
mMouses에 등록합니다.
- 사용할 마우스 버튼을
- void UpdateInputState():
- 매 프레임마다 등록된
mKeys와mMouses의 입력상태를 감지합니다.
- 매 프레임마다 등록된
- void HandleInputState(bool& press, bool& hold, bool& release, bool isPressed):
UpdateInputState()에서 호출됩니다.- 등록된
mKeys와mMouses의 입력상태를 업데이트합니다.
- bool GetKeyState(SDL_Scancode keyCode, EKeyAction action):
- 특정 키보드 키의 현재 입력상태를 확인합니다.
- bool GetMouseButtonState(Uint8 button, EKeyAction action):
- 특정 마우스 버튼의 현재 입력상태를 확인합니다.
- bool RegisterKey(SDL_Scancode keyCode):
2. CInputComponent 클래스 | 저장소 보기
class CInputComponent : public CComponent { public: CInputComponent(); virtual ~CInputComponent(); private: std::unordered_map<std::string, FBinder*> mBinders; private: virtual void Update(float deltaTime) final; virtual void Release() final; public: template <typename T> void AddFuncToBinder(const std::string& key, T* obj, void(T::* func)()); void AddFuncToBinder(const std::string& key, void* obj, const std::function<void()>& func); void DeleteFuncFromBinder(const std::string& key, void* obj); void AddInputToBinder(const std::string& key, SDL_Scancode keyCode, EKeyAction action); void AddInputToBinder(const std::string& key, Uint8 button, EKeyAction action); };
- 역할:
- 오브젝트 단위로
mBinders에 입력 조건(입력값, 입력상태)과 콜백 함수를 등록하며, 입력 조건과 일치하면 콜백 함수를 실행합니다.
- 오브젝트 단위로
- 핵심 변수:
mBinders:- 문자열 키를 기준으로
FBinder를 저장하며, 각 바인더에 입력 조건(입력값 + 입력상태)하고 콜백 함수를 보관합니다.
- 문자열 키를 기준으로
- 핵심 함수들:
- virtual void Update(float deltaTime):
mBinders에 등록된 입력 조건을CInputManager와 비교해, 일치하면 콜백 함수를 실행합니다.
- void AddFunctionToBinder(…) & void AddFunctionToBinder<T>(…):
- 문자열 키를 기준으로
mBinders에 콜백 함수를 등록합니다.
- 문자열 키를 기준으로
- void DeleteFunctionFromBinder(const std::string& key, void* obj):
- 문자열 키를 기준으로
mBinders에 등록된 콜백 함수를 제거합니다.
- 문자열 키를 기준으로
- void AddInputToBinder(…):
- 문자열 키를 기준으로
mBinders에 입력 조건를 등록합니다.
- 문자열 키를 기준으로
- virtual void Update(float deltaTime):
맺는 말
이번 구현을 통해 입력 매니저(CInputManager)와 입력 컴포넌트(CInputComponent)를 분리하여 관리하면, 사용자 정의 키 매핑이나 다양한 입력 패턴, 복잡한 입력 조건도 깔끔하게 처리할 수 있다는 점을 배웠습니다. 또한, 유연하고 확장성 있게 설계하는 관점에서 입력 시스템을 구성하는 방법을 깊이 이해하게 되었습니다.