Difference between revisions of "Complete Roguelike Tutorial, using python+libtcod, part 2 code"
(Created page with '<center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center> This is part of the '''code''' for a series of tutorials; the main page can…') |
|||
Line 156: | Line 156: | ||
libtcod.console_flush() | libtcod.console_flush() | ||
</pre> | </pre> | ||
== Field of View (FOV) == | |||
import libtcodpy as libtcod | |||
#actual size of the window | |||
SCREEN_WIDTH = 80 | |||
SCREEN_HEIGHT = 50 | |||
#size of the map | |||
MAP_WIDTH = 80 | |||
MAP_HEIGHT = 45 | |||
FOV_ALGO = 0 #default FOV algorithm | |||
FOV_LIGHT_WALLS = True #light walls or not | |||
TORCH_RADIUS = 10 | |||
LIMIT_FPS = 20 #20 frames-per-second maximum | |||
color_dark_wall = libtcod.Color(0, 0, 100) | |||
color_light_wall = libtcod.Color(130, 110, 50) | |||
color_dark_ground = libtcod.Color(50, 50, 150) | |||
color_light_ground = libtcod.Color(200, 180, 50) | |||
class Tile: | |||
#a tile of the map and its properties | |||
def __init__(self, blocked, block_sight = None): | |||
self.blocked = blocked | |||
#by default, if a tile is blocked, it also blocks sight | |||
if block_sight is None: block_sight = blocked | |||
self.block_sight = block_sight | |||
class Object: | |||
#this is a generic object: the player, a monster, an item, the stairs... | |||
#it's always represented by a character on screen. | |||
def __init__(self, x, y, char, color): | |||
self.x = x | |||
self.y = y | |||
self.char = char | |||
self.color = color | |||
def move(self, dx, dy): | |||
#move by the given amount, if the destination is not blocked | |||
if not map[self.x + dx][self.y + dy].blocked: | |||
self.x += dx | |||
self.y += dy | |||
def draw(self): | |||
#only show if it's visible to the player | |||
if libtcod.map_is_in_fov(fov_map, self.x, self.y): | |||
#set the color and then draw the character that represents this object at its position | |||
libtcod.console_set_foreground_color(0, self.color) | |||
libtcod.console_put_char(0, self.x, self.y, self.char, libtcod.BKGND_NONE) | |||
def clear(self): | |||
#erase the character that represents this object | |||
libtcod.console_put_char(0, self.x, self.y, ' ', libtcod.BKGND_NONE) | |||
def make_map(): | |||
global map | |||
#fill map with "unblocked" tiles | |||
map = [[ Tile(False) | |||
for y in range(MAP_HEIGHT) ] | |||
for x in range(MAP_WIDTH) ] | |||
#place two pillars to test the map | |||
map[30][22].blocked = True | |||
map[30][22].block_sight = True | |||
map[50][22].blocked = True | |||
map[50][22].block_sight = True | |||
def render_all(): | |||
global fov_map, color_dark_wall, color_light_wall | |||
global color_dark_ground, color_light_ground | |||
global fov_recompute | |||
#draw all objects in the list | |||
for object in objects: | |||
object.draw() | |||
if fov_recompute: | |||
#recompute FOV if needed (the player moved or something) | |||
fov_recompute = False | |||
libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) | |||
#go through all tiles, and set their background color according to the FOV | |||
for y in range(MAP_HEIGHT): | |||
for x in range(MAP_WIDTH): | |||
visible = libtcod.map_is_in_fov(fov_map, x, y) | |||
wall = map[x][y].block_sight | |||
if not visible: | |||
#it's out of the player's FOV | |||
if wall: | |||
libtcod.console_set_back(0, x, y, color_dark_wall, libtcod.BKGND_SET) | |||
else: | |||
libtcod.console_set_back(0, x, y, color_dark_ground, libtcod.BKGND_SET) | |||
else: | |||
#it's visible | |||
if wall: | |||
libtcod.console_set_back(0, x, y, color_light_wall, libtcod.BKGND_SET ) | |||
else: | |||
libtcod.console_set_back(0, x, y, color_light_ground, libtcod.BKGND_SET ) | |||
def handle_keys(): | |||
global fov_recompute | |||
key = libtcod.console_check_for_keypress() #real-time | |||
#key = libtcod.console_wait_for_keypress(True) #turn-based | |||
if key.vk == libtcod.KEY_ENTER and key.lalt: | |||
#Alt+Enter: toggle fullscreen | |||
libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) | |||
elif key.vk == libtcod.KEY_ESCAPE: | |||
return True #exit game | |||
#movement keys | |||
elif libtcod.console_is_key_pressed(libtcod.KEY_UP): | |||
player.move(0, -1) | |||
fov_recompute = True | |||
elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN): | |||
player.move(0, 1) | |||
fov_recompute = True | |||
elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT): | |||
player.move(-1, 0) | |||
fov_recompute = True | |||
elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT): | |||
player.move(1, 0) | |||
fov_recompute = True | |||
############################################# | |||
# Initialization & Main Loop | |||
############################################# | |||
libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD) | |||
libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False) | |||
libtcod.sys_set_fps(LIMIT_FPS) | |||
#create object representing the player | |||
player = Object(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, '@', libtcod.white) | |||
#create an NPC | |||
npc = Object(SCREEN_WIDTH/2 - 5, SCREEN_HEIGHT/2, '@', libtcod.yellow) | |||
#the list of objects with those two | |||
objects = [npc, player] | |||
#generate map (at this point it's not drawn to the screen) | |||
make_map() | |||
#create the FOV map, according to the generated map | |||
fov_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) | |||
for y in range(MAP_HEIGHT): | |||
for x in range(MAP_WIDTH): | |||
libtcod.map_set_properties(fov_map, x, y, not map[x][y].blocked, not map[x][y].block_sight) | |||
fov_recompute = True | |||
#first_time = True #for turn-based games | |||
while not libtcod.console_is_window_closed(): | |||
#erase all objects at their old locations, before they move | |||
for object in objects: | |||
object.clear() | |||
#handle keys and exit game if needed | |||
#if not first_time: #for turn-based games | |||
exit = handle_keys() | |||
if exit: | |||
break | |||
#first_time = False #for turn-based games | |||
#render the screen | |||
render_all() | |||
libtcod.console_flush() |
Revision as of 23:44, 26 December 2009
This is part of the code for a series of tutorials; the main page can be found here. |
The Map
import libtcodpy as libtcod #actual size of the window SCREEN_WIDTH = 80 SCREEN_HEIGHT = 50 #size of the map MAP_WIDTH = 80 MAP_HEIGHT = 45 LIMIT_FPS = 20 #20 frames-per-second maximum color_dark_wall = libtcod.Color(0, 0, 100) color_dark_ground = libtcod.Color(50, 50, 150) class Tile: #a tile of the map and its properties def __init__(self, blocked, block_sight = None): self.blocked = blocked #by default, if a tile is blocked, it also blocks sight if block_sight is None: block_sight = blocked self.block_sight = block_sight class Object: #this is a generic object: the player, a monster, an item, the stairs... #it's always represented by a character on screen. def __init__(self, x, y, char, color): self.x = x self.y = y self.char = char self.color = color def move(self, dx, dy): #move by the given amount, if the destination is not blocked if not map[self.x + dx][self.y + dy].blocked: self.x += dx self.y += dy def draw(self): #set the color and then draw the character that represents this object at its position libtcod.console_set_foreground_color(0, self.color) libtcod.console_put_char(0, self.x, self.y, self.char, libtcod.BKGND_NONE) def clear(self): #erase the character that represents this object libtcod.console_put_char(0, self.x, self.y, ' ', libtcod.BKGND_NONE) def make_map(): global map #fill map with "unblocked" tiles map = [[ Tile(False) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ] #place two pillars to test the map map[30][22].blocked = True map[30][22].block_sight = True map[50][22].blocked = True map[50][22].block_sight = True def render_all(): global color_light_wall global color_light_ground #draw all objects in the list for object in objects: object.draw() #go through all tiles, and set their background color for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): wall = map[x][y].block_sight if wall: libtcod.console_set_back(0, x, y, color_dark_wall, libtcod.BKGND_SET ) else: libtcod.console_set_back(0, x, y, color_dark_ground, libtcod.BKGND_SET ) def handle_keys(): key = libtcod.console_check_for_keypress() #real-time #key = libtcod.console_wait_for_keypress(True) #turn-based if key.vk == libtcod.KEY_ENTER and key.lalt: #Alt+Enter: toggle fullscreen libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) elif key.vk == libtcod.KEY_ESCAPE: return True #exit game #movement keys if libtcod.console_is_key_pressed(libtcod.KEY_UP): player.move(0, -1) elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN): player.move(0, 1) elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT): player.move(-1, 0) elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT): player.move(1, 0) ############################################# # Initialization & Main Loop ############################################# libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD) libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False) libtcod.sys_set_fps(LIMIT_FPS) #create object representing the player player = Object(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, '@', libtcod.white) #create an NPC npc = Object(SCREEN_WIDTH/2 - 5, SCREEN_HEIGHT/2, '@', libtcod.yellow) #the list of objects with those two objects = [npc, player] #generate map (at this point it's not drawn to the screen) make_map() #first_time = True #for turn-based games while not libtcod.console_is_window_closed(): #erase all objects at their old locations, before they move for object in objects: object.clear() #handle keys and exit game if needed #if not first_time: #for turn-based games exit = handle_keys() if exit: break #first_time = False #for turn-based games #render the screen render_all() libtcod.console_flush()
Field of View (FOV)
import libtcodpy as libtcod
- actual size of the window
SCREEN_WIDTH = 80 SCREEN_HEIGHT = 50
- size of the map
MAP_WIDTH = 80 MAP_HEIGHT = 45
FOV_ALGO = 0 #default FOV algorithm
FOV_LIGHT_WALLS = True #light walls or not
TORCH_RADIUS = 10
LIMIT_FPS = 20 #20 frames-per-second maximum
color_dark_wall = libtcod.Color(0, 0, 100)
color_light_wall = libtcod.Color(130, 110, 50)
color_dark_ground = libtcod.Color(50, 50, 150)
color_light_ground = libtcod.Color(200, 180, 50)
class Tile:
#a tile of the map and its properties def __init__(self, blocked, block_sight = None): self.blocked = blocked #by default, if a tile is blocked, it also blocks sight if block_sight is None: block_sight = blocked self.block_sight = block_sight
class Object:
#this is a generic object: the player, a monster, an item, the stairs... #it's always represented by a character on screen. def __init__(self, x, y, char, color): self.x = x self.y = y self.char = char self.color = color def move(self, dx, dy): #move by the given amount, if the destination is not blocked if not map[self.x + dx][self.y + dy].blocked: self.x += dx self.y += dy def draw(self): #only show if it's visible to the player if libtcod.map_is_in_fov(fov_map, self.x, self.y): #set the color and then draw the character that represents this object at its position libtcod.console_set_foreground_color(0, self.color) libtcod.console_put_char(0, self.x, self.y, self.char, libtcod.BKGND_NONE) def clear(self): #erase the character that represents this object libtcod.console_put_char(0, self.x, self.y, ' ', libtcod.BKGND_NONE)
def make_map():
global map #fill map with "unblocked" tiles map = [[ Tile(False) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ] #place two pillars to test the map map[30][22].blocked = True map[30][22].block_sight = True map[50][22].blocked = True map[50][22].block_sight = True
def render_all():
global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute
#draw all objects in the list for object in objects: object.draw() if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO)
#go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #it's out of the player's FOV if wall: libtcod.console_set_back(0, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_back(0, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_back(0, x, y, color_light_wall, libtcod.BKGND_SET ) else: libtcod.console_set_back(0, x, y, color_light_ground, libtcod.BKGND_SET )
def handle_keys():
global fov_recompute key = libtcod.console_check_for_keypress() #real-time #key = libtcod.console_wait_for_keypress(True) #turn-based if key.vk == libtcod.KEY_ENTER and key.lalt: #Alt+Enter: toggle fullscreen libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) elif key.vk == libtcod.KEY_ESCAPE: return True #exit game #movement keys elif libtcod.console_is_key_pressed(libtcod.KEY_UP): player.move(0, -1) fov_recompute = True elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN): player.move(0, 1) fov_recompute = True elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT): player.move(-1, 0) fov_recompute = True elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT): player.move(1, 0) fov_recompute = True
- Initialization & Main Loop
libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD) libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False) libtcod.sys_set_fps(LIMIT_FPS)
- create object representing the player
player = Object(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, '@', libtcod.white)
- create an NPC
npc = Object(SCREEN_WIDTH/2 - 5, SCREEN_HEIGHT/2, '@', libtcod.yellow)
- the list of objects with those two
objects = [npc, player]
- generate map (at this point it's not drawn to the screen)
make_map()
- create the FOV map, according to the generated map
fov_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) for y in range(MAP_HEIGHT):
for x in range(MAP_WIDTH): libtcod.map_set_properties(fov_map, x, y, not map[x][y].blocked, not map[x][y].block_sight)
fov_recompute = True
- first_time = True #for turn-based games
while not libtcod.console_is_window_closed():
#erase all objects at their old locations, before they move for object in objects: object.clear() #handle keys and exit game if needed #if not first_time: #for turn-based games exit = handle_keys() if exit: break #first_time = False #for turn-based games #render the screen render_all() libtcod.console_flush()