def console_get_char_background(self,con,x,y): if con == 0: col = libtcod.console_get_char_background(0,x,y) return libtcod.color_get_hsv(col) else: col = libtcod.console_get_char_background(self.mConsole[con-1],x,y) return libtcod.color_get_hsv(col)
def draw(self): """Draw this map tile""" # NB. this gets called a lot! if not self.is_visible: return if self.visible_to_player: if self.map.player.has_effect( StatusEffect.INFRAVISION) and not self.remains_in_place: c = libtcod.white else: c = self.light_colour # this is slow l = libtcod.color_get_hsv(c)[ 2] # this is copied from .light_level for performance if self.map.player.has_effect(StatusEffect.NIGHT_VISION): l = 1.0 - l c = libtcod.white - c if l > LightSource.INTENSITY_L_CLAMP: colour = self.colour * c symbol = self.symbol else: if self.has_been_seen and self.remains_in_place: colour = self.unseen_colour symbol = self.unseen_symbol else: return else: if self.has_been_seen and self.remains_in_place: colour = self.unseen_colour symbol = self.unseen_symbol else: return libtcod.console_put_char_ex(0, self.pos.x, self.pos.y, symbol, colour, libtcod.BKGND_NONE) self.has_been_seen = True
def draw(self): """Draw this map tile""" # NB. this gets called a lot! if not self.is_visible: return if self.visible_to_player: if self.map.player.has_effect(StatusEffect.INFRAVISION) and not self.remains_in_place: c = libtcod.white else: c = self.light_colour # this is slow l = libtcod.color_get_hsv(c)[2] # this is copied from .light_level for performance if self.map.player.has_effect(StatusEffect.NIGHT_VISION): l = 1.0 - l c = libtcod.white - c if l > LightSource.INTENSITY_L_CLAMP: colour = self.colour * c symbol = self.symbol else: if self.has_been_seen and self.remains_in_place: colour = self.unseen_colour symbol = self.unseen_symbol else: return else: if self.has_been_seen and self.remains_in_place: colour = self.unseen_colour symbol = self.unseen_symbol else: return libtcod.console_put_char_ex(0, self.pos.x, self.pos.y, symbol, colour, libtcod.BKGND_NONE) self.has_been_seen = True
def test_color(): color_a = libtcodpy.Color(0, 1, 2) assert list(color_a) == [0, 1, 2] assert color_a[0] == color_a.r assert color_a[1] == color_a.g assert color_a[2] == color_a.b color_a[1] = 3 color_a['b'] = color_a['b'] assert list(color_a) == [0, 3, 2] assert color_a == color_a color_b = libtcodpy.Color(255, 255, 255) assert color_a != color_b color = libtcodpy.color_lerp(color_a, color_b, 0.5) libtcodpy.color_set_hsv(color, 0, 0, 0) libtcodpy.color_get_hsv(color) libtcodpy.color_scale_HSV(color, 0, 0)
def __init__(self, tile_type): self.blocked = False self.block_sight = None self.type = tile_type # all tiles start unexplored self.explored = False if self.type == tile_types.CAVE_FLOOR: self.hot_cold = -1 self.wet_dry = -1 self.color_in_FOV = libtcod.light_grey elif self.type == tile_types.CAVE_WALL: self.hot_cold = -1 self.wet_dry = -1 self.blocked = True self.color_in_FOV = libtcod.grey elif self.type == tile_types.GRASS: self.hot_cold = 0 self.wet_dry = 0 self.color_in_FOV = libtcod.desaturated_green elif self.type == tile_types.SAND: self.hot_cold = 2 self.wet_dry = -2 self.color_in_FOV = libtcod.light_orange elif self.type == tile_types.SHALLOW_WATER: self.hot_cold = -4 self.wet_dry = 5 self.color_in_FOV = libtcod.light_sky elif self.type == tile_types.DEEP_WATER: self.hot_cold = -6 self.wet_dry = 8 self.blocked = True self.block_sight = False self.color_in_FOV = libtcod.dark_sky # the following assignments depend on assignments # in the tile_type tests, so they come after the tests # by default, a tile blocks sight if it is blocked and vice versa if self.block_sight is None: self.block_sight = self.blocked # set tile color outside of FOV as desaturated # and darker than color in FOV hsv = libtcod.color_get_hsv(self.color_in_FOV) # returns [h,s,v] # Colors are passed by reference, # so we have to create a whole new Color object. self.color_out_FOV = libtcod.Color(self.color_in_FOV.r, self.color_in_FOV.g, self.color_in_FOV.b) # Desaturate and darken color (unseen by default) libtcod.color_set_hsv(self.color_out_FOV, hsv[0], hsv[1] / 4, hsv[2] / 4)
def get_cylindrical_projection(stars, width=360, height=180): """ Return a tcod console instance of width and height that renders an equirectangular projection of the given list of stars. """ console = tcod.console_new(width, height) for star in stars: azimuthal = int((star.azimuthal * width) / (2 * math.pi)) polar = int((star.polar / math.pi) * height) # Color Work rgb = temperature_to_rgb(random.uniform(4000, 20000)) brightness = 1.0 - star.radial * 0.75 color = tcod.Color(rgb[0], rgb[1], rgb[2]) (h, s, v) = tcod.color_get_hsv(color) tcod.color_set_hsv(color, h, s, brightness) tcod.console_put_char_ex(console, azimuthal, polar, star.sprite, color, tcod.black) # Background Texture noise3d = tcod.noise_new(3) for map_x in range(width): for map_y in range(height): azimuthal = (map_x / (width * 1.0)) * 2.0 * math.pi polar = (map_y / (height * 1.0)) * math.pi x = math.sin(polar) * math.cos(azimuthal) y = math.sin(polar) * math.sin(azimuthal) z = math.cos(polar) blue = int( tcod.noise_get_turbulence(noise3d, [x, y, z], 32.0) * 16.0 + 16.0) green = int(tcod.noise_get(noise3d, [x, y, z]) * 8.0 + 8.0) red = int(tcod.noise_get_fbm(noise3d, [x, y, z], 32.0) * 4.0 + 4.0) background = tcod.Color(red, green, blue) if map_y == height / 2 or map_x == 0 or map_x == width / 2: background = tcod.darkest_yellow tcod.console_set_char_background(console, map_x, map_y, background) tcod.noise_delete(noise3d) return console
class LightSource(Mappable): """Light emitted from a single point""" INTENSITY_L_CLAMP = libtcod.color_get_hsv(Mappable.LIGHT_L_CLAMP)[2] INTENSITY_H_CLAMP = libtcod.color_get_hsv(Mappable.LIGHT_H_CLAMP)[2] INTENSITY_VISIBLE = libtcod.color_get_hsv(Mappable.LIGHT_VISIBLE)[2] def __init__(self, radius=0, intensity=1.0, light_colour=Mappable.LIGHT_H_CLAMP): self._radius = radius == 0 and 100 or radius # TODO: more sensible behaviour for infinite r self.intensity = intensity self.raw_light_colour = light_colour self.light_enabled = True self.__tcod_light_map = libtcod.map_new(radius * 2 + 1, radius * 2 + 1) self.__tcod_light_image = libtcod.image_new(radius * 2 + 1, radius * 2 + 1) @property def radius(self): """Set light radius""" return self._radius @radius.setter def radius(self, r): """Change light radius""" if r == self._radius: return # because this is slow! e = self.light_enabled self.close() self.light_enabled = e self._radius = r self.__tcod_light_map = libtcod.map_new(r * 2 + 1, r * 2 + 1) self.__tcod_light_image = libtcod.image_new(r * 2 + 1, r * 2 + 1) self.reset_map() def prepare_fov(self, light_walls=False): """Calculate light's distribution""" libtcod.map_compute_fov(self.__tcod_light_map, self.radius + 1, self.radius + 1, self.radius, light_walls, libtcod.FOV_BASIC) def reset_map(self, pos=None): """Reset light map. If pos is a list of Positions, only reset those areas""" if not self.light_enabled: libtcod.image_clear(self.__tcod_light_image, libtcod.black) libtcod.image_set_key_color(self.__tcod_light_image, libtcod.black) return assert not self.pos is None and not self.map is None, "resetting LightSource that is not placed on map" # [re-]calculating FOV of light within its map if pos is None: libtcod.map_clear(self.__tcod_light_map, False, False) cov = {} for o in self.map.find_all_within_r(self, Transparent, self.radius): # if there's something here already and it blocks light, light is blocked at pos if cov.get(o.pos, True): cov[o.pos] = not o.blocks_light() for (p, is_transparent) in cov.items(): # we're using the walkable bit to show that there is a tile that could be lit libtcod.map_set_properties(self.__tcod_light_map, self.radius + p.x - self.pos.x, self.radius + p.y - self.pos.y, is_transparent, True) else: if not isinstance(pos, list): pos = [pos] skip_calc = True for p in pos: if self.pos.distance_to(p) > self.radius: # pos isn't covered by this light; do nothing pass else: skip_calc = False is_transparent = True for o in self.map.find_all_at_pos(p): if isinstance(o, Transparent) and o.blocks_light(): is_transparent = False break libtcod.map_set_properties(self.__tcod_light_map, self.radius + p.x - self.pos.x, self.radius + p.y - self.pos.y, is_transparent, True) if skip_calc: # all pos were outside of light radius! return self.prepare_fov( False ) # TODO: calculate both True and False; use True only if light in LOS of player # use FOV data to create an image of light intensity, masked by opaque tiles # can optimise based on pos P: only need to recalculate area X # --- ---XX --- --XXX # / \ / XX / \ / XXX do this by splitting into quarters # | P| | PX | | | XXX and working out which to recalculate # | L | | L | | LP | | LPXX based on P-L # | | | | | | | XXX # \ / \ / \ / \ XXX # --- --- --- --XXX libtcod.image_clear(self.__tcod_light_image, libtcod.black) libtcod.image_set_key_color(self.__tcod_light_image, libtcod.black) r = self.radius rd2 = r / 2 i1 = self.raw_light_colour * self.intensity for x in range(r * 2 + 1): for y in range(r * 2 + 1): #print("(%d,%d)"%(x,y)) if libtcod.map_is_in_fov(self.__tcod_light_map, x, y): d = hypot(r - x, r - y) if d > rd2: libtcod.image_put_pixel(self.__tcod_light_image, x, y, i1 * (1.0 - (d - rd2) / rd2)) #print(" %s %s"%(d,i1*(1.0-(d-rd2)/rd2))) else: libtcod.image_put_pixel(self.__tcod_light_image, x, y, i1) #print(" %s %s"%(d,i1)) def blit_to(self, tcod_console, ox=0, oy=0, sx=-1, sy=-1): """Copy lighting information to libtcod console""" libtcod.image_blit_rect( self.__tcod_light_image, tcod_console, self.pos.x + ox - self.radius, self.pos.y + oy - self.radius, #self.radius*2+1-ox, self.radius*2+1-oy, sx, sy, libtcod.BKGND_ADD) def lights(self, pos, test_los=True): """Does this light light pos? If test_los is False; don't bother checking line of sight""" if not self.light_enabled: return False if self.pos.distance_to(pos) > self.radius: return False if not test_los: return True #print("does %s light pos %s?"%(self,pos)) #print("%d < %d" %(self.pos.distance_to(pos),self.radius)) #print("%d,%d"%(1+self.radius+pos.x-self.pos.x,1+self.radius+pos.y-self.pos.y)) return libtcod.map_is_in_fov(self.__tcod_light_map, self.radius + pos.x - self.pos.x, self.radius + pos.y - self.pos.y) def close(self): """Clean up lighting assets prior to deleting object""" libtcod.map_delete(self.__tcod_light_map) libtcod.image_delete(self.__tcod_light_image) self.light_enabled = False def __del__(self): """del light""" self.close()