Home » Community » Forums » » Creating a Scalable Console System with STL – Part 1
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Creating a Scalable Console System with STL Part 1
Post Reply 
The link from the front page doesn't seem to work...

 User Rating: 1428   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Shouldn't it be (on the second page)
  // tokenize
  while(index != std::string::npos)
  {
    // push word
    std::string::size_type next_space = m_commandLine.find(' ',index);


 User Rating: 1275   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Very nice! Looking forward to the subsequent parts of the article.

 User Rating: 1254   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I read this article on flipcode just last friday. The e-mail to the author is different. So I might as well post the e-mail stuff I sent, here.
Just nitpicky stuff I do to all articles :P I'm just giving some creative chritisism christianism criticism because articles creates habits in the readers, including the bad habits.

¤
void console::passIntro()
{
if(m_commandLine.length() > 0) parseCommandLine();
}
You should use .empty()==false instead. Some implementations of std::list::size() iterates through all the elements counting them. And empty() showes more what you're after, ++readability.

¤
You want to be able to push strings on the end of the commandBuffer, and remove from the beginning. Then you should use a std::deque.

¤
You don't have to declare all the variables in the beginning of the function (you probably know this but still). Declare them right before they're used. Makes reading and understand code much simpler, especially for tutorials. *thinking about console::parseCommandLine() and the 'iter' variable* Not only that, some variables don't get created if they aren't used (multiple exit points).

¤
Variable names like 'i' might be ok for loops because 'i' normally stands for "index". Variable names like "iter" doesn't say anything... It should be called "item" or "consoleItem" or something.

¤
"After adding the command when the user types '/print_args 1 2 hello' the console would output '1, 2, hello'."
Actually, your code will print
"1, 2, hello,
"
(notice the ending ", " and newline)


Overall, nice article! Hope to see Part 2 soon!

[Edited by - Seriema on December 6, 2004 9:21:47 PM]

[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ]
[ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]


 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I knew I'd read this article before.

 User Rating: 1003   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Seriema
void console::passIntro()
{
if(m_commandLine.length() > 0) parseCommandLine();
}
You should use .empty()==false instead. Some implementations of std::list::size() iterates through all the elements counting them. And empty() showes more what you're after, ++readability.

That's a string, not a list. The string length method has the same performance constraints as the standard container size() methods, which is constant. Not linear. Meaning any list that implements size() as a counting method is an incorrect implementation, and your compiler is probably no longer even on the market. Even VS6 wasn't that bad.
However, you are correct that using empty() is cleaner and more readable. So would changing the code to use two lines instead of one. While brevity is nice, clean code is nicer.
Quote:

You want to be able to push strings on the end of the commandBuffer, and remove from the beginning. Then you should use a std::deque.

Agreed.
Quote:

You don't have to declare all the variables in the beginning of the function (you probably know this but still). Declare them right before they're used. Makes reading and understand code much simpler, especially for tutorials. *thinking about console::parseCommandLine() and the 'iter' variable* Not only that, some variables don't get created if they aren't used (multiple exit points).

Variable names like 'i' might be ok for loops because 'i' normally stands for "index". Variable names like "iter" doesn't say anything... It should be called "item" or "consoleItem" or something.

Well, i don't think you should ever use i. Even if it's just a loop counter. Meaningful names, even in loop counters, can make a huge difference in both code quality, and in avoiding simple mistakes.

Overall a pretty good article though.

 User Rating: 1912   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Really cool article. I've already implemented my own console in a project that just wrapped up, I used char *'s instead of hte STL and I wish I would of used the STL. I am in the process of refactoring my system, and I like some of the ideas presented in this article so far. Can't wait for the next part :)

 User Rating: 1294   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Quote:
Original post by Washu
That's a string, not a list.


Oops + Doh == me :)

On a side note. The author of the flipcode version is Facundo Matias Carreiro, while the gamedev version is written by none other than Dave Astle himself! OMGWTFBBQRIBS!

[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ]
[ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]


 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Quote:
Original post by Seriema
On a side note. The author of the flipcode version is Facundo Matias Carreiro, while the gamedev version is written by none other than Dave Astle himself! OMGWTFBBQRIBS!
Really embarrassing screwup on my part. It's fixed now.

 User Rating: 2088   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Thanks a lot for the comments and critics, hope you can learn something from the article, improve it and use it.
I'm also learning as I write so I promess the second part will be better :D

Facundo

 User Rating: 1015    Report this Post to a Moderator | Link

