def initialize_rivers(self): lm = self.lm img_fullsize = self.get_material_image("Shallow water") imgs = {} for dx in [-1,0,1]: for dy in[-1,0,1]: imgs = tm.build_tiles(img_fullsize, lm.cell_sizes, lm.nframes, dx*lm.nframes, dy*lm.nframes, #dx, dy sin=False) river_obj = MapObject(self, imgs[0], "river", 1.) river_obj.is_ground = True self.register_object_type(river_obj)
def add_random_river(me, layer, material_dict, imgs, costs_materials, costs_objects, possible_materials, possible_objects, min_length, max_length): """Computes and draw a random river.""" print(" Building random river...") lm = me.lm md = material_dict #1) pick one random end if "shallow water" in md: cell_end = random.choice(md["shallow water"]) elif "grass" in md: cell_end = random.choice(md["grass"]) elif "snow" in md: cell_end = random.choice(md["snow"]) else: return #2) pick one random source if "snow" in md: cell_source = random.choice(md["snow"]) elif "thin snow" in md: cell_source = random.choice(md["thin snow"]) elif "rock" in md: cell_source = random.choice(md["rock"]) else: return #3) verify distance cell_source = lm.cells[cell_source[0]][cell_source[1]] cell_end = lm.cells[cell_end[0]][cell_end[1]] if min_length <= cell_source.distance_to(cell_end) <= max_length: pass else: return sp = BranchAndBoundForMap(lm, cell_source, cell_end, costs_materials, costs_objects, possible_materials, possible_objects) path = sp.solve() #4) change the end to first shallow shore cell actual_path = [] for cell in path: if cell.name == "river": break actual_path.append(cell) if "water" in cell.material.name.lower(): break else: next_to_water = False for neigh in cell.get_neighbors_von_neuman(): if neigh: if "water" in neigh.material.name.lower(): next_to_water = True break if next_to_water: break # objs = {} for delta in imgs: #imgs[(dx,dy)][zoom] river_obj = MapObject(me, imgs[delta][0], "river", 1.) river_obj.is_ground = True objs[delta] = river_obj #5) add river cells to map and layer for i,cell in enumerate(actual_path): dx,dy = get_path_orientation(i, cell, actual_path) c = objs.get((dx,dy)) if not c: raise Exception("No river object for delta", dx, dy) assert cell.name != "river" c = c.add_copy_on_cell(cell) cell.name = "river" layer.static_objects.append(c) if path: print("RIVER BUILT:", [cell.coord for cell in path]) return objs
def add_static_objects(self, me): #1) We use another hmap to decide where we want trees (or any other object) S = len(me.hmap) self._forest_map = ng.generate_terrain(S, n_octaves=self.static_objects_n_octaves, persistance=self.static_objects_persistance, chunk=self.static_objects_chunk) ng.normalize(self._forest_map) #me.lm is a superimposed map on which we decide to blit some static objects: #3) We build the objects that we want. # its up to you to decide what should be the size of the object (3rd arg) tree = MapObject(me,self.tree,self.forest_text,self.tree_size) tree.max_relpos = [0., 0.] fir1 = MapObject(me,self.fir1,self.forest_text,self.fir1_size) fir1.max_relpos = [0., 0.] fir2 = MapObject(me,self.fir2,self.forest_text,self.fir2_size) fir2.max_relpos = [0., 0.] firsnow = MapObject(me,self.firsnow, self.forest_snow_text, self.firsnow_size) firsnow.max_relpos = [0., 0.] fir1.set_same_type([fir2, firsnow]) palm = MapObject(me,self.palm,self.palm_text,self.palm_size) palm.max_relpos[0] = 0.1 #restrict because they are near to water palm.min_relpos[0] = -0.1 bush = MapObject(me,self.bush,"bush",self.bush_size) village1 = MapObject(me,self.village1, "village",self.village1_size) ## village2 = MapObject(me,self.village2, "village",self.village2_size) ## village3 = MapObject(me,self.village3, "village",self.village3_size) ## all_villages = [village1,village2,village3] all_villages = [village1] for v in all_villages: v.max_relpos = [0, 0.15] v.min_relpos = [0, 0.1] # cobble = MapObject(me,self.cobble,"cobblestone",self.cobble_size) cobble.is_ground = True self.cobblestone = cobble bridge_h = MapObject(me,self.bridge_h,"bridge",self.bridge_h_size, str_type="bridge_h") bridge_h.is_ground = True bridge_h.max_relpos = [0., 0.] bridge_h.min_relpos = [0., 0.] bridge_v = MapObject(me,self.bridge_v,"bridge",self.bridge_v_size, str_type="bridge_v") bridge_v.is_ground = True bridge_v.max_relpos = [0.,0.] bridge_v.min_relpos = [0., 0.] self.bridge_h_mapobject = bridge_h self.bridge_v_mapobject = bridge_v self._objects = {"oak":tree, "fir1":fir1, "fir2":fir2, "firsnow":firsnow, "palm":palm, "bush":bush, "village":village1, "cobble":cobble, "bridge_h":bridge_h, "bridge_v":bridge_v, "road":cobble} #4) we add the objects via distributors, to add them randomly in a nice way #normal forest ## print("LALA 1", tree.relpos, tree.max_relpos, tree.min_relpos) all_forest = [fir1, fir2, tree] distributor = objs.get_distributor(me, all_forest, self._forest_map, ["Grass","Rock"]) ## print("LALA 2", tree.relpos, tree.max_relpos, tree.min_relpos) for obj in distributor.objs: obj.max_relpos[1] *= self.forest_relposy_multiplier ## print("LALA 3", tree.relpos, tree.max_relpos, tree.min_relpos) ## tree.max_relpos = [0., -0.25] #!!!!!!!!!!!!!!!!! ## tree.max_relpos = list(tree.min_relpos) ## tree.randomize_relpos() distributor.max_density = self.forest_max_density distributor.homogeneity = self.forest_homogeneity distributor.zones_spread = self.forest_zones_spread distributor.distribute_objects(me.lm, exclusive=True) #here, relpos is randomized for each object distributed #more trees in plains distributor = objs.get_distributor(me, [tree], self._forest_map, ["Grass"]) for obj in distributor.objs: obj.max_relpos[1] *= self.forest_relposy_multiplier distributor.max_density = self.forest_max_density distributor.homogeneity = self.forest_homogeneity distributor.zones_spread = self.forest_zones_spread distributor.distribute_objects(me.lm, exclusive=True) #snow forest distributor = objs.get_distributor(me, [firsnow, firsnow.flip()], self._forest_map, ["Thin snow","Snow"]) for obj in distributor.objs: obj.max_relpos[1] *= self.forest_relposy_multiplier distributor.max_density = self.forest_snow_max_density distributor.homogeneity = self.forest_snow_homogeneity distributor.zones_spread = self.forest_snow_zones_spread distributor.distribute_objects(me.lm, exclusive=True) #palm forest distributor = objs.get_distributor(me, [palm, palm.flip()], self._forest_map, ["Sand"]) for obj in distributor.objs: obj.max_relpos[1] *= self.forest_relposy_multiplier distributor.max_density = self.palm_max_density distributor.homogeneity = self.palm_homogeneity distributor.zones_spread = self.palm_zones_spread distributor.distribute_objects(me.lm, exclusive=True) #bushes distributor = objs.get_distributor(me, [bush], self._forest_map, ["Grass"]) distributor.max_density = 2 distributor.homogeneity = 0.2 distributor.zones_spread = [(0., 0.05), (0.3,0.05), (0.6,0.05)] distributor.distribute_objects(me.lm) #villages distributor = objs.get_distributor(me, [village1, village1.flip()], self._forest_map, ["Grass"], limit_relpos_y=False) distributor.max_density = 1 distributor.homogeneity = self.village_homogeneity distributor.zones_spread = [(0.1, 0.02), (0.2,0.02), (0.4,0.02), (0.5,0.02)] ## distributor.distribute_objects(me.lm, exclusive=True) village_mat = list(me.materials.keys()) village_mat = [n for n in village_mat if not("water" in n.lower())] village_mat.remove("outside") objs.simple_distribution(me, [village1, village1.flip()], village_mat, 6) cobbles = [cobble, cobble.flip(True,False), cobble.flip(False,True), cobble.flip(True,True)] ############################################################################ #Here we show how to use the path finder for a given unit of the game #Actually, we use it here in order to build cobblestone roads on the map me.initialize_rivers() costs_materials_road = {name:1. for name in me.materials} costs_materials_road["Snow"] = 10. #unit is 10 times slower in snow costs_materials_road["Thin snow"] = 2. #twice slower on thin snow... costs_materials_road["Sand"] = 2. ## for name in me.materials: ## if "water" in name.lower(): ## costs_materials_road[name] = 10 print(" COST SHALLOW WATER", costs_materials_road) river_type = me.object_types["river"] costs_objects_road = {bush.int_type: 2., #unit is 2 times slower in bushes cobble.int_type: 0.9, river_type:2.} #Materials allowed (here we allow water because we add bridges) possible_materials_road=list(me.materials) for name in me.materials: if "water" in name.lower(): possible_materials_road.remove(name) possible_objects_road=[cobble.int_type, bush.int_type, village1.int_type, river_type] ######################################################################## #now we build a path for rivers, just like we did with roads. costs_materials_river = {name:1. for name in me.materials} #Materials allowed (here we allow water because we add bridges) possible_materials_river=list(me.materials) possible_objects_river=[] river_img = me.get_material_image("Shallow water") random.seed(self.seed_static_objects) n_roads = 0 n_rivers = 0 imgs_river = {} lm = me.lm for dx in [-1,0,1]: for dy in[-1,0,1]: imgs_river[(dx,dy)] = tm.build_tiles(river_img, lm.cell_sizes, lm.nframes, dx*lm.nframes, dy*lm.nframes, #dx, dy sin=False) self.imgs_river = imgs_river material_dict = get_materials_dict(lm) self.update_loading_bar("Finding paths for rivers and roads...",0.6) while n_roads < self.max_number_of_roads or n_rivers < self.max_number_of_rivers: if n_rivers < self.max_number_of_rivers: n_rivers += 1 self.rivers = add_random_river(me, me.lm, material_dict, imgs_river, costs_materials_river, costs_objects_road, possible_materials_river, possible_objects_river, min_length=self.min_river_length, max_length=self.max_river_length) if n_roads < self.max_number_of_roads: n_roads += 1 add_random_road(me.lm, me.lm, cobbles, (bridge_h,bridge_v), costs_materials_road, costs_objects_road, possible_materials_road, possible_objects_road, min_length=self.min_road_length, max_length=self.max_road_length)