#3 Lina Engine: Console
Hey there folks! Today I talk about, the mighty backbone of all the systems, maybe one of the most important sub-system in our engine, the Console. So for Lina Engine, we started up a Console application in C++. So, initially, basically all we get is the command console, and we can print out on this console to debug our systems. However, using a simple std::cout isn't going to be sufficient for our needs. Writing a console system is crucial, because this way, we can debug and fake the existence of the systems without implementing them. We can print to console on any particular system, on it's initialization or dead, or when it's updater or it faces some problems. This way, we can just create classes for our systems, not need to implement them yet, and fake their existence so we can further and better grasp the understanding on our developing architecture.
Design Choice For Console
First thing that came to our minds while developing the console is to decide how to implement it, in the means of dependency injection. Any particular system or a sub-system should be able to print something on the console. Firstly, we of course thought about a singleton console class. However, we do not want to mess with the singletons just yet, yes singleton design pattern is great and work well for the objects that we want to have their lifetime to last for the whole program, but they do hide dependencies and this can create further problems. So, we thought, since the console would be only for debugging purposes and we will exclude any console calls from the build later on, we can create a separate console object instance on the stack in whichever code-block we want to print something in. This way, if some problem is to occur on our console, we would know whoever is using it since the dependencies would be visible from the header files.
Implementation of Console
We want our console to have particular features. First, it should of course print out messages, then it can also keep track of the sender via a simple copied string, to print out who sent that message. Really basic implementation would be something like this:
As you can see we print out the sender, the message, and a timestamp, pretty nice. But you know what would be cool, giving different colors to the messages. This way, we can print out successful initialization messages with, lets say green, while we can print out the errors with red. To do this, we would define some color values, and get the current console we are printing it to process some attribute for it. At this step, SDL comes to our help. We can use SDL to get the console, run a simple if block to set the desired color out of a message type enumeration. Then apply that color attribute for that current message block. Which would look something like this:
This would give us a nice console, that looks like this:
Everything is great for now, we can fake our systems. However, in the cases where I would like to print a message to the console every frame, writing it to a new line might be a little bit hard to track. So we need a member function to print a message, just like the above one, but on the same line. We could use simple booleans to the parameter of the above function, however, for the sake of simplicity i would rather write a separate one for this task. We would use '/r' to get the console to the beginning of the current line, after writing a line and flushing it with std::flush. And that would look like:
And our result would look like:
So yeah, that's it. We have a implemented a simple console, and now we can call it via any object instance of it, they will all write to the same command prompt. We can make it write stuff separately, or on the same line. In the future, we plan to implement a static console manager to create separate command prompts if desired to specifically keep track of the debugging on a single system, however, this is sufficient enough for now.
Hope it was helpful in some way, see you on the next post!