def generate_land(self): for x in range(self.width): for y in range(self.height): f = [self.noise_zoom * x / self.width, self.noise_zoom * y / self.height] value = libtcod.noise_get_fbm(self.world_noise, f, self.noise_octaves, libtcod.NOISE_PERLIN) #Threshold c = ((value + 1.0) / 2.0) col = libtcod.color_lerp(libtcod.dark_green, libtcod.black, c) self.map_list[x][y].land_type = 'grass' c = int((value + 1.0) / 2.0 * 200) c = c - int(self.dist(x,y))/1.5 #This is a beach if c < 28: col = libtcod.lightest_amber self.map_list[x][y].land_type = 'beach' #This is water if c < 20: coef = self.dist(x,y) / 320 col = libtcod.color_lerp(libtcod.azure, libtcod.darkest_azure * (c/2), coef) if c > 5: self.map_list[x][y].land_type = 'shallow_water' else: self.map_list[x][y].land_type = 'deep_water' libtcod.map_set_properties(self.deepsea_map, x, y, False, True) if self.map_list[x][y].land_type == 'grass' or self.map_list[x][y].land_type == 'beach': libtcod.map_set_properties(self.ground_map, x, y, False, True) self.map_list[x][y].color = col libtcod.image_put_pixel(self.world_img, x, y, self.map_list[x][y].color)
def test_image(console, tmpdir): img = libtcodpy.image_new(16, 16) libtcodpy.image_clear(img, libtcodpy.Color(0, 0, 0)) libtcodpy.image_invert(img) libtcodpy.image_hflip(img) libtcodpy.image_rotate90(img) libtcodpy.image_vflip(img) libtcodpy.image_scale(img, 24, 24) libtcodpy.image_set_key_color(img, libtcodpy.Color(255, 255, 255)) libtcodpy.image_get_alpha(img, 0, 0) libtcodpy.image_is_pixel_transparent(img, 0, 0) libtcodpy.image_get_size(img) libtcodpy.image_get_pixel(img, 0, 0) libtcodpy.image_get_mipmap_pixel(img, 0, 0, 1, 1) libtcodpy.image_put_pixel(img, 0, 0, libtcodpy.Color(255, 255, 255)) libtcodpy.image_blit(img, console, 0, 0, libtcodpy.BKGND_SET, 1, 1, 0) libtcodpy.image_blit_rect(img, console, 0, 0, 16, 16, libtcodpy.BKGND_SET) libtcodpy.image_blit_2x(img, console, 0, 0) libtcodpy.image_save(img, tmpdir.join('test.png').strpath) libtcodpy.image_delete(img) # Not portable. #img = libtcodpy.image_from_console(console) #libtcodpy.image_refresh_console(img, console) #libtcodpy.image_delete(img) libtcodpy.image_delete(libtcodpy.image_load('../data/img/circle.png'))
def draw(self, main_map): #Settings libtcod.console_set_default_background(self.console, libtcod.black) libtcod.console_set_alignment(self.console, libtcod.CENTER) if main_map.selected_unit: start = (self.width - 4)/2 #Draw all units in the unit image for x in range(self.width - 4): for y in range(self.width - 4): libtcod.image_put_pixel(self.unit_image, x, y, main_map.map_list[main_map.selected_unit.x + x - start][main_map.selected_unit.y + y - start].color) for u in main_map.units: if u.x == (main_map.selected_unit.x + x - start) and u.y == (main_map.selected_unit.y + y - start): libtcod.console_set_char_foreground(self.console, x + 2, y + 4, u.color) libtcod.console_set_char(self.console, x + 2, y + 4, u.char) libtcod.console_print_frame(self.console, 0, 0, self.width, self.height, False, libtcod.BKGND_NONE, main_map.selected_unit.name) libtcod.console_rect(self.console, 0,0, 20, 1, False) libtcod.image_blit_rect(self.unit_image, self.console, 2, 4, self.width - 4, self.width - 4, libtcod.BKGND_SET) libtcod.console_set_alignment(self.console, libtcod.LEFT) #Unit stats statx = self.width + 1 libtcod.console_print(self.console, 2, statx, 'Speed') libtcod.console_print(self.console, 2, statx + 1, 'Attack') libtcod.console_print(self.console, 2, statx + 2, 'Armor') libtcod.console_set_alignment(self.console, libtcod.RIGHT) libtcod.console_print(self.console, self.width - 2, statx, str(main_map.selected_unit.speed)) libtcod.console_print(self.console, self.width - 2, statx + 1, str(main_map.selected_unit.attack)) libtcod.console_print(self.console, self.width - 2, statx + 2, str(main_map.selected_unit.armor)) libtcod.console_blit(self.console, 0, 0, self.width, self.height, 0, 1, 60 - self.height/2, 1, 0.75)
def draw_point(self, x, y, color=None): # draw a pixel to the screen's semigraphics layer # fails silently if there is currently no graphics layer if color is None: color = self.foreground if self.graphics_mode and self.img is not None: libtcod.image_put_pixel(self.img, x, y, color) return
def generate_starpic(): # Generates a random starfield pattern and stores it in img img = libtcod.image_new(160, 100) libtcod.image_clear(img, libtcod.black) colors = [libtcod.lightest_yellow, libtcod.lightest_grey, libtcod.white, libtcod.white, libtcod.light_orange, libtcod.darker_red] for x in range(100): x = libtcod.random_get_int(0, 0, 159) y = libtcod.random_get_int(0, 0, 99) c = libtcod.random_get_int(0, 0, len(colors) - 1) libtcod.image_put_pixel(img, x, y, colors[c]) return img
def create_map_legend(self, con, mode=0): for x in range(game.WORLDMAP_WIDTH): for y in range(game.WORLDMAP_HEIGHT): if mode == 0: cellheight = libtcod.heightmap_get_value(game.heightmap, x, y) else: cellheight = self.hm_list[(y * game.WORLDMAP_WIDTH) + x] if cellheight >= game.terrain['Mountain Peak']['elevation']: # mountain peak bcolor = libtcod.color_lerp(libtcod.silver, libtcod.grey, (1.000 - cellheight) / 0.050) elif cellheight >= game.terrain['Mountains']['elevation']: # mountains bcolor = libtcod.color_lerp(libtcod.grey, libtcod.Color(40, 24, 12), (game.terrain['Mountain Peak']['elevation'] - cellheight) / 0.125) elif cellheight >= game.terrain['High Hills']['elevation']: # hills bcolor = libtcod.color_lerp(libtcod.Color(40, 24, 12), libtcod.Color(53, 33, 16), (game.terrain['Mountains']['elevation'] - cellheight) / 0.125) elif cellheight >= game.terrain['Low Hills']['elevation']: # forest bcolor = libtcod.color_lerp(libtcod.Color(53, 33, 16), libtcod.Color(40, 67, 25), (game.terrain['High Hills']['elevation'] - cellheight) / 0.125) elif cellheight >= game.terrain['Forest']['elevation']: # forest bcolor = libtcod.color_lerp(libtcod.Color(40, 67, 25), libtcod.Color(80, 134, 50), (game.terrain['Low Hills']['elevation'] - cellheight) / 0.345) elif cellheight >= game.terrain['Plains']['elevation']: # plains bcolor = libtcod.color_lerp(libtcod.Color(80, 134, 50), libtcod.Color(112, 150, 80), (game.terrain['Forest']['elevation'] - cellheight) / 0.090) elif cellheight >= game.terrain['Coast']['elevation']: # coast bcolor = libtcod.color_lerp(libtcod.Color(112, 150, 80), libtcod.Color(176, 176, 153), (game.terrain['Plains']['elevation'] - cellheight) / 0.020) elif cellheight >= game.terrain['Shore']['elevation']: # shallow water bcolor = libtcod.color_lerp(libtcod.Color(176, 176, 153), libtcod.Color(47, 67, 103), (game.terrain['Coast']['elevation'] - cellheight) / 0.010) elif cellheight >= game.terrain['Sea']['elevation']: # deep water bcolor = libtcod.color_lerp(libtcod.Color(47, 67, 103), libtcod.Color(8, 32, 72), (game.terrain['Shore']['elevation'] - cellheight) / 0.040) else: # ocean bcolor = libtcod.Color(8, 32, 72) libtcod.console_put_char_ex(con, x, y, ' ', bcolor, bcolor) if mode != 3: libtcod.image_put_pixel(self.map_image_small, x, y, bcolor) if mode == 0: self.hm_list[(y * game.WORLDMAP_WIDTH) + x] = float("{0:.4f}".format(cellheight))
def generate_screen(): # create 'computer screen' backdrop and store in screen_img screen_img = libtcod.image_new(160, 100) for x in range(124): for y in range(68): libtcod.image_put_pixel(screen_img, x + 16, y + 16, libtcod.grey) for x in range(120): for y in range(60): libtcod.image_put_pixel(screen_img, x + 18, y + 18, libtcod.darkest_green) for x in range(3): libtcod.image_put_pixel(screen_img, x + 132, 80, libtcod.red) return screen_img
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)
def generate(self): self.owner.log.message("Generating map...", debug = True) noise = libtcod.noise_new(2, 0.5, 2.0) heightmap = libtcod.heightmap_new(2*self.width, 2*self.height) maxi = 0 mini = 0 self.tiles = [[ Tile() for y in range(self.height) ] for x in range(self.width) ] self.owner.log.message("-- creating heightmap...", debug = True) for x in range(self.width*2): for y in range(self.height*2): f = [3 * float(x) / (2*self.width), 3 * float(y) / (2*self.height)] value = (libtcod.noise_get_fbm(noise, f, 5, libtcod.NOISE_PERLIN))/2 if value > maxi: maxi = value if value < mini: mini = value libtcod.heightmap_set_value(heightmap, x, y, value) # print "-- erode the map" # libtcod.heightmap_rain_erosion(heightmap, self.width*2*self.height*2*2,0.1,0.2) self.owner.log.message("-- normalize heights...", debug = True) self.heightmap = libtcod.heightmap_new(self.width*2, self.height*2) for x in range(self.width*2): for y in range(self.height*2): value = libtcod.heightmap_get_value(heightmap, x, y) if value < 0: value += 1 mini2 = mini + 1 coeff = (value - mini2)/(1-mini2) libtcod.heightmap_set_value(self.heightmap, x, y, -coeff) else: value = value / maxi libtcod.heightmap_set_value(self.heightmap, x, y, value) self.owner.log.message("-- setting up tiles", debug = True) for x in range(self.width): for y in range(self.height): h = libtcod.heightmap_get_value(self.heightmap, x*2, y*2) if h >= 0.05: self.tiles[x][y].terrain = "land" else: self.tiles[x][y].terrain = "water" # self.owner.log.message("-- creating temperature map", debug = True) # noise2 = libtcod.noise_new(2, 0.5, 2.0) # temp_max = 0 # temp_min = 1 # for x in range(self.width): # for y in range(self.height): # f = [3 * float(x) / (self.width), 3 * float(y) / (self.height)] # value = (libtcod.noise_get_fbm(noise2, f, 5, libtcod.NOISE_PERLIN))/2 # value = (value + 1)/2 # if value < temp_min: # temp_min = value # if value > temp_max: # temp_max = value # self.tiles[x][y].temp = value # temp_max = temp_max - temp_min # height_factor = 0.5 # for x in range(self.width): # for y in range(self.height): # temp = (self.tiles[x][y].temp - temp_min)/temp_max # h = libtcod.heightmap_get_value(self.heightmap, x*2, y*2) # if h > 0: # factor = (-h)*height_factor # temp = temp + factor # temp = min(1, temp) # temp = max(0, temp) # self.tiles[x][y].temp = temp self.owner.log.message("-- creating rainfall map", debug = True) noise3 = libtcod.noise_new(2, 0.5, 2.0) self.rainmap = libtcod.heightmap_new(self.width*2, self.height*2) rain_max = 0 rain_min = 1 for x in range(self.width*2): for y in range(self.height*2): f = [5 * float(x) / (self.width*2), 5 * float(y) / (self.height*2)] value = (libtcod.noise_get_fbm(noise3, f, 5, libtcod.NOISE_PERLIN))/2 value = (value + 1)/2 if value < rain_min: rain_min = value if value > rain_max: rain_max = value self.tiles[x/2][y/2].rain = value libtcod.heightmap_set_value(self.rainmap, x, y, value) rain_max = rain_max - rain_min for x in range(self.width*2): for y in range(self.height*2): libtcod.heightmap_set_value(self.rainmap, x, y, (libtcod.heightmap_get_value(self.rainmap, x, y) - rain_min)/rain_max) self.tiles[x/2][y/2].rain = (self.tiles[x/2][y/2].rain - rain_min)/rain_max self.owner.log.message("Terrain complete", debug = True) self.owner.log.message("Painting terrain", debug = True) deep = libtcod.Color(1, 10, 27) mid = libtcod.Color(38, 50, 60) shallow = libtcod.Color(51, 83, 120) water_idx = [0, 70, 210, 255] water_cols = [deep, deep, mid, shallow] water_colormap = libtcod.color_gen_map(water_cols, water_idx) mountaintop = libtcod.Color(145, 196, 88) grass = libtcod.Color(40, 62, 19) foothill = libtcod.Color(57, 81, 34) sand = libtcod.Color(215, 185, 115) watersedge = libtcod.Color(19, 97, 101) land_idx = [0, 15, 20, 128, 255] land_cols = [watersedge, sand, grass, foothill, mountaintop] land_colormap = libtcod.color_gen_map(land_cols, land_idx) # Apply height-based colours for x in range(self.width*2): for y in range(self.height*2): value = libtcod.heightmap_get_value(self.heightmap, x, y) if value < 0: index = int(-value * 255) libtcod.image_put_pixel(self.image, x, y, water_colormap[index]) else: index = int(value * 255) libtcod.image_put_pixel(self.image, x, y, land_colormap[index]) # Adjust colours for desert-plains-forest for x in range(self.width*2): for y in range(self.height*2): if libtcod.heightmap_get_value(self.heightmap, x, y) > 0: rain = libtcod.heightmap_get_value(self.rainmap, x, y) cur_col = libtcod.image_get_pixel(self.image, x, y) cols = [libtcod.light_sepia, cur_col, cur_col, cur_col * 1.1] col_idx = [0, 100, 165, 255] col_map = libtcod.color_gen_map(cols, col_idx) index = int(rain*255) if index > 165 and libtcod.heightmap_get_value(self.heightmap, x, y) > 0.15: self.tiles[x/2][y/2].biome = "forest" self.tiles[x/2][y/2].char = 'T' self.tiles[x/2][y/2].fg_color = grass * 0.7 libtcod.image_put_pixel(self.image, x, y, col_map[index]) self.owner.log.message("-- apply normal shadows", debug = True) for x in range(self.width*2): for y in range(self.height*2): normal = libtcod.heightmap_get_normal(self.heightmap, x, y, 0) nx = normal[0] ny = normal[1] avg = (nx + ny)/2 if avg > 0: avg = 1 else: avg = avg + 1 avg = min(avg/2 + 0.5, 1) col = libtcod.image_get_pixel(self.image, x, y) * avg libtcod.image_put_pixel(self.image, x, y, col) self.owner.log.message("Placing cities", debug=True) self.owner.entities = [] max_cities = 10 num_cities = 0 for i in range(max_cities): x = libtcod.random_get_int(0, 0, self.width - 1) y = libtcod.random_get_int(0, 0, self.height - 1) if self.tiles[x][y].terrain == "land": city = entity.City(self.owner, x, y, '#', libtcod.Color(libtcod.random_get_int(0, 0, 255), libtcod.random_get_int(0, 0, 255), libtcod.random_get_int(0, 0, 255))) self.owner.entities.append(city) num_cities += 1 self.owner.log.message("-- placed " + str(num_cities) + " cities") self.owner.log.message("Map generated", debug = True) self.generated = True
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)
##=============================================================================== def getMap(self): ##=============================================================================== return self.map_arr #Just for testing ;) if __name__ == "__main__": Main_Console = libtcod.console_init_root(Game_Screen_Width, Game_Screen_Height, "Lost Horizon 0.0.1a", False) libtcod.sys_set_fps(25) map = GenDungeon(50, 50, var=50) map_arr = map.getMap() pix = libtcod.image_new(len(map_arr), len(map_arr)) for x in range(len(map_arr)): for y in range(len(map_arr)): if map_arr[x][y] == "#": libtcod.image_put_pixel(pix, x, y, libtcod.dark_grey) if map_arr[x][y] == " ": libtcod.image_put_pixel(pix, x, y, libtcod.white) while not libtcod.console_is_window_closed(): #libtcod.image_blit(pix,0,50,50,libtcod.BKGND_SET,1.0,1.0,0.0) libtcod.image_blit_2x(pix, 0, 0, 0) libtcod.console_flush() key = libtcod.console_check_for_keypress(libtcod.KEY_PRESSED) if key.vk == libtcod.KEY_ESCAPE: break
while phi <= pi_div_two: while theta <= pi_times_two: f = [ noise_zoom * math.cos(phi) * math.cos(theta), noise_zoom * math.cos(phi) * math.sin(theta), noise_zoom * math.sin(phi), ] value = 0.0 value = libtcod.noise_get_fbm(noise, f, noise_octaves, libtcod.NOISE_PERLIN) c = int((value + 1.0) / 2.0 * 255) if c < 0: c = 0 elif c > 255: c = 255 col = libtcod.Color(c // 2, c // 2, c) libtcod.image_put_pixel(noise_img,x,y,col) theta += (pi_times_two / SCREEN_WIDTH) x += 1 phi += (math.pi / SCREEN_HEIGHT) y += 1 x = 0 theta = 0.0 # for y in range(SCREEN_HEIGHT): # for x in range(SCREEN_WIDTH): # f = [noise_zoom * x / (SCREEN_WIDTH) + noise_dx, # noise_zoom * y / (SCREEN_HEIGHT) + noise_dy] # pp(f) # value = 0.0 # value = libtcod.noise_get_fbm(noise, f, noise_octaves, libtcod.NOISE_PERLIN) # c = int((value + 1.0) / 2.0 * 255)
##=============================================================================== def getMap(self): ##=============================================================================== return self.map_arr #Just for testing ;) if __name__ == "__main__": Main_Console = libtcod.console_init_root(Game_Screen_Width,Game_Screen_Height,"Lost Horizon 0.0.1a",False) libtcod.sys_set_fps(25) map = GenDungeon(50,50,var=50) map_arr = map.getMap() pix = libtcod.image_new(len(map_arr),len(map_arr)) for x in range(len(map_arr)): for y in range(len(map_arr)): if map_arr[x][y] == "#": libtcod.image_put_pixel(pix,x,y,libtcod.dark_grey) if map_arr[x][y] == " ": libtcod.image_put_pixel(pix,x,y,libtcod.white) while not libtcod.console_is_window_closed(): #libtcod.image_blit(pix,0,50,50,libtcod.BKGND_SET,1.0,1.0,0.0) libtcod.image_blit_2x(pix,0,0,0) libtcod.console_flush() key = libtcod.console_check_for_keypress(libtcod.KEY_PRESSED) if key.vk == libtcod.KEY_ESCAPE: break
def image_put_pixel(self,i,x,y,r,g,b): col = libtcod.Color(r,g,b) libtcod.image_put_pixel(self.mImages[i-1],x,y,col)