Nice article.
May I suggest for anyone looking to go a bit further that they check out the boost library (http://www.boost.org/ - How do I make that a link?). I've just finished making a console for my project and I found boost::variant and boost::tokenizer in particular really handy.

- Xavier

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

meink, you can use the normal HTML tags for links. < a href="www.link.com" > linktext < /a >
I'm curious, how did you use boost for your console? :)

[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ]
[ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]


 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

hey, i want to ask you folks a question: why making such a hard work and make your own console, when you can use a scripting language to do that for you and just use the windows console functions to renderit. windows console has built-in history, very easy input and output, different coloring, scrolling suport and is very fast. why making another system for it?in my projects i use win console functions an Lua language to run all my commands(the commands are also done by me and then registered to lua, i don't use lua library functions.

Mihai

 User Rating: 1057   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

meeshoo, have you used the console in Quake and other games with the same type of console? A in-game console is very useful. And cross-platform in itself because as long as the game runs on a platform the console will work too. Having the windows console is inpractical for several reasons. Just imagine you're playing a game and you have a windows console in windows running. Everything you'd do quickly with the console, like changing brightness - enter cheatcodes - switch level - debug, you'd have to change to windows - enter the command - return to the game. Ever alt-tab'ed out of a game? That's pure joy!

using a scripting language as the backbone for the console managing system itself would be an idea, but I have never tried it.

[ ThumbView: Adds thumbnail support for DDS, PCX, TGA and 16 other imagetypes for Windows XP Explorer. ]
[ Chocolate peanuts: Brazilian recipe for home made chocolate covered peanuts. Pure coding pleasure. ]


 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

I'm wondering what other people have done for the rendering section of this code. I'd like to be able to log my console to disk, but that feels like it should be external to the console. Also, I'm wondering if I should have observers on the console, that are notified of updates (since other game subsystems will log messages directly to the console), or if I should just have some internal tracking of "last accessed lines" so a GetRecent() method can spit out any updated messages.

A coworker just suggested making the internal list available for read only, but that seems like it's unnecessarily exposing guts of this class that should be hidden, even though it would be memory efficient.

 User Rating: 1009   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Please *really* use the STL.

Don't use a loop to tokenize the string:

// tokenize
while(index != std::string::npos)
{
// push word
std::string::size_type next_space = m_commandLine.find(' ');
arguments.push_back(m_commandLine.substr(index, next_space));

// increment index
if(next_space != std::string::npos) index = next_space + 1;
else break;
}

Do it with the features that the STL offers:

std::istringstream iss(m_commandLine);

std::copy(std::istream_iterator(iss),
std::istream_iterator(),
std::back_inserter(arguments));

Otherwise good article!

Christian

 User Rating: 1015    Report this Post to a Moderator | Link

I have a question (probably a really stupid one, but anyway) : in the last page of the article, the writer gives an example on how to create new commands for the console. In the example he gave (print_args), he wrote console->print(args[i]);
How come can he do this? Wouldn't he have to instanciate a new console to be able to use the "print" function?

 User Rating: 1028   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I think the author is assuming that Console is externally defined as some pointer to a global console object.

Personally, I just made it a singleton, and created a factory method to access the singleton. I can't see having more than one console in my system anyway.

 User Rating: 1015    Report this Post to a Moderator | Link

Hello,

why use a list for the itens:

std::list <console_item_t> m_itemList;

and not a hashtable mapping the name to a item?

[]s

Túlio Caraciolo

 User Rating: 1025   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

hmm i get some errors:

i have defined m_textBuffer like this in my code:

list<string> *m_lTextBuffer;


These are the errors i get:

.\Console\ConsoleBase.cpp(78) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'std::list<_Ty>::_Iterator<_Secure_validation>'
with
[
_Ty=std::string,
_Secure_validation=false
]
C:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1818) : see declaration of 'std::operator -'
.\Console\ConsoleBase.cpp(78) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'std::list<_Ty>::_Iterator<_Secure_validation>'
with
[
_Ty=std::string,
_Secure_validation=false
]
C:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1818) : see declaration of 'std::operator -'
.\Console\ConsoleBase.cpp(78) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'std::list<_Ty>::_Iterator<_Secure_validation>'
with
[
_Ty=std::string,
_Secure_validation=false
]
C:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1818) : see declaration of 'std::operator -'
.\Console\ConsoleBase.cpp(78) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'std::list<_Ty>::_Iterator<_Secure_validation>'
with
[
_Ty=std::string,
_Secure_validation=false
]
C:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1818) : see declaration of 'std::operator -'
.\Console\ConsoleBase.cpp(78) : error C2676: binary '-' : 'std::list<_Ty>::_Iterator<_Secure_validation>' does not define this operator or a conversion to a type acceptable to the predefined operator
with
[
_Ty=std::string,
_Secure_validation=false
]



All the errors are pointing to these lines:

if(m_lTextBuffer->size() > m_iTextBufferSize)
{
list<string>::iterator it;
line 78: it = m_lTextBuffer->end() - m_iTextBufferSize;
m_lTextBuffer->erase(m_lTextBuffer->begin(), it);
}

I would be grateful if any one could help me with this.

Thanks

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I'm looking for a way to make console in my game, but the thing is, it's in C#. Is there another article similar to this that is not language dependent, or based on C#?

Google searches turn up either console gaming (xbox, etc), how to enable console in Steam games, or how to program for a console. It's like searching for needle in a haystack.

Thanks!

 User Rating: 1128   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: