我将以下内容实现为我不久前正在编写的 opengl 游戏的控制台。这绝不是您问题的明确答案,但它对我有用,您可能会从中得到一些有用的东西。
这两个文件在这篇文章的底部。该代码不太可能直接运行,因为我不打算包含 2 个库头文件中的一个。如果您想要完整的来源,请告诉我。
基本上,尽管控制台类允许您向它添加可以在运行时更改的变量指针。它接受来自 Windows 事件消息的输入。(输入的实际处理在别处完成)命令解析在 ProcessInput() 方法中完成,变量在 ChangeVariable() 方法中更新。
一句警告。这种方法本质上使控制台用户可以直接访问单个变量的内存位置。这需要良好的输入验证,以确保用户不会导致应用程序在运行时崩溃。如果我坐下来尝试制作另一个控制台,我可能会做一些稍微不同的事情。不过我希望这能给你一点帮助。
头文件:
#ifndef CONSOLE_H
#define CONSOLE_H
#include <vector>
#include <map>
#include <string>
#include "Singleton.h"
#include <Windows.h>
#include "Enumerations.h"
#include "StringConversion.h"
class Console
{
public:
Console();
~Console();
void Update(std::vector<WPARAM> pressedKeys);
void AddInt(std::string varName, int *ptrToInt);
void AddFloat(std::string varName, float *ptrToFloat);
void AddLong(std::string varName, long *ptrToLong);
void AddBool(std::string varName, bool *ptrToBool);
const std::string &GetCurrentText();
const std::vector<std::string> &GetPreviousText();
private:
std::map<std::string, int *> m_Ints;
std::map<std::string, float *> m_Floats;
std::map<std::string, long *> m_Longs;
std::map<std::string, bool *> m_Bools;
std::map<std::string, std::string> m_Variables;
std::vector<std::string> m_PrevConsoleText;
std::string m_CurrInput;
int m_PrevSelection;
bool ProcessInput();
void ChangeVariable(const std::string &varName, const std::string &value);
};
typedef Singleton<Console> g_Console;
#endif // CONSOLE_H
.cpp 文件:
#include "Console.h"
Console::Console()
{
m_PrevSelection = 0;
}
Console::~Console()
{
}
void Console::AddInt(std::string varName, int *ptrToInt)
{
m_Ints[varName] = ptrToInt;
m_Variables[varName] = "int";
}
void Console::AddFloat(std::string varName, float *ptrToFloat)
{
m_Floats[varName] = ptrToFloat;
m_Variables[varName] = "float";
}
void Console::AddLong(std::string varName, long *ptrToLong)
{
m_Longs[varName] = ptrToLong;
m_Variables[varName] = "long";
}
void Console::AddBool(std::string varName, bool *ptrToBool)
{
m_Bools[varName] = ptrToBool;
m_Variables[varName] = "bool";
}
void Console::ChangeVariable(const std::string &varName, const std::string &value)
{
//*(m_Bools[varName]) = value;
std::string temp = m_Variables[varName];
if(temp == "int")
{
//*(m_Ints[varName]) = fromString<int>(value);
}
else if(temp == "float")
{
//*(m_Floats[varName]) = fromString<float>(value);
}
else if(temp == "long")
{
//*(m_Longs[varName]) = fromString<long>(value);
}
else if(temp == "bool")
{
if(value == "true" || value == "TRUE" || value == "True")
{
*(m_Bools[varName]) = true;
}
else if(value == "false" || value == "FALSE" || value == "False")
{
*(m_Bools[varName]) = false;
}
}
}
const std::string &Console::GetCurrentText()
{
return m_CurrInput;
}
void Console::Update(std::vector<WPARAM> pressedKeys)
{
for(int x = 0; x < (int)pressedKeys.size(); x++)
{
switch(pressedKeys[x])
{
case KEY_A:
m_CurrInput.push_back('a');
break;
case KEY_B:
m_CurrInput.push_back('b');
break;
case KEY_C:
m_CurrInput.push_back('c');
break;
case KEY_D:
m_CurrInput.push_back('d');
break;
case KEY_E:
m_CurrInput.push_back('e');
break;
case KEY_F:
m_CurrInput.push_back('f');
break;
case KEY_G:
m_CurrInput.push_back('g');
break;
case KEY_H:
m_CurrInput.push_back('h');
break;
case KEY_I:
m_CurrInput.push_back('i');
break;
case KEY_J:
m_CurrInput.push_back('j');
break;
case KEY_K:
m_CurrInput.push_back('k');
break;
case KEY_L:
m_CurrInput.push_back('l');
break;
case KEY_M:
m_CurrInput.push_back('m');
break;
case KEY_N:
m_CurrInput.push_back('n');
break;
case KEY_O:
m_CurrInput.push_back('o');
break;
case KEY_P:
m_CurrInput.push_back('p');
break;
case KEY_Q:
m_CurrInput.push_back('q');
break;
case KEY_R:
m_CurrInput.push_back('r');
break;
case KEY_S:
m_CurrInput.push_back('s');
break;
case KEY_T:
m_CurrInput.push_back('t');
break;
case KEY_U:
m_CurrInput.push_back('u');
break;
case KEY_V:
m_CurrInput.push_back('v');
break;
case KEY_W:
m_CurrInput.push_back('w');
break;
case KEY_X:
m_CurrInput.push_back('x');
break;
case KEY_Y:
m_CurrInput.push_back('y');
break;
case KEY_Z:
m_CurrInput.push_back('z');
break;
case KEY_0:
m_CurrInput.push_back('0');
break;
case KEY_1:
m_CurrInput.push_back('1');
break;
case KEY_2:
m_CurrInput.push_back('2');
break;
case KEY_3:
m_CurrInput.push_back('3');
break;
case KEY_4:
m_CurrInput.push_back('4');
break;
case KEY_5:
m_CurrInput.push_back('5');
break;
case KEY_6:
m_CurrInput.push_back('6');
break;
case KEY_7:
m_CurrInput.push_back('7');
break;
case KEY_8:
m_CurrInput.push_back('8');
break;
case KEY_9:
m_CurrInput.push_back('9');
break;
case KEY_QUOTE:
m_CurrInput.push_back('\"');
break;
case KEY_EQUALS:
m_CurrInput.push_back('=');
break;
case KEY_SPACE:
m_CurrInput.push_back(' ');
break;
case KEY_BACKSPACE:
if(m_CurrInput.size() > 0)
{
m_CurrInput.erase(m_CurrInput.end() - 1, m_CurrInput.end());
}
break;
case KEY_ENTER:
ProcessInput();
break;
case KEY_UP:
m_PrevSelection--;
if(m_PrevSelection < 1)
{
m_PrevSelection = m_PrevConsoleText.size() + 1;
m_CurrInput = "";
}
else
{
m_CurrInput = m_PrevConsoleText[m_PrevSelection - 1];
}
break;
case KEY_DOWN:
if(m_PrevSelection > (int)m_PrevConsoleText.size())
{
m_PrevSelection = 0;
m_CurrInput = "";
}
else
{
m_CurrInput = m_PrevConsoleText[m_PrevSelection - 1];
}
m_PrevSelection++;
break;
}
}
}
bool Console::ProcessInput()
{
int x;
std::string variable = "NULL", value;
bool ok = false;
std::string::iterator it;
//Split up the input from the user.
//variable will be the variable to change
//ok will = true if the syntax is correct
//value will be the value to change variable to.
for(x = 0; x < (int)m_CurrInput.size(); x++)
{
if(m_CurrInput[x] == ' ' && variable == "NULL")
{
variable = m_CurrInput.substr(0, x);
}
else if(m_CurrInput[x] == '=' && m_CurrInput[x - 1] == ' ' && m_CurrInput[x + 1] == ' ')
{
ok = true;
}
else if(m_CurrInput[x] == ' ')
{
value = m_CurrInput.substr(x + 1, m_CurrInput.size());
}
}
if(ok)
{
m_PrevConsoleText.push_back(m_CurrInput);
m_PrevSelection = m_PrevConsoleText.size();
if(m_PrevConsoleText.size() > 10)
{
m_PrevConsoleText.erase(m_PrevConsoleText.begin(), m_PrevConsoleText.begin() + 1);
}
m_CurrInput.clear();
ChangeVariable(variable, value);
}
else
{
m_PrevConsoleText.push_back("Error invalid console syntax! Use: <variableName> = <value>");
m_CurrInput.clear();
}
return ok;
}
const std::vector<std::string> &Console::GetPreviousText()
{
return m_PrevConsoleText;
}
编辑 1:添加 DrawConsole()
我只是从控制台类中获取文本,渲染一个看起来类似于在任何最近的 Valve 游戏中找到的源引擎控制台窗口的图像,然后在适当的位置绘制文本。
void View::DrawConsole()
{
Square console;
std::vector<std::string> temp;
temp = g_Console::Instance().GetPreviousText();
console.top = Vector3f(0.0, 0.0, 1.0);
console.bottom = Vector3f(640, 480, 1.0);
g_Render::Instance().SetOrthographicProjection();
g_Render::Instance().PushMatrix();
g_Render::Instance().LoadIdentity();
g_Render::Instance().BindTexture(m_ConsoleTexture);
g_Render::Instance().DrawPrimative(console, Vector3f(1.0f, 1.0f, 1.0f));
g_Render::Instance().DisableTexture();
g_Render::Instance().SetOrthographicProjection();
//Draw the current console text
g_Render::Instance().DrawString(g_Console::Instance().GetCurrentText(), 0.6f, 20, 465);
//Draw the previous console text
for(int x = (int)temp.size(); x > 0; x--)
{
g_Render::Instance().DrawString(temp[x-1], 0.6f, 20, (float)(425 - (abs((int)temp.size() - x) * 20)));
}
g_Render::Instance().SetPerspectiveProjection();
g_Render::Instance().PopMatrix();
g_Render::Instance().SetPerspectiveProjection();
}