2012-06-12 10 views
9

मेरे एप्लिकेशन को को एप्लिकेशन विंडो में एम्बेड करने के लिए एक कंसोल की आवश्यकता होती है, उदाहरण के लिए एक प्रोग्राम में ऑटोकैड होगा जहां कंसोल कमांड के लिए विंडो के निचले हिस्से में है।एप्लिकेशन के भीतर एक कंसोल लिखना

enter image description here

मैं अपने आवेदन के भीतर सांत्वना की जरूरत है ताकि मैं चर और अन्य चीजों को बदल सकते हैं, तो कंसोल एक पूरी तरह से नष्ट हो खोल होने की जरूरत नहीं है।

इस समय मेरे पास मेरे आवेदन के भीतर एक सरल कंसोल है, लेकिन यह एक टर्मिनल (खोल) की तुलना में बहुत गुस्सा लगता है, जो मैं कंसोल की तरह होना चाहता हूं।

enter image description here

तरह से है कि मैं इसे सांत्वना मैं के साथ किया है उपयोगकर्ता TAB कुंजी सांत्वना शो दबाता है, तो वे अपने आदेश/पंक्ति में टाइप कर सकते हैं है, एक बार Return कुंजी दबाए गए स्ट्रिंग को दबा दिया गया है जिसे उन्होंने टाइप किया है पार्स किया गया है और कमांड संसाधित हो गया है।

मैं अपनी एप्लिकेशन विंडो में टेक्स्ट प्रिंट करने के लिए sf::Text ऑब्जेक्ट्स का उपयोग कर रहा हूं। कुल 5 sf::Text ऑब्जेक्ट्स जिनका उपयोग किया जाता है, पिछले आदेश/त्रुटि संदेशों के लिए 4 और वर्तमान कमांड लाइन के लिए 1 हैं। जब Return कुंजी दबाया जाता है तो चौथा sf::Text अपनी वर्तमान स्ट्रिंग को तीसरे, तीसरे से दूसरे, दूसरे से पहले और 1 को वर्तमान कमांड स्ट्रिंग में बदल देता है, तो वर्तमान कमांड स्ट्रिंग को साफ़ किया जाता है और फिर इनपुट के लिए तैयार हो जाता है। इस तरह कमांड और/या त्रुटियों के 4 'इतिहास' के लिए जगह है। सबसे महान नहीं, लेकिन यह सबसे अच्छा था जिसके साथ मैं आ सकता था। निश्चित रूप से sf::Text ऑब्जेक्ट्स जोड़कर इतिहास की मात्रा बदला जा सकता है। तो अंत में यह कैसे मैं स्क्रीन

sf::RectangleShape rectangle; 

rectangle.setSize(sf::Vector2f(App->getSize().x, App->getSize().y/3)); 
rectangle.setPosition(0, 0); 

rectangle.setFillColor(sf::Color::black); 

App->draw(rectangle); // This renders the console looking background rectangle 
App->draw(CLine); // This renders the current command line 

for(int i = 4; i >= 0; --i) // This renders the history as described above, their idevidual positions are setup earlier on in the program 
{ 
    CHistory[i].setString(CS[i]); 
    App->draw(CHistory[i]); 
} 

App को सांत्वना प्रस्तुत करना है तो बस एक sf::RenderWindow*

मेरे समग्र सवाल यह है कि, है वहाँ एक रास्ता है कि मैं अपने SFML में एक सांत्वना एम्बेड कर सकते हैं खिड़की बिना किसी कंसोल की तरह दिखने के लिए प्रस्तुत की गई टेक्स्ट ऑब्जेक्ट्स की एक छवि होने के बिना। मैं अपने आवेदन के भीतर एक वास्तविक कंसोल/खोल/टर्मिनल रखना पसंद करूंगा। मानक बाश खोल की तरह, लेकिन निश्चित रूप से मेरा खुद का खोल दुभाषिया।

उत्तर

-1

यदि आप अपना कस्टम कंसोल लागू कर रहे हैं तो आपको खुद को बहुत कुछ लिखना होगा। the SMFL docs की एक त्वरित स्कीम बताती है कि आपकी मदद करने के लिए कुछ भी नहीं बनाया गया है। यह सिर्फ एक सरल और फास्ट मल्टीमीडिया लाइब्रेरी है ;-)

यदि आपको कुछ और पूरी तरह से विशेष रुप से प्रदर्शित करने की आवश्यकता है तो मैं OGRE में देखने का सुझाव दूंगा।

