My roguelike development blog ~ part 4
In my last tutorial I promised to show how you separate your cursor positioning into a separate function, and how to add color to your roguelike indie knockout title. We will also learn how to add a console title, a simple way to run our program in fullscreen and to remove the console cursor (the blinking _) from the commandline terminal.
If you have followed along so far, you have a simple program that shows us a main menu where you have to options; New game and Quit. Our menu is just printed to the screen at the current cursor position. We then used a built in Windows.h helper function called SetConsoleCursorPosition() to position our cursor at the first line of the menu, but what if we want to position the menu at the center of the screen and position the cursor next to it?
Let us extract the helper function into our own customizable function to position the cursor where we want.
Positioning the cursor
So far our own functions have not included anything inside the parameter list, but this function needs to know the x- and y-coordinate to position the cursor at. Since this function basically places the cursor at the given coordinates, then returns to where it was called to continue program execution, we don't need to return anything when our positioning function finishes, so a return type void (nothing returned) is fine. As always we start writing a new function by building a function prototype in our function definition (GameManager.h). I choose to call it SetCursor and feed the x- and y-position in as parameters when calling this function. With a void return type, our function definition should look like this:
void SetCursor(int x, int y);
To implement this so this function we open our GameManager.cpp file, and add our new function below our other functions:
void GameManager::SetCursor(int x, int y) {
} // END SetCursor
When we used SetConsoleCursorPosition() to place the menu cursor infront of the menu, we defined a COORD point in GameManager.h. To easily identify a variable and its use, we should be careful when naming our functions/variables. A better name to identify this variables use could have been cursorPos. Luckily for us most modern programming IDEs have a method to replace text, usually found by pressing ctrl+f.
We could still use this name, but to keep things manageble for when our project contains a large amount of custom functions we should consider naming any function/variable with a name identifying where it's used or what it is used for. Using a more specified variable name will (hopefully) prevent variable and function shadowing later on.
To complete the SetCursor(int x, int y) we add only two more lines of code:
void GameManager::SetCursor(int x, int y) {
COORD position = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
} // END SetCursor
We now replace the direct calls to SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point) in our Menu() with SetCursor(point.X, point.Y).
Adding color
Windows console is a very limited plattform, and doesn't allow a lot of colors to paint it any prettier. It will allow us to use 16 colors as text color, and the same 16 as background color. The color palette is as following:
0 BLACK,
1 BLUE,
2 GREEN,
3 CYAN,
4 RED,
5 MAGENTA,
6 BROWN,
7 LIGHTGRAY,
8 DARKGRAY,
9 LIGHTBLUE,
10 LIGHTGREEN,
11 LIGHTCYAN,
12 LIGHTRED,
13 LIGHTMAGENTA,
14 YELLOW,
15 WHITE
This function should take two parameters when it's called, the desired foreground color and background color. We don't need to return anything when the function finishes, so return type is void. Our function definition should look like this:
void SetColor(int fcolor, int bcolor);
Over in GameManager.cpp we add a new line below SetCursor() and add the function implementation like shown here:
void GameManager::SetColor(int fcolor, int bcolor) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), fcolor + (bcolor * 16));
} // END SetColor
The built in Windows helper function SetConsoleTextAttribute() takes a handle to the console window, and the color code for the fore- and background color. It's as easy as that!
Setting the console window title
Adding a function to set the console window title is also a short and simple process. Again there is no need to return anything (if there are no errors we'll see the window name at the top of the console window), so return type should be void. Our function prototype needs to take the program name (a text string) as a parameter, so we write:
void SetTitle(string title);
The function definition utilizes the Windows helper function SetConsoleTitle() and adds our parameter title into the helper function with c_str(). Your implementation should look like this:
void GameManager::SetTitle(string title) {
SetConsoleTitle(title.c_str());
} // END SetTitle
If your compiler issues a warning or don't want to compile this, try including <string>>.
Running the program in fullscreen
Our program has so far just been running in a windowed mode, and you may have tried to maximize it by pressing the maximize-button in the top left corner. If you are familiar with the commandline, you might even be aware that you can run the commandline window in fullscreen by pressing alt+enter. What we want is to run our program in fullscreen mode from the start, so how can we achieve that?
Again we use a built in helper function. Windows.h has a function to simulate keyboard presses, so lets write a simple function that simulates pressing alt+enter.
Beginning in GameManager.h we create a function called SetFullscreen(). This doesn't take a return type or anything as parameter, so make it short and simple:
void SetFullscreen();
Adding this function into GameManager.cpp we end up with:
void GameManager::SetFullscreen() {
keybd_event(VK_MENU, 0x36, 0, 0);
keybd_event(VK_RETURN, 0x1C, 0, 0);
keybd_event(VK_RETURN, 0x1C, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, 0x36, KEYEVENTF_KEYUP, 0);
} // END SetFullscreen
Running this function in you program puts the program in fullscreen mode, but leaves a scrollbar on the right side. I'll show you how to remove this in a later tutorial.
Removing the visible console cursor
Last, but not least, we will remove the console cursor from our program. The prototype function needs no return, so another void. We name it SetFullscreen(), plane and simple, and take a boolean variable to indicate wether the cursor is shown or not. Written out in our GameManager.h we get:
void ShowCursor(bool showCursor);
Next up, implementing this function we end up with:
void GameManager::ShowCursor(bool showCursor) {
HANDLE hCursor = ::GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hCursor, &cursorInfo);
if (cursorInfo.bVisible == false) {
cursorInfo.bVisible = true;
} else if (cursorInfo.bVisible == true) {
cursorInfo.bVisible = false;
}
SetConsoleCursorInfo(hCursor, &cursorInfo);
}
Please note that calling this function should be done before any calls to SetFullscreen(), as removing the cursor after setting the program to run in fullscreen seems to makes the cursor reappear.
This is all for now! We have learned to position the cursor where we want and to add color to the text and background. We also learned how to add a console title, and how to make the console window run in fullscreen without the cursor visible.
Next time around we will begin to look into creating the game window and how to draw it to screen.
To see more - upvote this post and follow me @jonrhythmic
During setting the colour, you have "bcolor * 16" as the background colour parameter for SetConsoleTextAttribute. Do you know why it's multiplied by 16?
Is there a reason for the leading "::" before calling GetStdHandle in ShowCursor?
Foreground color is stored as a single byte, with the background color being stored in a double-byte character set (known as a expanded 8-bit character set). A single-byte character set (SBCS) is a mapping of 256 individual characters to their identifying code values, implemented as a code page. To get the correct result you multiply the foreground color with the expanded bit, so the result is inbetween 0-256 (16 * 16).
The leading scope resolution operator before GetStdHandle in ShowCursor is a trick to call the function directly to avoid any overloading if the function is used anywhere else.
Thanks. Excellent information for me, as well as for those learning coding for the first time too. Sometimes little things like this aren't learnt amongst the big picture things when studying for a degree even
Hey bro here's a tip; don't use 5 keywords for your blog posts, I've read that 4 are enough otherwise your blog will be placed in the 'main' category.
@alphapack Thanks for the tip! I'll try that next time.
EDIT: Changed this post to see if there is any increased response.
nice post. ;)
Thank you!
This post was resteemed by @resteembot!
Good Luck!
Learn more about the @resteembot project in the introduction post.