// , cotrols->Update() ... void Player::Move() { if (controls->MouseButonPressed(0)) { ... } if (controls->KeyPressed(KEY_SPACE)) { ... } if (controls->JoystickButtonPressed(0)) { ... } } int GetAlias(const char* name); enum AliasAction { Active, Activated }; bool GetAliasState(int alias, AliasAction action); float GetAliasValue(int alias, bool delta); void FreeCamera::Init() { proj.BuildProjection(45.0f * RADIAN, 600.0f / 800.0f, 1.0f, 1000.0f); angles = Vector2(0.0f, -0.5f); pos = Vector(0.0f, 6.0f, 0.0f); alias_forward = controls.GetAlias("FreeCamera.MOVE_FORWARD"); alias_strafe = controls.GetAlias("FreeCamera.MOVE_STRAFE"); alias_fast = controls.GetAlias("FreeCamera.MOVE_FAST"); alias_rotate_active = controls.GetAlias("FreeCamera.ROTATE_ACTIVE"); alias_rotate_x = controls.GetAlias("FreeCamera.ROTATE_X"); alias_rotate_y = controls.GetAlias("FreeCamera.ROTATE_Y"); alias_reset_view = controls.GetAlias("FreeCamera.RESET_VIEW"); } void FreeCamera::Update(float dt) { if (controls.GetAliasState(alias_reset_view)) { angles = Vector2(0.0f, -0.5f); pos = Vector(0.0f, 6.0f, 0.0f); } if (controls.GetAliasState(alias_rotate_active, Controls::Active)) { angles.x -= controls.GetAliasValue(alias_rotate_x, true) * 0.01f; angles.y -= controls.GetAliasValue(alias_rotate_y, true) * 0.01f; if (angles.y > HALF_PI) { angles.y = HALF_PI; } if (angles.y < -HALF_PI) { angles.y = -HALF_PI; } } float forward = controls.GetAliasValue(alias_forward, false); float strafe = controls.GetAliasValue(alias_strafe, false); float fast = controls.GetAliasValue(alias_fast, false); float speed = (3.0f + 12.0f * fast) * dt; Vector dir = Vector(cosf(angles.x), sinf(angles.y), sinf(angles.x)); pos += dir * speed * forward; Vector dir_strafe = Vector(dir.z, 0,-dir.x); pos += dir_strafe * speed * strafe; view.BuildView(pos, pos + Vector(cosf(angles.x), sinf(angles.y), sinf(angles.x)), Vector(0, 1, 0)); render.SetTransform(Render::View, view); proj.BuildProjection(45.0f * RADIAN, (float)render.GetDevice()->GetHeight() / (float)render.GetDevice()->GetWidth(), 1.0f, 1000.0f); render.SetTransform(Render::Projection, proj); } { "Aliases" : [ { "name" : "FreeCamera.MOVE_FORWARD", "AliasesRef" : [ { "names" : ["KEY_W"], "modifier" : 1.0 }, { "names" : ["KEY_I"], "modifier" : 1.0 }, { "names" : ["KEY_S"], "modifier" : -1.0 }, { "names" : ["KEY_K"], "modifier" : -1.0 } ]}, { "name" : "FreeCamera.MOVE_STRAFE", "AliasesRef" : [ { "names" : ["KEY_A"], "modifier" : -1.0 }, { "names" : ["KEY_J"], "modifier" : -1.0 }, { "names" : ["KEY_D"], "modifier" : 1.0 }, { "names" : ["KEY_L"], "modifier" : 1.0 } ]}, { "name" : "FreeCamera.MOVE_FAST", "AliasesRef" : [ { "names" : ["KEY_LSHIFT"] } ]}, { "name" : "FreeCamera.ROTATE_ACTIVE", "AliasesRef" : [ { "names" : ["MS_BTN1"] } ]}, { "name" : "FreeCamera.ROTATE_X", "AliasesRef" : [ { "names" : ["MS_X"] } ]}, { "name" : "FreeCamera.ROTATE_Y", "AliasesRef" : [ { "names" : ["MS_Y"] } ]}, { "name" : "FreeCamera.RESET_VIEW", "AliasesRef" : [ { "names" : ["KEY_R", "KEY_LCONTROL"] } ]} ] } bool GetAliasState(int alias, bool exclusive, AliasAction action); float GetAliasValue(int alias, bool delta); bool DebugKeyPressed(const char* name, AliasAction action); bool DebugHotKeyPressed(const char* name, const char* name2, const char* name3); enum Device { Keyboard, Mouse, Joystick }; struct HardwareAlias { std::string name; Device device; int index; float value; }; struct AliasRefState { std::string name; int aliasIndex = -1; bool refer2hardware = false; }; struct AliasRef { float modifier = 1.0f; std::vector<AliasRefState> refs; }; struct Alias { std::string name; bool visited = false; std::vector<AliasRef> aliasesRef; }; bool Controls::Init(const char* name_haliases, bool allowDebugKeys) { this->allowDebugKeys = allowDebugKeys; //Init input devices and related stuff JSONReader* reader = new JSONReader(); if (reader->Parse(name_haliases)) { while (reader->EnterBlock("keyboard")) { haliases.push_back(HardwareAlias()); HardwareAlias& halias = haliases[haliases.size() - 1]; halias.device = Keyboard; reader->Read("name", halias.name); reader->Read("index", halias.index); debeugMap[halias.name] = (int)haliases.size() - 1; reader->LeaveBlock(); } while (reader->EnterBlock("mouse")) { haliases.push_back(HardwareAlias()); HardwareAlias& halias = haliases[(int)haliases.size() - 1]; halias.device = Mouse; reader->Read("name", halias.name); reader->Read("index", halias.index); debeugMap[halias.name] = (int)haliases.size() - 1; reader->LeaveBlock(); } } reader->Release(); return true; } bool Controls::LoadAliases(const char* name_aliases) { JSONReader* reader = new JSONReader(); bool res = false; if (reader->Parse(name_aliases)) { res = true; while (reader->EnterBlock("Aliases")) { std::string name; reader->Read("name", name); int index = GetAlias(name.c_str()); Alias* alias; if (index == -1) { aliases.push_back(Alias()); alias = &aliases.back(); alias->name = name; aliasesMap[name] = (int)aliases.size() - 1; } else { alias = &aliases[index]; alias->aliasesRef.clear(); } while (reader->EnterBlock("AliasesRef")) { alias->aliasesRef.push_back(AliasRef()); AliasRef& aliasRef = alias->aliasesRef.back(); while (reader->EnterBlock("names")) { aliasRef.refs.push_back(AliasRefState()); AliasRefState& ref = aliasRef.refs.back(); reader->Read("", ref.name); reader->LeaveBlock(); } reader->Read("modifier", aliasRef.modifier); reader->LeaveBlock(); } reader->LeaveBlock(); } ResolveAliases(); } reader->Release(); } void Controls::ResolveAliases() { for (auto& alias : aliases) { for (auto& aliasRef : alias.aliasesRef) { for (auto& ref : aliasRef.refs) { int index = GetAlias(ref.name.c_str()); if (index != -1) { ref.aliasIndex = index; ref.refer2hardware = false; } else { for (int l = 0; l < haliases.size(); l++) { if (StringUtils::IsEqual(haliases[l].name.c_str(), ref.name.c_str())) { ref.aliasIndex = l; ref.refer2hardware = true; break; } } } if (index == -1) { printf("alias %s has invalid reference %s", alias.name.c_str(), ref.name.c_str()); } } } } for (auto& alias : aliases) { CheckDeadEnds(alias); } } void Controls::CheckDeadEnds(Alias& alias) { alias.visited = true; for (auto& aliasRef : alias.aliasesRef) { for (auto& ref : aliasRef.refs) { if (ref.aliasIndex != -1 && !ref.refer2hardware) { if (aliases[ref.aliasIndex].visited) { ref.aliasIndex = -1; printf("alias %s has circular reference %s", alias.name.c_str(), ref.name.c_str()); } else { CheckDeadEnds(aliases[ref.aliasIndex]); } } } } alias.visited = false; } bool Controls::GetHardwareAliasState(int index, AliasAction action) { HardwareAlias& halias = haliases[index]; switch (halias.device) { case Keyboard: { //code that access to state of keyboard break; } case Mouse: { //code that access to state of mouse break; } } return false; } bool Controls::GetHardwareAliasValue(int index, bool delta) { HardwareAlias& halias = haliases[index]; switch (halias.device) { case Keyboard: { //code that access to state of keyboard break; } case Mouse: { //code that access to state of mouse break; } } return 0.0f; } bool Controls::GetAliasState(int index, AliasAction action) { if (index == -1 || index >= aliases.size()) { return 0.0f; } Alias& alias = aliases[index]; for (auto& aliasRef : alias.aliasesRef) { bool val = true; for (auto& ref : aliasRef.refs) { if (ref.aliasIndex == -1) { continue; } if (ref.refer2hardware) { val &= GetHardwareAliasState(ref.aliasIndex, Active); } else { val &= GetAliasState(ref.aliasIndex, Active); } } if (action == Activated && val) { val = false; for (auto& ref : aliasRef.refs) { if (ref.aliasIndex == -1) { continue; } if (ref.refer2hardware) { val |= GetHardwareAliasState(ref.aliasIndex, Activated); } else { val |= GetAliasState(ref.aliasIndex, Activated); } } } if (val) { return true; } } return false; } float Controls::GetAliasValue(int index, bool delta) { if (index == -1 || index >= aliases.size()) { return 0.0f; } Alias& alias = aliases[index]; for (auto& aliasRef : alias.aliasesRef) { float val = 0.0f; for (auto& ref : aliasRef.refs) { if (ref.aliasIndex == -1) { continue; } if (ref.refer2hardware) { val = GetHardwareAliasValue(ref.aliasIndex, delta); } else { val = GetAliasValue(ref.aliasIndex, delta); } } if (fabs(val) > 0.01f) { return val * aliasRef.modifier; } } return 0.0f; } bool Controls::DebugKeyPressed(const char* name, AliasAction action) { if (!allowDebugKeys || !name) { return false; } if (debeugMap.find(name) == debeugMap.end()) { return false; } return GetHardwareAliasState(debeugMap[name], action); } bool Controls::DebugHotKeyPressed(const char* name, const char* name2, const char* name3) { if (!allowDebugKeys) { return false; } bool active = DebugKeyPressed(name, Active) & DebugKeyPressed(name2, Active); if (name3) { active &= DebugKeyPressed(name3, Active); } if (active) { if (DebugKeyPressed(name) | DebugKeyPressed(name2) | DebugKeyPressed(name3)) { return true; } } return false; } void Controls::Update(float dt) { //update state of input devices } Source: https://habr.com/ru/post/343258/
All Articles