+0

मैं एसएफएमएल के लिए यह करने के लिए नहीं हूं, मैंने टैग के रूप में एसएफएमएल जोड़ा और कोड उदाहरणों में यह दिखाने के लिए कि मैं एसएफएमएल का उपयोग कर रहा था। मुझे पता है कि मुझे इसे खुद लिखना है, मैं इसके बाद क्या कर रहा हूं इस पर दिशा है। अन्य लोग अपने आवेदन में कंसोल लिखने के बारे में कैसे गए हैं। : डी – Elgoog

+0

एक बार जब आप पहचान लें कि आप क्या हासिल करना चाहते हैं तो मैं आपके प्रश्न को कुछ छोटे हिस्सों में परिष्कृत करने का सुझाव दूंगा। आपकी आवश्यकताओं क्या हैं? क्वैक या अवास्तविक टूर्नामेंट में से किसी एक का उपयोग करने का प्रयास करें या जिस भी गेम में आप रुचि रखते हैं। –

+0

वुल्फियर ने स्पष्ट रूप से वेबकिट पर आधारित कुछ विकसित किया: http://www.youtube.com/watch?v=c-4WdtTGIkg&feature=relmfu –

0

ठीक है, क्या आप शायद अगर आप इसे और अधिक एक सांत्वना की तरह महसूस करना चाहते हैं चाहते हैं:

  • पर स्विच करने में सक्षम होने के नाते और एक बटन दबाएँ, शायद ~ की तरह कुछ, के साथ बंद जो प्रयोग किया जाता है एक बहुत।
  • उस रेखा को दें जो आप पृष्ठभूमि रंग पर टाइप कर रहे हैं, शायद पारदर्शी, लेकिन कम से कम सुनिश्चित करें कि यह केवल रेंडरविंडो पर फ़्लोटिंग टेक्स्ट नहीं है। यदि कमांड का आउटपुट एकाधिक लाइन है, तो सुनिश्चित करें कि वे सभी दिखाई दे रहे हैं या लोग कम से कम इतिहास के माध्यम से स्क्रॉल कर सकते हैं।
  • सुनिश्चित करें कि आदेश समझने और सुसंगत हैं। उदाहरण के लिए, यदि मुझे गलत नहीं लगता है, तो स्रोत इंजन पर बहुत सारे गेम cl_ उपसर्ग को किसी भी प्रतिपादन के लिए उपयोग करते हैं। उदाहरण के लिए cl_showfps 1 देखें।
  • पारंपरिक टर्मिनल इनपुट एक अच्छा स्पर्श होगा। ऊपर आपको पिछली कमांड दिखाती है जिसमें आप भरे हुए हैं। शायद अगर आप साहसी महसूस कर रहे हैं, तो पूरा होने के लिए टैब का उपयोग करें।
  • यदि आपके पास कुछ समय शेष है, उदाहरण के लिए --help के माध्यम से उपलब्ध कमांड दिखाने का एक तरीका भी अच्छा होगा। इस पर निर्भर करता है कि आपका गेम कितना जटिल है।

बाकी के लिए, यह देखें कि अन्य खेलों ने यह कैसे किया। आपने क्वैक का उल्लेख किया है, जिसमें एक इंजेम टर्मिनल का एक बड़ा उदाहरण है। मैं एक के लिए सोचता हूं कि बहुत से स्रोत गेम में से एक का उपयोग करना भी आसान है (हाफ लाइफ 2, काउंटर स्ट्राइक सोर्स, टीम किले 2, वाम 4 डेड इत्यादि देखें)। मुझे नहीं लगता कि इसके लिए कोई मानक पुस्तकालय हैं, जिसमें ओजीआरई या इरिलिच जैसे अन्य ढांचे शामिल नहीं हैं।

4

मैंने कुछ समय पहले एक ओपनग्ल गेम के लिए कंसोल के रूप में निम्नलिखित को लागू किया था। यह आपके लिए कोई निश्चित जवाब नहीं है लेकिन यह मेरे लिए काम करता है और आपको इससे कुछ उपयोगी मिल सकता है।

2 फाइलें इस पोस्ट के नीचे हैं। कोड सीधे चलाने की संभावना नहीं है क्योंकि 2 लाइब्रेरी हेडर फाइलों में से एक है जिसे मैं शामिल नहीं करने जा रहा हूं। अगर आप चाहते हैं कि पूरा स्रोत मुझे बताए।

