commit 7634722c16a478ca9783077f19eb55d4cef3b4cc Author: devZoGok Date: Sat Dec 4 12:48:21 2021 +0200 initial commit diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6a3c5b3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/glfw"] + path = external/glfw + url = https://github.com/glfw/glfw diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a5b1def --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.2) +project(gameBase) + +set(CMAKE_BUILD_TYPE Debug) +cmake_policy(SET CMP0015 NEW) + +set(states abstractAppState.cpp) +set(core inputManager.cpp mapping.h stateManager.cpp) +set(util util.cpp) + +add_library(gameBase ${states} ${core} ${util}) + +set(GLFW_DIR external/glfw) +set(LIB_NAME gameBase) + +add_subdirectory(${GLFW_DIR}) +set(GLFW_LIB_DIR build/${GLFW_DIR}/src) +target_include_directories(${LIB_NAME} PUBLIC ${GLFW_DIR}/include/GLFW) +target_link_directories(${LIB_NAME} PUBLIC ${GLFW_LIB_DIR}) + +target_link_libraries(gameBase glfw) diff --git a/abstractAppState.cpp b/abstractAppState.cpp new file mode 100644 index 0000000..0e27678 --- /dev/null +++ b/abstractAppState.cpp @@ -0,0 +1,47 @@ +#include "abstractAppState.h" +#include "util.h" +#include "mapping.h" + +using namespace std; + +namespace gameBase { + void AbstractAppState::onAttached(){ + attached = true; + + for(int i = 0; i < bindingsLines.size(); i++){ + int semicolon; + + for(int j = 0; j < bindingsLines[i].length(); j++) + if(bindingsLines[i].c_str()[j] == ':') + semicolon = j; + + Mapping::BindType type = (Mapping::BindType)atoi(bindingsLines[i].substr(semicolon + 1, 1).c_str()); + bool action = atoi(bindingsLines[i].substr(semicolon + 3, 1).c_str()); + int trigger = atoi(bindingsLines[i].substr(semicolon + 5, string::npos).c_str()); + + Mapping *m = new Mapping; + m->bind = (Mapping::Bind)(3 + i); + m->type = type; + m->action = action; + m->trigger = trigger; + mappings.push_back(m); + } + } + + void AbstractAppState::onDettached(){ + attached = false; + } + + void AbstractAppState::update(){} + + void AbstractAppState::removeMapping(Mapping::Bind bind){ + int id = -1; + + for(int i = 0; i < mappings.size(); i++) + if(mappings[i]->bind == bind) + id = i; + + if(id != -1) + mappings.erase(mappings.begin() + id); + } +} diff --git a/abstractAppState.h b/abstractAppState.h new file mode 100644 index 0000000..e3a62f3 --- /dev/null +++ b/abstractAppState.h @@ -0,0 +1,37 @@ +#ifndef ABSTRACT_APP_STATE_H +#define ABSTRACT_APP_STATE_H + +#include "mapping.h" + +#include +#include + +namespace gameBase { + class AbstractAppState{ + public: + virtual void update(); + virtual void onAttached(); + virtual void onDettached(); + inline int getType(){return type;} + inline Mapping* getMapping(int id){return mappings[id];} + inline std::vector& getMappings(){return mappings;} + inline int getNumMappings(){return mappings.size();} + inline bool isAttached(){return attached;} + void removeMapping(Mapping::Bind); + virtual void onAction(Mapping::Bind,bool){} + virtual void onAnalog(Mapping::Bind,float){} + virtual void onRawKeyButton(short){} + virtual void onRawMouseButton(short){} + virtual void onRawJoystickAxis(short,float){} + virtual void onRawJoystickButton(short){} + protected: + AbstractAppState(){} + ~AbstractAppState(){} + std::vector mappings; + std::vector bindingsLines; + int type; + bool attached = false; + }; +} + +#endif diff --git a/inputManager.cpp b/inputManager.cpp new file mode 100644 index 0000000..c59d747 --- /dev/null +++ b/inputManager.cpp @@ -0,0 +1,122 @@ +#include "inputManager.h" +#include "stateManager.h" +#include "util.h" + +#include +#include +#include + +namespace gameBase{ + double *posX, *posY, strX, strY; + int width, height; + + void foo(GLFWwindow *window, double newPosX, double newPosY){ + strX = (*posX - newPosX) / width, strY = (newPosY - *posY) / height; + } + + InputManager::InputManager(StateManager *stateManager, GLFWwindow *window){ + this->stateManager = stateManager; + this->window = window; + posX = new double, posY = new double; + } + + InputManager::~InputManager(){} + + void InputManager::update(){ + glfwGetWindowSize(window, &width, &height); + + + glfwGetCursorPos(window, posX, posY); + int joystick; + int numAxis = 3, numButtons = 6; + const u8 *buttons; + const float *axis; + + if(glfwJoystickPresent(GLFW_JOYSTICK_1)){ + joystick = GLFW_JOYSTICK_1; + axis = glfwGetJoystickAxes(joystick, &numAxis); + buttons = glfwGetJoystickButtons(joystick, &numButtons); + } + + for(int j = 0; j < stateManager->getAppStates().size(); j++){ + AbstractAppState *a = stateManager->getAppStates()[j]; + + for(int i = 0; i < a->getNumMappings(); i++){ + Mapping *m = a->getMapping(i); + + if(m->action){ + bool pressed; + + switch(m->type){ + case Mapping::KEYBOARD: + pressed = glfwGetKey(window, m->trigger); + break; + case Mapping::MOUSE_KEY: + pressed = glfwGetMouseButton(window, m->trigger); + break; + case Mapping::JOYSTICK_KEY: + if(glfwJoystickPresent(GLFW_JOYSTICK_1)) + pressed = buttons[m->trigger]; + + break; + } + + if((pressed && !m->pressed) || (!pressed&&m->pressed)){ + m->pressed = pressed; + a->onAction(m->bind, pressed); + } + } + else{ + switch(m->type){ + case Mapping::MOUSE_AXIS: + { + float str; + + switch(m->trigger){ + case Mapping::MOUSE_AXIS_LEFT: + case Mapping::MOUSE_AXIS_RIGHT: + str = strX; + break; + case Mapping::MOUSE_AXIS_UP: + case Mapping::MOUSE_AXIS_DOWN: + str = strY; + break; + } + a->onAnalog(m->bind, str); + break; + } + case Mapping::JOYSTICK_AXIS: + { + int axisId = (m->trigger - (m->trigger % 2 > 0)) / 2; + float str = (fabs(axis[axisId]) >= .1 ? axis[axisId] : 0); + + if(fabs(str) > 0) + a->onAnalog(m->bind, str); + + break; + } + } + } + } + + for(int i = 0; i < 350; i++){ + if(glfwGetKey(window, i)) + a->onRawKeyButton(i); + else if(glfwGetMouseButton(window, i)) + a->onRawMouseButton(i); + } + + glfwSetCursorPosCallback(window, foo); + + if(glfwJoystickPresent(GLFW_JOYSTICK_1)){ + for(int i = 0; i < numAxis; i++) + if(abs(axis[i]) == 1) + a->onRawJoystickAxis(i, axis[i]); + + for(int i = 0; i < numButtons; i++) + if(buttons[i]) + a->onRawJoystickButton(i); + } + } + } +} diff --git a/inputManager.h b/inputManager.h new file mode 100644 index 0000000..8972813 --- /dev/null +++ b/inputManager.h @@ -0,0 +1,20 @@ +#ifndef INPUT_MANAGER_H +#define INPUT_MANAGER_H + +class GLFWwindow; + +namespace gameBase{ + class StateManager; + + class InputManager{ + public: + InputManager(StateManager*, GLFWwindow*); + ~InputManager(); + void update(); + private: + StateManager *stateManager; + GLFWwindow *window; + }; +} + +#endif diff --git a/mapping.h b/mapping.h new file mode 100755 index 0000000..b3e37a9 --- /dev/null +++ b/mapping.h @@ -0,0 +1,60 @@ +#pragma once +#ifndef KEY_H +#define KEY_H + +namespace gameBase{ + struct Mapping{ + enum Bind{ + LEFT_CLICK, + SCROLLING_UP, + SCROLLING_DOWN, + LEFT, + RIGHT, + DELETE_CHAR, + CAPS_LOCK, + SHIFT_CAPS, + SPACE, + PLUS, + MINUS, + DEVSTERISK, + TOGGLE_MAIN_MENU, + HALT, + ZOOM_IN, + ZOOM_OUT, + LOOK_AROUND, + LOOK_UP, + LOOK_DOWN, + LOOK_LEFT, + LOOK_RIGHT, + DRAG_BOX, + DESELECT, + LEFT_CONTROL, + LEFT_SHIFT, + SELECT_PATROL_POINTS, + LAUNCH, + TOGGLE_SUB, + INSTALL_AWM, + INSTALL_AAM, + GROUP_0, + GROUP_1, + GROUP_2, + GROUP_3, + GROUP_4, + GROUP_5, + GROUP_6, + GROUP_7, + GROUP_8, + GROUP_9, + LAST_BIND + }; + enum BindType{KEYBOARD, MOUSE_KEY, MOUSE_AXIS, JOYSTICK_KEY, JOYSTICK_AXIS}; + enum AuxTriggers{MOUSE_AXIS_LEFT = 310, MOUSE_AXIS_RIGHT = 311, MOUSE_AXIS_UP = 312, MOUSE_AXIS_DOWN = 313}; + + Bind bind; + BindType type; + int trigger; + bool action, pressed = false; + }; +} + +#endif diff --git a/stateManager.cpp b/stateManager.cpp new file mode 100644 index 0000000..8b6c924 --- /dev/null +++ b/stateManager.cpp @@ -0,0 +1,49 @@ +#include "stateManager.h" + +namespace gameBase { + void StateManager::update(){ + for(int i = 0; i < appStates.size(); i++) + appStates[i]->update(); + } + + void StateManager::attachState(AbstractAppState *a){ + appStates.push_back(a); + a->onAttached(); + } + + void StateManager::dettachState(AbstractAppState *a){ + int id=-1; + + for(int i = 0; i < appStates.size() && id == -1; i++) + if(appStates[i] == a) + id = i; + + if(id != -1){ + a->onDettached(); + appStates.erase(appStates.begin() + id); + } + } + + void StateManager::dettachStateByType(int type){ + int id = -1; + + for(int i = 0; i < appStates.size() && id == -1; i++) + if(appStates[i]->getType() == type) + id = i; + + if(id != -1){ + appStates[id]->onDettached(); + appStates.erase(appStates.begin() + id); + } + } + + AbstractAppState* StateManager::getStateByType(int type){ + AbstractAppState *a = nullptr; + + for(int i = 0; i < appStates.size() && !a; i++) + if(appStates[i]->getType() == type) + a = appStates[i]; + + return a; + } +} diff --git a/stateManager.h b/stateManager.h new file mode 100644 index 0000000..d061999 --- /dev/null +++ b/stateManager.h @@ -0,0 +1,27 @@ +#ifndef STATE_MANAGER_H +#define STATE_MANAGER_H + +#include + +#include "abstractAppState.h" + +namespace gameBase { + class StateManager{ + public: + StateManager(){} + ~StateManager(){} + void update(); + void attachState(AbstractAppState *a); + void dettachState(AbstractAppState*); + void dettachStateByType(int); + inline void dettachStateById(int id){appStates.erase(appStates.begin() + id);} + inline AbstractAppState* getStateById(int i){return appStates[i];} + AbstractAppState* getStateByType(int); + inline std::vector getAppStates(){return appStates;} + inline int getNumAppStates(){return appStates.size();} + private: + std::vector appStates; + }; +} + +#endif diff --git a/util.cpp b/util.cpp new file mode 100644 index 0000000..63425f5 --- /dev/null +++ b/util.cpp @@ -0,0 +1,189 @@ +#include + +#include "util.h" +#include "mapping.h" +#include "stateManager.h" +#include "abstractAppState.h" + +using namespace std; +using namespace chrono; + +namespace gameBase{ + std::string keyStrings[]{ + "Escape", + "Enter", + "Tab", + "Backspace", + "Insert", + "Delete", + "Right", + "Left", + "Up", + "Down", + "PageUp", + "PageDown", + "Home", + "End", + "CapsLock", + "ScrollLock", + "NumLock", + "PrintScreen", + "Space", + "Pause", + "Numpad .", + "Numpad /", + "Numpad *", + "Numpad -", + "Numpad +", + "Numpad enter", + "=", + "Left shift", + "Left control", + "Left alt", + "Left super", + "Right shift", + "Right control", + "Right alt", + "Right super", + "Left click", + "Right click", + "Middle click" + }; + + int triggers[]{ + GLFW_KEY_ESCAPE, + GLFW_KEY_ENTER, + GLFW_KEY_TAB, + GLFW_KEY_BACKSPACE, + GLFW_KEY_INSERT, + GLFW_KEY_DELETE, + GLFW_KEY_RIGHT, + GLFW_KEY_LEFT, + GLFW_KEY_UP, + GLFW_KEY_DOWN, + GLFW_KEY_PAGE_UP, + GLFW_KEY_PAGE_DOWN, + GLFW_KEY_HOME, + GLFW_KEY_END, + GLFW_KEY_CAPS_LOCK, + GLFW_KEY_SCROLL_LOCK, + GLFW_KEY_NUM_LOCK, + GLFW_KEY_PRINT_SCREEN, + GLFW_KEY_SPACE, + GLFW_KEY_PAUSE, + GLFW_KEY_KP_DECIMAL, + GLFW_KEY_KP_DIVIDE, + GLFW_KEY_KP_MULTIPLY, + GLFW_KEY_KP_SUBTRACT, + GLFW_KEY_KP_ADD, + GLFW_KEY_KP_ENTER, + GLFW_KEY_EQUAL, + GLFW_KEY_LEFT_SHIFT, + GLFW_KEY_LEFT_CONTROL, + GLFW_KEY_LEFT_ALT, + GLFW_KEY_LEFT_SUPER, + GLFW_KEY_RIGHT_SHIFT, + GLFW_KEY_RIGHT_CONTROL, + GLFW_KEY_RIGHT_ALT, + GLFW_KEY_RIGHT_SUPER, + GLFW_MOUSE_BUTTON_LEFT, + GLFW_MOUSE_BUTTON_RIGHT, + GLFW_MOUSE_BUTTON_MIDDLE + }; + + string fromIntToString(int data[3]){ + string output; + + switch((Mapping::BindType)data[0]){ + case Mapping::KEYBOARD: + case Mapping::MOUSE_KEY: + { + bool specialKey = false; + int numSpecialKeys = sizeof(triggers) / sizeof(int); + + for(int i = 0; i < numSpecialKeys; i++){ + if(data[2] == triggers[i]){ + specialKey = true; + output = keyStrings[i]; + } + + if(!specialKey){ + char c[]{data[2]}; + output = string(c); + } + } + + break; + } + case Mapping::MOUSE_AXIS: + output = "MOUSE_AXIS_" + to_string(data[2]) + (data[1] ? "+" : "-"); + break; + case Mapping::JOYSTICK_KEY: + output = "JOYSTICK_BUTTON_" + to_string(data[2]); + break; + case Mapping::JOYSTICK_AXIS: + output = "JOYSTICK_AXIS_" + to_string(data[2]) + (data[1] ? "+" : "-"); + break; + } + return output; + } + + int* fromStringToInt(string data){ + int *output = new int[3], length = data.length(); + + if(data.substr(0, 11) == "MOUSE_AXIS_"){ + output[0] = Mapping::MOUSE_AXIS; + output[1] = 0; + output[2] = atoi(data.substr(11, string::npos - 1).c_str()) + (int)data.c_str()[12] == '+'; + } + else if(data.substr(0, 16) == "JOYSTICK_BUTTON_"){ + output[0] = Mapping::JOYSTICK_KEY; + output[1] = 1; + output[2] = atoi(data.substr(16, string::npos - 1).c_str()); + } + else if(data.substr(0, 14) == "JOYSTICK_AXIS_"){ + output[0] = Mapping::JOYSTICK_AXIS; + output[1] = 0; + output[2] = 2*atoi(data.substr(14, 1).c_str()) + (data.c_str()[15] == '+' ? 1 : 0); + } + else{ + bool specialKey = false; + int numSpecialKeys = sizeof(triggers) / sizeof(int); + + for(int i = 0; i < numSpecialKeys; i++) + if(data == keyStrings[i]){ + specialKey = true; + output[0] = numSpecialKeys - i <= 3 ? Mapping::MOUSE_KEY:Mapping::KEYBOARD; + output[2] = triggers[i]; + } + + if(!specialKey){ + output[0] = Mapping::KEYBOARD; + output[2] = data.c_str()[0]; + } + + output[1] = 1; + } + + return output; + } + + wstring stringToWstring(string str){ + wstring wstr = L""; + + for(char ch : str) + wstr += ch; + + return wstr; + } + + string wstringToString(wstring wstr){ + string str = ""; + + for(wchar_t ch : wstr) + if(ch < 256) + str += ch; + + return str; + } +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..50c1e32 --- /dev/null +++ b/util.h @@ -0,0 +1,30 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include + +namespace gameBase{ + typedef char s8; + typedef short s16; + typedef int s32; + typedef long long s64; + + typedef unsigned char u8; + typedef unsigned short u16; + typedef unsigned int u32; + typedef unsigned long long u64; + + inline s64 getTime(){return (s64)(std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1));} + void readFile(std::string, std::vector&, int = 0, int = -1); + void writeFile(std::string, std::vector&); + std::string convert(std::string); + int* fromStringToInt(std::string); + std::string fromIntToString(int[3]); + std::wstring stringToWstring(std::string); + std::string wstringToString(std::wstring); +} + +#endif