Alright guys, Stackoverflow failed me and I need some help with my libtcod+python Field of View code.
Basically there are several units (~10 on each team with 2 teams) and each one has its own sight range (~5-10). I need to create a set of all the tiles on the map which should be highlighted based on the total FOV of all units. I'm not playing with light intensity or any such shenanigans so I just need a simple on/off toggle of the tile.
Here's what I have:
class Unit:
#This is a generic unit: cavalry, infantry etc.
def __init__(self, name, x, y, char, color,
move_range, atk_range, unit_size, morale, base_power, base_defence,
fatigue, team):
self.name = name
self.x = x
self.y = y
self.char = char
self.color = color
self.range = move_range
self.move_counter = 0
self.atk_range = atk_range
self.sight_range = 5
self.fov_map = libtcod.map_new(self.sight_range, self.sight_range)
self.visible_set = set([])
self.exp = 0
self.rank = ''
self.rank_level = self.exp/10
self.unit_size = unit_size
self.current_unit_size = unit_size
self.morale = self.exp + morale
self.current_morale = morale
self.fatigue = fatigue + self.exp
self.current_fatigue = fatigue
self.base_power = base_power + self.rank_level
self.base_defence = base_defence + self.rank_level
self.power_multiplier = 1
self.power = self.power_multiplier*self.base_power
self.defence = self.power_multiplier*self.base_defence
self.team = team
self.targeted = False
self.can_move = False
self.can_attack = False
self.inactive_color = libtcod.gray
def draw(self, screen):
#set the color and then draw the character that represents this object at its position
#if libtcod.map_is_in_fov(new_map, self.x, self.y):
if game_ready == True:
if self.can_move == True or self.can_attack == True:
libtcod.console_set_default_foreground(screen, self.color)
elif self.can_move == False and self.can_attack == False:
libtcod.console_set_default_foreground(screen, self.inactive_color)
#elif game_ready == False:
#libtcod.console_set_default_foreground(screen, self.color)
libtcod.console_put_char(screen, self.x, self.y, self.char, libtcod.BKGND_NONE)
libtcod.map_set_properties(new_map, self.x, self.y, False, False)
def set_fov(self): #Relevant function to the issue
sight_range_tiles = get_tiles_in_range(self.x, self.y, self.sight_range) #Gets the coordinates of the tiles within a certain range (in this case, the sight range)
self.visible_set = {tile for tile in T_Map.tile_array if (tile.x, tile.y) in sight_range_tiles} #Gets all the tiles with the corresponding coords in sight_range_tiles
self.blocked_tiles_set = (self.visible_set & terrain_tiles_set) #Creates a subset of the visible tiles by intersecting with a different set, terrain_tiles_set, which contains all the tiles which block light; thus blocked_tiles_set contains all the tiles within range which block light
#Iterates through light-blocking tiles in range and assigns them as blocked to a separate, unique FOV map for each unit
for tile in self.blocked_tiles_set:
libtcod.map_set_properties(self.fov_map, tile.x, tile.y, False, True)
libtcod.map_compute_fov(self.fov_map, unit.x, unit.y, self.sight_range, True, libtcod.FOV_SHADOW)
def render_all():
global color_dark_wall
global color_dark_ground
global lclick_x, lclick_y
global coord_in_range
global new_map
global game_ready
global fov_recompute
global turn_counter
#render map
if map_archetype == 'forest':
T_Map.render_map(T_Map.tileset_forest, T_Map.colors_forest, T_Map.terrain_forest)
elif map_archetype == 'desert':
T_Map.render_map(T_Map.tileset_desert, T_Map.colors_desert, T_Map.terrain_desert)
elif map_archetype == 'tundra':
T_Map.render_map(T_Map.tileset_tundra, T_Map.colors_tundra, T_Map.terrain_tundra)
elif map_archetype == 'plains':
T_Map.render_map(T_Map.tileset_plains, T_Map.colors_plains, T_Map.terrain_forest)
#draw all objects in the list and compute the field of view
for team in teams:
for unit in team:
if fov_recompute:
if unit.team == 1:
unit.set_fov()
elif unit.team == 2:
unit.set_fov()
#Team 1
if (turn_counter%2 == 0 or turn_counter == -1):
for fov_map in fov_maps1:
if unit.team == 1 or libtcod.map_is_in_fov(fov_map, unit.x, unit.y):
unit.draw(con)
#Team 2
if turn_counter%2 == 1 or turn_counter == -1:
for fov_map in fov_maps2:
if unit.team == 2 or libtcod.map_is_in_fov(fov_map, unit.x, unit.y):
unit.draw(con)
#
visible_1 = []
visible_2 = []
#Change the color of a tile if it is in the FOV.
for x in range(MAP_WIDTH):
for y in range(MAP_HEIGHT):
for unit in team1:
visible_1 += [libtcod.map_is_in_fov(unit.fov_map, x, y)]
for unit in team2:
visible_2 += [libtcod.map_is_in_fov(unit.fov_map, x, y)]
if turn_counter%2 == 0 and any(visible_1):
libtcod.console_set_char_background(con, x, y, libtcod.darker_purple, libtcod.BKGND_SET)
elif turn_counter%2 == 1 and any(visible_2):
libtcod.console_set_char_background(con, x, y, libtcod.darker_purple, libtcod.BKGND_SET)
Not only does this code not display anything (as in no FOV for either side) it also lags like hell. The latter I expected (since I'm iterating through 5000 objects every time render_all() runs, which is looping until exit) but the former is giving me a headache. Help.
EDIT: Nevermind, it turns out it was a simple fix. This is what happens with sleep deprivation. Good to know.