असल में हालांकि कंसोल क्लास आपको वैरिएबल पॉइंटर्स जोड़ने की अनुमति देता है जिसे रन टाइम में बदला जा सकता है। यह विंडोज इवेंट संदेशों से इनपुट स्वीकार करता है। (इनपुट की वास्तविक हैंडलिंग कहीं और की जाती है) कमांड पार्सिंग 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() मैं सिर्फ एक छवि है कि देखा प्रस्तुत करना कंसोल वर्ग से पाठ मिलता है किसी भी हालिया वाल्व गेम में पाए जाने वाले स्रोत इंजन कंसोल विंडो के समान और फिर उपयुक्त स्थान पर टेक्स्ट खींचा जाता है।

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(); 
} 
+0

क्या मैं पूछ सकता हूं आप ओपनजीएल विंडो में इसे कैसे प्रस्तुत करते हैं? – Elgoog

+0

मैंने ऊपर दिए गए मेरे उत्तर में DrawConsole फ़ंक्शन जोड़ा। ध्यान रखें कि एक बार फिर कोड का एक छोटा सा कोड है जो मेरे रेंडर क्लास जैसे अन्य स्थानों से जुड़ा हुआ है। – Brendan

2

इसमें कुछ चीजें हैं। सबसे पहले आप किसी प्रकार का लाइन संपादन समर्थन चाहते हैं। वहाँ उदाहरण NetBSD के editline के लिएhttp://www.thrysoee.dk/editline/

तो फिर तुम किसी भी तरह keypresses कार्रवाई करने के लिए की जरूरत है, इस के लिए पुस्तकालय हैं। अब यह वह जगह है जहां मजा शुरू होता है। मुख्य घटनाओं को सीधे संसाधित करने की कोशिश करने के बजाय, मैं उन्हें pipe (POSIX)/CreatePipe पर विंडोज पर एक अज्ञात पाइप में खिलाऊंगा। फिर दूसरी तरफ आप उन्हें पढ़ सकते हैं, जैसे कि वे stdin से आए थे।एक दूसरी अनाम पाइप stdout के फ़ंक्शन को दोगुना करता है और इसके आउटपुट को इन-गेम कंसोल पर प्रदर्शित किया जाता है। मैं परिणामी जोड़ी एफडी कंसोलिन और कंसोलआउट पर कॉल करूंगा। मैं तत्काल त्रुटि संदेशों के लिए कंसोलर एफडी भी जोड़ूंगा; कंसोल उन्हें किसी अन्य रंग में प्रदर्शित कर सकता है या उन्हें फ़िल्टर कर सकता है।

इस दृष्टिकोण के बारे में अच्छी बात यह है कि आप अपने कंसोल से बात करने के लिए सभी अच्छी मानक लाइब्रेरी सुविधाओं का उपयोग कर सकते हैं। आप fprintf(consoleout, ...), fscanf(consolein, ...) और इसी तरह का उपयोग कर सकते हैं; यह निश्चित रूप से सी ++ iostreams के साथ भी काम करता है। लेकिन अधिक महत्वपूर्ण बात यह है कि आप उपरोक्त एडिटलाइन जैसे पुस्तकालयों को सीधे संलग्न कर सकते हैं।

अंत में आपको कंसोल में टाइप किए गए आदेशों को संसाधित करने की आवश्यकता है। वहां मैं आलसी मार्ग पर जाऊंगा और बस एक स्क्रिप्टिंग भाषा दुभाषिया को एम्बेड करूंगा, जो इंटरैक्टिव ऑपरेशन का समर्थन करता है। पायथन, या पूरे गेम में बहुत व्यापक, लुआ की तरह। आप निश्चित रूप से अपना खुद का कमांड दुभाषिया भी कार्यान्वित कर सकते हैं।

+1

यही वह था जो मैं इसके बाद था, इसके बारे में कुछ स्पष्टीकरण कि इसके बारे में कैसे जाना है। मुझे आपके द्वारा उल्लिखित अज्ञात पाइप समाधान में बहुत दिलचस्पी है, ऐसा लगता है कि यह सही तरीका है। मुझे यह सुनिश्चित नहीं है कि इसे कैसे कार्यान्वित किया जाए, यदि आप एक पॉज़िक्स सिस्टम पर थोड़ा कोड उदाहरण दे सकते हैं तो मैं बहुत सराहना करता हूं। धन्यवाद। – Elgoog

संबंधित मुद्दे