http://roguebasin.com/api.php?action=feedcontributions&user=Fsolt&feedformat=atomRogueBasin - User contributions [en]2024-03-29T01:11:40ZUser contributionsMediaWiki 1.36.0http://roguebasin.com/index.php?title=User_talk:Weilian&diff=44920User talk:Weilian2017-04-26T19:11:09Z<p>Fsolt: /* Roguelike tutorial with tdl */ new section</p>
<hr />
<div>Hi, <br />
<br />
Just wanted to thank you for your awesome tutorial. <br />
<br />
As someone who just got started into Roguelike development, it's been a really great help, because I couldn't figure out by myself how to convert the snippets from the libtcod tutorial to Python 3.<br />
<br />
So, thanks a lot for what you're doing ! <br />
<br />
--[[User:Edern|Edern]] ([[User talk:Edern|talk]]) 18:42, 28 November 2016 (CET)<br />
<br />
== Roguelike tutorial with tdl ==<br />
<br />
Any plans to finish the tutorial?<br />
Thanks for everything so far!<br />
-Fsolt</div>Fsolthttp://roguebasin.com/index.php?title=Roguelike_Tutorial,_using_python3%2Btdl,_part_1_code&diff=44919Roguelike Tutorial, using python3+tdl, part 1 code2017-04-26T18:52:06Z<p>Fsolt: changed full screen toggle to toggle</p>
<hr />
<div><center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center><br />
This is part of a series of tutorials; the main page can be found [[Roguelike Tutorial, using python3+tdl|here]].<br />
<br />
The tutorial uses tdl version 1.5.3 and Python 3.5<br />
<br />
</center></td></tr></table></center><br />
<br />
== Showing the @ on screen ==<br />
<div style="background-color: #EEEEEE; border-style: dotted"><syntaxhighlight lang="python"><br />
#!/usr/bin/env python3<br />
<br />
import tdl<br />
<br />
#actual size of the window<br />
SCREEN_WIDTH = 80<br />
SCREEN_HEIGHT = 50<br />
<br />
LIMIT_FPS = 20 #20 frames-per-second maximum<br />
<br />
<br />
tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)<br />
<br />
console = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="Roguelike", fullscreen=False)<br />
<br />
tdl.setFPS(LIMIT_FPS)<br />
<br />
while not tdl.event.is_window_closed():<br />
<br />
console.draw_char(1, 1, '@', bg=None, fg=(255,255,255))<br />
<br />
tdl.flush()<br />
</syntaxhighlight></div><br />
<br />
<br />
== Moving around ==<br />
<br />
<div style="background-color: #EEEEEE; border-style: dotted"><syntaxhighlight lang="python"><br />
#!/usr/bin/env python3<br />
<br />
import tdl<br />
<br />
#actual size of the window<br />
SCREEN_WIDTH = 80<br />
SCREEN_HEIGHT = 50<br />
<br />
LIMIT_FPS = 20 #20 frames-per-second maximum<br />
<br />
def handle_keys():<br />
global playerx, playery<br />
<br />
'''<br />
#realtime<br />
<br />
keypress = False<br />
for event in tdl.event.get():<br />
if event.type == 'KEYDOWN':<br />
user_input = event<br />
keypress = True<br />
if not keypress:<br />
return<br />
'''<br />
<br />
#turn-based<br />
user_input = tdl.event.key_wait()<br />
<br />
if user_input.key == 'ENTER' and user_input.alt:<br />
#Alt+Enter: toggle fullscreen<br />
tdl.set_fullscreen(not tdl.get_fullscreen())<br />
<br />
elif user_input.key == 'ESCAPE':<br />
return True #exit game<br />
<br />
#movement keys<br />
if user_input.key == 'UP':<br />
playery -= 1<br />
<br />
elif user_input.key == 'DOWN':<br />
playery += 1<br />
<br />
elif user_input.key == 'LEFT':<br />
playerx -= 1<br />
<br />
elif user_input.key == 'RIGHT':<br />
playerx += 1<br />
<br />
<br />
#############################################<br />
# Initialization & Main Loop #<br />
#############################################<br />
<br />
tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)<br />
console = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="Roguelike", fullscreen=False)<br />
tdl.setFPS(LIMIT_FPS)<br />
<br />
playerx = SCREEN_WIDTH//2<br />
playery = SCREEN_HEIGHT//2<br />
<br />
while not tdl.event.is_window_closed():<br />
<br />
console.draw_char(playerx, playery, '@', bg=None, fg=(255,255,255))<br />
<br />
tdl.flush()<br />
<br />
console.draw_char(playerx, playery, ' ', bg=None)<br />
<br />
#handle keys and exit game if needed<br />
exit_game = handle_keys()<br />
if exit_game:<br />
break<br />
</syntaxhighlight></div><br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Roguelike_Tutorial,_using_python3%2Btdl,_part_1&diff=44918Roguelike Tutorial, using python3+tdl, part 12017-04-26T18:51:08Z<p>Fsolt: changed so full screen toggle actually toggles.</p>
<hr />
<div><center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center><br />
This is part of a series of tutorials; the main page can be found [[Roguelike Tutorial, using python3+tdl|here]].<br />
<br />
The tutorial uses tdl version 1.5.3 and Python 3.5<br />
<br />
</center></td></tr></table></center><br />
<br />
<br />
__TOC__<br />
<br />
<center><h1>'''Graphics'''</h1></center><br />
<br />
== Setting it up ==<br />
<br />
Ok, now that we got that out of our way let's get our hands dirty!<br />
<br />
* If you haven't yet, [http://www.python.org/download/ download and install Python 3.5].<br />
<br />
* Install the tdl module for python3. In windows:<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">python3 -m pip install tdl</syntaxhighlight></div><br />
<br />
* Note: If you're working on a fresh environment or a new PC, don't forget to install the latest Microsoft Visual C++ runtime. If you've made sure that your x32 or x64 version of Python matches both your operating system and the install packages and you're still getting "ImportError: DLL Load Failed" when you try to execute the code, this may be the issue.<br />
<br />
* In Linux:<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">pip3 install tdl</syntaxhighlight></div><br />
<br />
Now to create your project's folder. Create an empty file with a name of your choice, like ''firstrl.py''. <br />
You'll also need a font file in png format. We chose '' arial10x10.png'', which you can download [https://github.com/HexDecimal/python-tdl/blob/master/fonts/libtcod/arial10x10.png here].<br />
<br />
More fonts are available [https://github.com/HexDecimal/python-tdl/tree/master/fonts/libtcod here].<br />
<br />
== Choice of code editor ==<br />
<br />
If you're just starting out with Python, you'll find that many Python coders just use a simple editor and run their scripts from a console to see any debugging output. Most Python coders don't feel the need to use a fancy IDE! On Windows, Notepad++ is an excellent bet; most Linux programmers already have an editor of choice. Almost all editors allow you to configure shortcut keys (like F5 for instance) to quickly run the script you're editing, without having to switch to a console.<br />
<br />
[[Complete Roguelike Tutorial, using Python+libtcod, extras#A neat Python shortcut for Notepad++|See this page from the libtcod tutorial]] if you want to set up a Notepad++ shortcut with a couple of nice features for debugging, or if you tried to roll your own and hit the infamous "module not found" error.<br />
<br />
<br />
== Showing the @ on screen ==<br />
<br />
This first part will be a bit of a crash-course. The reason is that you need a few lines of boilerplate code that will initialize and handle the basics of a libtcod window. And though there are many options, we won't explain them all or this part will really start to drag out. Fortunately the code involved is not as much as in many other libraries!<br />
<br />
First we import the library.<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">import tdl</syntaxhighlight></div><br />
<br />
<br />
Then, a couple of important values. It's good practice to define special numbers that might get reused. Many people capitalize them to distinguish from variables that may change.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">SCREEN_WIDTH = 80<br />
SCREEN_HEIGHT = 50<br />
LIMIT_FPS = 20</syntaxhighlight></div><br />
<br />
<br />
Now we're going to use a custom font! It's pretty easy. You can find many choices [https://github.com/HexDecimal/python-tdl/tree/master/fonts/libtcod here]. Remember however that they can be in different '''formats''', and you'll need to tell it about this. This one is "grayscale" and using the "tcod layout", which we indicate by setting the parameter ''altLayout=True''. Most fonts are in this format and thus end with ''_gs_tc''. If you wanna use a font with a different layout or make your own, the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_set_custom_font.html?c=false&cpp=false&cs=false&py=true&lua=false docs on the subject] are really informative. You can worry about that at a later time though. Notice that the size of a font is automatically detected.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)<br />
</syntaxhighlight></div><br />
<br />
<br />
This is probably the most important call, initializing the window. We're specifying its size, the title (change it now if you want to), and the last parameter tells it if it should be fullscreen or not.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">console = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="Roguelike", fullscreen=False)</syntaxhighlight></div><br />
<br />
<br />
For a real-time roguelike, you wanna limit the speed of the game (frames-per-second or FPS). If you want it to be turn-based, ignore this line. (This line will simply have no effect if your game is turn-based.)<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #D0FFC2"><syntaxhighlight lang="python">tdl.setFPS(LIMIT_FPS)</syntaxhighlight></div><br />
<br />
<br />
Now the main loop. It will keep running the logic of your game as long as the window is not closed.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">while not tdl.event.is_window_closed():</syntaxhighlight></div><br />
<br />
<br />
For each iteration we'll want to print something useful to the window. If your game is turn-based each iteration is a turn; if it's real-time, each one is a frame. <br />
<br />
Now print a character to the coordinates (1,1). Can you guess what that character is? No, it doesn't move yet! <br />
<br />
Don't forget the indentation at the beginning of the line, it's extra-important in Python. '''Make sure you don't mix tabs with spaces for indentation!''' This comes up often if you copy-and-paste code from the net, and you'll see an error telling you something about the indentation (that's a pretty big clue right there!). Choose one option and stick with it. In this tutorial we're using the 4-spaces convention, but tabs are easy to work with in many editors so they're a valid choice too.<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> console.draw_char(1, 1, '@', bg=None, fg=(255,255,255))</syntaxhighlight></div><br />
<br />
Here we're setting the text color to be white. In RGB color codes, that's ''255,255,255'' [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/color.html?c=false&cpp=false&cs=false&py=true&lua=false There's a good list of colors you can use here], along with some info about mixing them and all that. Alternatively, we can use hexidecimal color codes. For white, that would be: ''0xFFFFFF'' (note that there are no quotations around it, since Python will read it as a hexidecimal integer, not a string.)<br />
<br />
<br />
At the end of the main loop you'll always need to present the changes to the screen. This is called ''flushing'' the console and is done with the following line.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> tdl.flush()</syntaxhighlight></div><br />
<br />
<br />
Ta-da! You're done. Run that code and give yourself a pat on the back!<br />
<br />
Note that since we don't have any input handling code, the game may crash on exit (it won't process the OS's requests to close). Oops! Don't worry though, this problem will go away as soon as we add keyboard support.<br />
<br />
[[Roguelike Tutorial, using python3+tld, part 1 code#Showing the @ on screen|Here]]'s the complete code so far.<br />
<br />
== Moving around ==<br />
<br />
That was pretty neat, huh? Now we're going to move around that @ with the keys!<br />
<br />
First, we need to keep track of the player's position. We'll use these variables for that, and take the opportunity to initialize them to the center of the screen instead of the top-left corner. This can go just before the main loop.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">playerx = SCREEN_WIDTH//2<br />
playery = SCREEN_HEIGHT//2</syntaxhighlight></div><br />
<br />
<br />
There are functions to check for pressed keys. When that happens, just change the coordinates accordingly. Then, print the @ at those coordinates. We'll make a separate function to handle the keys.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">def handle_keys():<br />
global playerx, playery<br />
<br />
user_input = tdl.event.key_wait()<br />
<br />
#movement keys<br />
if user_input.key == 'UP':<br />
playery -= 1<br />
<br />
elif user_input.key == 'DOWN':<br />
playery += 1<br />
<br />
elif user_input.key == 'LEFT':<br />
playerx -= 1<br />
<br />
elif user_input.key == 'RIGHT':<br />
playerx += 1</syntaxhighlight></div><br />
<br />
<br />
Done! These are the arrow keys, if you want to use other keys here's a [https://pythonhosted.org/tdl/tdl.event.KeyEvent-class.html#key reference]. Most codes are self-explanatory. KP stands for ''keypad''. <br />
<br />
While we're at it, why not include keys to toggle fullscreen mode, and exit the game? You can put this just above the movement keys.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> if user_input.key == 'ENTER' and user_input.alt:<br />
#Alt+Enter: toggle fullscreen<br />
tdl.set_fullscreen(not tdl.get_fullscreen())<br />
<br />
elif user_input.key == 'ESCAPE':<br />
return True #exit game</syntaxhighlight></div><br />
<br />
From now on, we'll show code for a <span style="background-color: #D0FFC2">'''real-time game'''</span> with a green background, and code for a <span style="background-color: #DFEEFF">'''turn-based game'''</span> with a blue background.<br />
<br />
So far, we've been writing a turn-based game. Then the game won't go on unless the player presses a key. So effectively you have a turn-based game now. However, we'll introduce another option at this point. If we comment out the line ''user_input = tdl.event.key_wait()'' and replace it with the following block of code, we'll have a real-time game:<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #D0FFC2"><syntaxhighlight lang="python"> #realtime<br />
keypress = False<br />
for event in tdl.event.get():<br />
if event.type == 'KEYDOWN':<br />
user_input = event<br />
keypress = True<br />
if not keypress:<br />
return</syntaxhighlight></div><br />
<br />
This works because ''tdl.event.get()'' won't block the game.<br />
<br />
Now, the main loop needs to call this function in order for it to work. If the returned value is True, then we "break" from the main loop, ending the game. The inside of the main loop should now look like this:<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">console.draw_char(playerx, playery, '@', bg=None, fg=(255,255,255))<br />
<br />
tdl.flush()<br />
<br />
#handle keys and exit game if needed<br />
exit_game = handle_keys()<br />
if exit_game:<br />
break</syntaxhighlight></div><br />
<br />
<br />
The reason why we draw stuff before handling key input is that, in a turn-based game, the first screen is shown before the first key is pressed (otherwise the first screen would be blank).<br />
<br />
One more thing! If you try that, you'll see that moving you leave around a trail of little @'s. That's not what we want! We need to clear the character at the last position before moving to the new one, this can be done by simply printing a space there. Put this just before ''exit_game = handle_keys()''.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> console.draw_char(playerx, playery, ' ', bg=None)</syntaxhighlight></div><br />
<br />
<br />
[[Roguelike Tutorial, using python3+tdl, part 1 code#Moving around|Here]]'s a rundown of the whole code so far.<br />
<br />
[[Roguelike Tutorial, using python3+tdl, part 2|Go on to the next part]].<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod,_part_2&diff=44916Complete Roguelike Tutorial, using python+libtcod, part 22017-04-26T03:34:47Z<p>Fsolt: typo</p>
<hr />
<div><center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center><br />
This is part of a series of tutorials; the main page can be found [[Complete Roguelike Tutorial, using python+libtcod|here]].<br />
<br />
The tutorial uses libtcod version 1.6.0 and above.<br />
<br />
If you choose to use 1.5.1, you can find the old version [http://www.roguebasin.com/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod,_part_2&oldid=42384 here].<br/><br />
If you choose to use 1.5.0, you can find the old version [http://roguebasin.roguelikedevelopment.org/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod,_part_2&oldid=29861 here].<br />
</center></td></tr></table></center><br />
<br />
<br />
__TOC__<br />
<br />
<center><h1>'''The object and the map'''</h1></center><br />
<br />
== Off-screen consoles ==<br />
<br />
There's one small thing we need to get out of the way before we can continue. Notice that the drawing functions we called (''console_set_default_foreground'' and ''console_put_char'') have their first argument set to 0, meaning that they draw on the ''root console''. This is the buffer that is shown directly on screen.<br />
<br />
It can be useful, however, to have other buffers to store the results of drawing functions without automatically showing them to the player. This is akin to drawing surfaces or buffers in other graphics libraries; but instead of pixels they store characters and colors so you can modify them at will. Some uses of these off-screen consoles include semi-transparency or fading effects and composing GUI panels by blitting them to different portions of the root console. We're going to draw on an off-screen console from now on. The main reason is that not doing so would mean that later on you can't compose different GUI panels as easily, or add certain effects.<br />
<br />
First, create a new off-screen console, which for now will occupy the whole screen, but this can be changed later. We'll use a simple name like ''con'' because it will be used '''a lot'''! You can put this in the initialization, right after ''console_init_root''.<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">con = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)</syntaxhighlight></div><br />
<br />
<br />
Now change the first argument of ''console_put_char'' (there are 2 calls to this function) and ''console_set_default_foreground'', from ''0'' to ''con''. They're now drawing on the new console.<br />
<br />
Finally, just before ''console_flush()'', blit the contents of the new console to the root console, to display them. The parameters may look a bit mysterious at first, but they're just saying that the source rectangle has its top-left corner at coordinates (0, 0) and is the same size as the screen; the destination coordinates are (0, 0) as well. Check the documentation on [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_offscreen.html?c=false&cpp=false&cs=false&py=true&lua=false#6 the console_blit function] for more details.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)</syntaxhighlight></div><br />
<br />
<br />
That was a lot of talk for so little code and no visible change! The next section will surely be much more interesting, as we'll introduce our first dummy NPC among other things. Remember to check back the above documentation page when you get to coding your GUI.<br />
<br />
== Generalizing ==<br />
<br />
Now that we have the @ walking around, it would be a good idea to step back and think a bit about the design. Having variables for the player's coordinates is easy, but it can quickly get out of control when you're defining things such as HP, bonuses, and inventory. We're going to take the opportunity to generalize a bit.<br />
<br />
Now, there ''can'' be such a thing as over-generalization, but we'll try not to fall in that trap. What we're going to do is define the player as a game ''Object'', by creating that class. It will hold all position and display information (character and color). The neat thing is that the player will just be one instance of the ''Object'' class -- it's general enough that you can re-use it to define items on the floor, monsters, doors, stairs; anything representable by a character on the screen. Here's the class, with the initialization, and three common methods ''move'', ''draw'' and ''clear''. The code for drawing and erasing is the same as the one we used for the player earlier.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">class Object:<br />
#this is a generic object: the player, a monster, an item, the stairs...<br />
#it's always represented by a character on screen.<br />
def __init__(self, x, y, char, color):<br />
self.x = x<br />
self.y = y<br />
self.char = char<br />
self.color = color<br />
<br />
def move(self, dx, dy):<br />
#move by the given amount<br />
self.x += dx<br />
self.y += dy<br />
<br />
def draw(self):<br />
#set the color and then draw the character that represents this object at its position<br />
libtcod.console_set_default_foreground(con, self.color)<br />
libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)<br />
<br />
def clear(self):<br />
#erase the character that represents this object<br />
libtcod.console_put_char(con, self.x, self.y, ' ', libtcod.BKGND_NONE)</syntaxhighlight></div><br />
<br />
Please note that there are ''two'' underscores on each side of <code>__init__</code>!<br />
<br />
Now, before the main loop, instead of just setting the player's coordinates, we create it as an actual ''Object''. We also add it to a list, that will hold ''all'' objects that are in the game. While we're at it we'll add a yellow @ that represents a non-playing character, like in an RPG, just to test it out!<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">player = Object(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, '@', libtcod.white)<br />
npc = Object(SCREEN_WIDTH/2 - 5, SCREEN_HEIGHT/2, '@', libtcod.yellow)<br />
objects = [npc, player]</syntaxhighlight></div><br />
<br />
<br />
We'll have to make a couple of changes now. First, in the ''handle_keys'' function, instead of dealing directly with the player's coordinates, we can use the player's ''move'' method with the appropriate displacement. Later this will come in handy as it can automatically check if the player (or another object) is about to hit a wall. Secondly, the main loop will now clear all objects like this:<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> for object in objects:<br />
object.clear()</syntaxhighlight></div><br />
<br />
<br />
And draw them like this:<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> for object in objects:<br />
object.draw()</syntaxhighlight></div><br />
<br />
<br />
Ok, that's all! A fully generic object system. Later, this class can be modified to have all the special info that items, monsters and all that will require. But we can add that as we go along!<br />
<br />
[[Complete Roguelike Tutorial, using python+libtcod, part 2 code#Generalizing|Here]]'s the code so far.<br />
<br />
== The Map ==<br />
<br />
Just like how you generalized the concept of the player object, you'll now do the same thing with the dungeon map. Your map will be a two-dimensional array of tiles where all your dungeon adventuring will happen. We'll start by defining its size at the top of the file. It's not quite the same size as the screen, to leave some space for a panel to show up later (where you can show stats and all). We'll try to make this as configurable as possible, this should suffice for now!<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">MAP_WIDTH = 80<br />
MAP_HEIGHT = 45</syntaxhighlight></div><br />
<br />
<br />
Next, the tile colors. For now there are two tile types -- wall and ground. These will be their "dark" colors, which you'll see when they're not in FOV; their "lit" counterparts are not needed right now. Notice that their values are between 0 and 255, if you found colors on the web in hexadecimal format you'll have to convert them with a calculator. Finding RGB values by educated trial-and-error works at first but with time you'll have a set of colors that don't mix together very well (contrast and tone as perceived by the human eye, and all that stuff), so it's usually better to look at a chart of colors; just search for "html colors" and use one you like.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">color_dark_wall = libtcod.Color(0, 0, 100)<br />
color_dark_ground = libtcod.Color(50, 50, 150)</syntaxhighlight></div><br />
<br />
<br />
What sort of info will each tile hold? We'll start simple, with two values that say whether a tile is passable or not, and whether it blocks sight. In this case, it's better to seperate them early, so later you can have see-through but unpassable tiles such as chasms, or passable tiles that block sight for secret passages. They'll be defined in a Tile class, that we'll add to as we go. Believe me, this class will quickly grow to have about a dozen different values for each tile!<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">class Tile:<br />
#a tile of the map and its properties<br />
def __init__(self, blocked, block_sight = None):<br />
self.blocked = blocked<br />
<br />
#by default, if a tile is blocked, it also blocks sight<br />
if block_sight is None: block_sight = blocked<br />
self.block_sight = block_sight</syntaxhighlight></div><br />
<br />
<br />
As promised, the map is a two-dimensional array of tiles. The easiest way to do that is to have a list of rows, each row itself being a list of tiles, since there are no native multi-dimensional arrays in Python. We'll build it using a neat trick, [http://docs.python.org/tutorial/datastructures.html#list-comprehensions list comprehensions]. See, the usual way to build lists (from C++ land) is to create an empty list, then iterate with a ''for'' and add elements gradually. But in Python, the syntax [''element'' for ''index'' in ''range''], where ''index'' and ''range'' are the same as what you'd use in a ''for'', will return a list of ''element''s. Just take a second to understand that sentence if you never worked with that before. With two of those, one for rows and another for tiles in each row, we create the map in one fell swoop! The linked page has a ton of examples on that, and also an example of [http://docs.python.org/tutorial/datastructures.html#nested-list-comprehensions nested list comprehensions] like we're using for the map. Well, that's an awful lot of words for such a tiny piece of code!<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">def make_map():<br />
global map<br />
<br />
#fill map with "unblocked" tiles<br />
map = [[ Tile(False)<br />
for y in range(MAP_HEIGHT) ]<br />
for x in range(MAP_WIDTH) ]</syntaxhighlight></div><br />
<br />
<br />
Accessing the tiles is as easy as ''map[x][y]''. Here we add two pillars (blocked tiles) to demonstrate that, and provide a simple test.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> map[30][22].blocked = True<br />
map[30][22].block_sight = True<br />
map[50][22].blocked = True<br />
map[50][22].block_sight = True</syntaxhighlight></div><br />
<br />
<br />
One very important piece of advice: ''in list comprehensions, always call the constructor of the objects you're creating'', like we did with Tile(False). If we had tried to first create an unblocked tile like ''floor = Tile(False)'' and then in the list comprehension just refer to that same ''floor'', we'd get all sorts of weird bugs! This is a common rookie (and veteran!) mistake in Python. That's because all elements in the list would point to the exact same Tile (the one you defined as ''floor''), not copies of it. Changing a property of one element would appear to change it in other elements as well! Calling the constructor for every element ensures that each is a distinct instance.<br />
<br />
<br />
Don't worry, we're already close to a playable version! Since we need to draw both the objects and the map, it now makes sense to put them all under a new function instead of directly in the main loop. Take the object rendering code to a new ''render_all'' function, and in its place (in the main loop) call ''render_all()''.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">def render_all():<br />
#draw all objects in the list<br />
for object in objects:<br />
object.draw()</syntaxhighlight></div><br />
<br />
<br />
Still in the same function, we can now go through all the tiles and draw them to the screen, with the background color of a console character representing the corresponding tile. This will render the map.<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> for y in range(MAP_HEIGHT):<br />
for x in range(MAP_WIDTH):<br />
wall = map[x][y].block_sight<br />
if wall:<br />
libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET )<br />
else:<br />
libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET )</syntaxhighlight></div><br />
<br />
<br />
Also, move the ''console_blit'' call to the end of ''render_all()'' since it's part of the rendering code, just to keep things tidy.<br />
<br />
A little note on customization: if you want a more old-school look, using characters like ' '''.''' ' and ' '''#''' ' to represent floor and wall tiles, [[Complete Roguelike Tutorial, using Python+libtcod, extras#Old-school wall and floor tiles|check out this Extra]].<br />
<br />
<br />
Ok! Don't forget to call ''make_map()'' before the main loop, to set it up before the game begins. You should be able to see the two pillars and walk around the map now!<br />
<br />
But wait, there's something wrong. The pillars show up, but the player can walk over them. That's easy to fix though, add this check to the beginning of the ''Object'' 's ''move'' method:<br />
<br />
<br />
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">if not map[self.x + dx][self.y + dy].blocked:</syntaxhighlight></div><br />
<br />
<br />
[[Complete Roguelike Tutorial, using python+libtcod, part 2 code#The Map|Here]]'s the code so far.<br />
<br />
[[Complete Roguelike Tutorial, using python+libtcod, part 3|Go on to the next part]].<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43724Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T01:22:09Z<p>Fsolt: /* Installing libtcod */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
For OS X/macOS :<br />
<br />
First, you need to install [http://brew.sh/ homebrew]. Then you need to install Xcode through the App Store. Then, from the command line run the following command : <br />
<br />
> xcode-select install<br />
<br />
This will install gcc. Then run the following command :<br />
<br />
> brew update && brew install gdb sdl<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
For OS X/macOS : <br />
<br />
> git clone https://github.com/podiki/libtcod-mac.git<br />
> cd libtcod-mac<br />
> make -f makefiles/makefile-osx release<br />
<br />
Also for OS X/macOS, at the time of writing this, there is a small file change to make. In the file ../libtcod-mac/include/libtcod.h on line 109, you will need to change the <SDL.h> to <SDL/SDL.h>.<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OS X/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
and on OS X/macOS with :<br />
<br />
> gcc src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43723Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T01:10:51Z<p>Fsolt: /* Installing the compiler */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
For OS X/macOS :<br />
<br />
First, you need to install [http://brew.sh/ homebrew]. Then you need to install Xcode through the App Store. Then, from the command line run the following command : <br />
<br />
> xcode-select install<br />
<br />
This will install gcc. Then run the following command :<br />
<br />
> brew update && brew install gdb sdl<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OS X/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
and on OS X/macOS with :<br />
<br />
> gcc src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43722Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T01:00:06Z<p>Fsolt: /* First program */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OS X/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
and on OS X/macOS with :<br />
<br />
> gcc src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43721Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T00:59:13Z<p>Fsolt: /* Setting up the project */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OS X/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
and on OS X/macOS with :<br />
<br />
> gcc src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43720Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T00:58:59Z<p>Fsolt: /* First program */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OSX/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
and on OS X/macOS with :<br />
<br />
> gcc src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolthttp://roguebasin.com/index.php?title=Complete_roguelike_tutorial_using_C%2B%2B_and_libtcod_-_part_1:_setting_up&diff=43719Complete roguelike tutorial using C++ and libtcod - part 1: setting up2016-11-04T00:57:44Z<p>Fsolt: /* Setting up the project */</p>
<hr />
<div>{{Template:Complete roguelike tutorial using C++ and libtcod}}<br />
This article is the first part of a series heavily inspired by Jotaf's excellent [[Complete Roguelike Tutorial, using python+libtcod|"Complete roguelike tutorial using python + libtcod"]].<br />
<br />
It is intended for C++ beginners and people who want to learn how to use [https://bitbucket.org/libtcod/libtcod libtcod] to create a simple [[What_a_roguelike_is#|roguelike]] video game. It covers both Linux and Windows operating systems.<br />
<br />
'''The source code of this tutorial uses the C99 standard. That means that it won't compile out of the box on Visual Studio.'''<br />
<br />
While an experienced C++ developer won't have much trouble to port the code to Visual Studio, if you're a C++ beginner, I strongly advise to use one of the [[Complete roguelike tutorial using C++ and libtcod - extra 1: about editors and IDE|suggested compilers/IDE]].<br />
<br />
<center><big>[https://bitbucket.org/libtcod/tutorial/src/7f4f77fab400/src1/?at=master View source here]</big></center><br />
<br />
==Introduction==<br />
<br />
===Why C++ ?===<br />
<br />
While being often criticized for being complex, for lacking features or for failing to enforce a single programming style, C++ is still one of the most used languages. Here are a few reasons that make it still relevant :<br />
<br />
*the language itself is public domain. It's not owned by a private company like the more elegant java or C#<br />
*there are compilers that produce high-performance native binaries for almost any existing platform<br />
*it has a great compatibility with C, which makes it easy to use with C libraries like SDL<br />
<br />
Pre-requisite : this tutorial does not replace a C++ manual. You're supposed to have a basic knowledge of the C++ syntax and object oriented programming.<br />
<br />
===Why libtcod ?===<br />
<br />
It's easy to use and provides out of the box a lot of tools that are frequently used in a roguelike (Field of view and path finding algorithms amongst others). While browsing this tutorial, you should always have the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/index2.html?c=false&cpp=true&cs=false&py=false&lua=false libtcod C++ manual open]. '''The code in this article series works with libtcod versions 1.5.1 and 1.5.2.'''<br />
<br />
==libtcod functions used in this article==<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::initRoot]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_window.html?c=false&cpp=true&cs=false&py=false&lua=false#1 TCODConsole::isWindowClosed]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODSystem::checkForEvent]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#2 TCODConsole::clear]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 TCODConsole::putChar]<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_flush.html?c=false&cpp=true&cs=false&py=false&lua=false TCODConsole::flush]<br />
<br />
==Pre-requisites==<br />
<br />
===Installing the compiler===<br />
<br />
First you need a C++ compiler. On Linux, it's easy :<br />
<br />
> sudo apt-get install g++ gdb libsdl1.2debian-all<br />
<br />
On Windows, follow this tutorial : [http://roguecentral.org/doryen/data/libtcod/doc/1.5.2/html2/compile_libtcod_mingw.html?c=true&cpp=true&cs=true&py=true&lua=true libtcod 1.5.2 documentation].<br />
<br />
'''When installing Mingw, you must absolutely choose the "Use pre-packaged repository catalogues" option. Apparently, the latest version is not working with libraries compiled with the previous one.'''<br />
<br />
===Installing libtcod===<br />
<br />
All you have to do is download the library corresponding to your platform from [http://roguecentral.org/doryen/libtcod/download this URL] and extract it to your hard drive.<br />
<br />
'''Note that the Windows/Mingw precompiled library only works with a 32 bits compiler. If you want to use a 64 bits compiler, you'll have to recompile the library.'''<br />
<br />
==Setting up the project==<br />
Create an empty directory somewhere on your hardrive. Inside, create 3 empty directories :<br />
<br />
> mkdir include src lib<br />
<br />
Then you'll have to copy those files from the libtcod directory to your project directory :<br />
<br />
*include/*.h<br />
*include/*.hpp<br />
*terminal.png<br />
<br />
For Linux only :<br />
*libtcod.so<br />
*libtcodxx.so<br />
*libtcod_debug.so<br />
*libtcodxx_debug.so<br />
<br />
For Windows only :<br />
*libtcod-mingw.dll<br />
*libtcod-mingw-debug.dll<br />
*lib/libtcod-mingw.a<br />
*lib/libtcod-mingw-debug.a<br />
*SDL.dll<br />
<br />
For OSX/macOS only :<br />
*libtcod.dylib<br />
*libtcodxx.dylib<br />
*libtcod_debug.dylib<br />
*libtcodxx_debug.dylib<br />
<br />
==First program==<br />
We'll create a very simple program, just to check that we can compile and run. Let's create a src/main.cpp file :<br />
<br />
main.cpp<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
TCODConsole::root->clear();<br />
TCODConsole::root->putChar(40,25,'@');<br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
You can compile this on Windows with (type a single line) :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -Llib -ltcod-mingw -static-libgcc -static-libstdc++ -Wall<br />
<br />
If you want to get rid of the debug console when running the game from windows explorer, add the -mwindows flag. But since we're in the development phase, it's good to be able to get the program standard output. <br />
<br />
and on Linux with :<br />
<br />
> g++ src/*.cpp -o tuto -Iinclude -L. -ltcod -ltcodxx -Wl,-rpath=. -Wall<br />
<br />
==Line by line explanation==<br />
<br />
#include "libtcod.hpp"<br />
<br />
Here we're importing all the libtcod classes declaration. Actually, before compiling the main.cpp file, the compiler will replace this line by the content of libtcod.hpp.<br />
<br />
int main() {<br />
<br />
This is the function that will be called when the program starts. It returns an error code. 0 : no error. Any other value : an error occured.<br />
<br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
<br />
Here we're calling our first libtcod function to create the game window. It will contain a 80x50 console using the default font "./terminal.png". The false value indicates that we don't want to start in fullscreen mode.<br />
<br />
[http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_init_root.html?c=false&cpp=true&cs=false&py=false&lua=false initRoot] is a static function inside the TCODConsole class. It's basically a global function inside the TCODConsole namespace.<br />
<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<br />
Now we're starting the main game loop and we'll keep looping until the game window is closed by the player.<br />
<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,NULL,NULL);<br />
<br />
Even though we're not using keyboard input yet, we need to call [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_non_blocking_input.html?c=false&cpp=true&cs=false&py=false&lua=false#2 checkForEvent] for libtcod to process the screen redraw events.<br />
<br />
TCODConsole::root->clear();<br />
<br />
This is the first non static function we use. We access the static "root" variable inside the TCODConsole namespace. It's a pointer to the console bound to the main game window. We call the clear function on this console to erase everything with default color (black).<br />
<br />
TCODConsole::root->putChar(40,25,'@');<br />
<br />
Now we use [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_draw_basic.html?c=false&cpp=true&cs=false&py=false&lua=false#6 putChar] to print an @ in the middle of the screen, using the default color (white).<br />
<br />
TCODConsole::flush();<br />
<br />
This line actually generates the console image and displays it on the window.<br />
<br />
==The walking @==<br />
<br />
Now we're ready to reach the first step in any roguelike : the walking @ step :<br />
<br />
#include "libtcod.hpp"<br />
int main() {<br />
<span style="color:green">int playerx=40,playery=25;</span><br />
TCODConsole::initRoot(80,50,"libtcod C++ tutorial",false);<br />
while ( !TCODConsole::isWindowClosed() ) {<br />
<span style="color:green">TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}</span><br />
TCODConsole::root->clear();<br />
<span style="color:green">TCODConsole::root->putChar(playerx,playery,'@');</span><br />
TCODConsole::flush();<br />
}<br />
return 0;<br />
}<br />
<br />
We store the player position in two variables :<br />
<br />
int playerx=40,playery=25;<br />
<br />
and use them to draw the @ instead of the hardcoded values :<br />
<br />
TCODConsole::root->putChar(playerx,playery,'@');<br />
<br />
This time, we'll get the result from the checkForEvent function in a TCOD_key_t structure :<br />
<br />
TCOD_key_t key;<br />
TCODSystem::checkForEvent(TCOD_EVENT_KEY_PRESS,&key,NULL);<br />
<br />
The key variable contains everything we need to know about the keyboard input from the user. We can use it to update the player position :<br />
<br />
switch(key.vk) {<br />
case TCODK_UP : playery--; break;<br />
case TCODK_DOWN : playery++; break;<br />
case TCODK_LEFT : playerx--; break;<br />
case TCODK_RIGHT : playerx++; break;<br />
default:break;<br />
}<br />
That's it. Recompile the program (you can press CTRL-R and type g++ in the terminal to recall the last compilation command).<br />
<br />
[[Category:Developing]]</div>Fsolt