Roguelike Game in C++17
Console and moving around
At this time the code compiles, generated an executable which runs AND
presents a window with @ in middle of the screen. But that does not
a roguelike make. So, onwards we go…
Goals
For this section the goals are:
- Refactor code so it's amenable to change.
- Load Custom font file.
- Handle input.
- Move
@around using arrow keys (←,↑,→, and↓). - Exit when
ESCis pressed. - Toggle
fullscreenmode withAlt+Enter.
- Move
That list doesn't look too bad, relatively simple goals.
Refactoring
The code renders @ in a hard coded position directly on what tcod
calls the root console. Ideally, it would be rendered on to some
offscreen buffer, which would then be merged with root console when its
time to display. Additionally, we want @ to be more 'dynamic'.
Within the refactored code, offscreen buffer is called game_console,
it has the same dimensions as root console. Before root console is displayed
on to the screen, game_console is merged using blit method.
The @'s position is now determined by value of two variables player_x
and player_y. Also it's color is explicitly set to be white. It is drawn
on game_console using putChar method.
Loading Custom Font
For this we use setCustomFont method of the TCODConsole class. Reading
the documentation of tcod, we learn that setCustomFont must be called
before initRoot is called.
Another thing that needs to be done to get font to work, is we need to copy
a font file to same directory as executable. Techincally, we could pass any
path to setCustomFont, but for simplicity, I am just copying the
arial10x10.png to same directory as CMake's Build output. The file is
provided by tcod in it's data/fonts directory. Feel free to use a
different font file, if you don't like arial.
The copying action is done by CMake, by declaring/updating the custom target
that was setup for project to consume tcod. CMake target is now updated
to copy 3 files, two .dll and one .png.
Handling Input
Compared to font loading, this is bit more involved. Basically, this task can be divided into two smaller concepts.
- Action handling.
- Key press handling.
Action handling
Player in our game can do set of actions on any given turn/frame. For the moment these are
- Do nothing.
- Exit the game.
- Move one square in X or Y direction.
- Toggle fullscreen mode between
windowed<->fullscreen.
Game doesn't really care which key is pressed to perform these actions. We'll get to mapping actions to keypresses in next section.
To capture our actions in code we use an enumeration in C++. It has
four actions identified in previous paragraph. At the moment our
actions list is very small, so the code to act on any given action is
within main function. It's a very simple switch statement block.
In future, we may change this aspect, for now it's good enough.
The switch expects a std::pair with .first type being action and
.second type being data. For the moment, data is only used by move
case, where .second is another std::pair type and is used to update
player position. Second std::pair is typedef'd to move_dir.
move_dir's two members first and second, representing the offset
value to move the player in X and Y axis respectively.
Key press handling
The function handling key presses will transform the key pressed into an action from our actions list.
Returned object by our input handler, is going to be a tuple std::pair.
Tuple will have to things in it, in order
- one action value from within our actions enum.
- one data object held by
std::anytype. Depending on the action, data can be either astd::pairtype, ornullptr
For our current set of actions, we have to check about 6 different key presses.
ESCtoExit the gameUPtoMoveinyaxis by-1DOWNtoMoveinyaxis by+1LEFTtoMoveinxaxis by-1RIGHTtoMoveinxaxis by+1ALT + ENTERtoToggle Fullscreen
When any of the arrows keys are pressed, we populate .second member of
std::pair with position value. In all cases, we populate .first member
with action value. std::pair is then returned to caller, which is main,
where above described Action Handling occurs.
Now we have @ displayed on the screen which can be moved around using arrow
keys. The application can exit when ESC key is pressed and it'll go fullscreen
when ALT and ENTER keys are pressed together.
Links
╣ GitHub Repo ╠═══
╣ Home ╠═══
╣ Prev: Environment and project setup ╠═══
╣ Next: The entity and the map ╠═══