diff --git a/assets/tiles/cave.png b/assets/tiles/cave.png new file mode 100644 index 0000000..3942d77 Binary files /dev/null and b/assets/tiles/cave.png differ diff --git a/assets/tiles/city.png b/assets/tiles/city.png new file mode 100644 index 0000000..a9fa384 Binary files /dev/null and b/assets/tiles/city.png differ diff --git a/assets/tiles/desert.png b/assets/tiles/desert.png new file mode 100644 index 0000000..050659a Binary files /dev/null and b/assets/tiles/desert.png differ diff --git a/assets/tiles/farm.png b/assets/tiles/farm.png new file mode 100644 index 0000000..cc81a41 Binary files /dev/null and b/assets/tiles/farm.png differ diff --git a/assets/tiles/forest.png b/assets/tiles/forest.png new file mode 100644 index 0000000..376aaa9 Binary files /dev/null and b/assets/tiles/forest.png differ diff --git a/assets/tiles/glacier.png b/assets/tiles/glacier.png new file mode 100644 index 0000000..25cf8c9 Binary files /dev/null and b/assets/tiles/glacier.png differ diff --git a/assets/tiles/grassland.png b/assets/tiles/grassland.png new file mode 100644 index 0000000..490ed1f Binary files /dev/null and b/assets/tiles/grassland.png differ diff --git a/assets/tiles/mountain.png b/assets/tiles/mountain.png new file mode 100644 index 0000000..ac5134b Binary files /dev/null and b/assets/tiles/mountain.png differ diff --git a/assets/tiles/original.jpg b/assets/tiles/original.jpg new file mode 100644 index 0000000..fedc46a Binary files /dev/null and b/assets/tiles/original.jpg differ diff --git a/assets/tiles/plain.png b/assets/tiles/plain.png new file mode 100644 index 0000000..05ce1b7 Binary files /dev/null and b/assets/tiles/plain.png differ diff --git a/assets/tiles/rainforest.png b/assets/tiles/rainforest.png new file mode 100644 index 0000000..7f2f748 Binary files /dev/null and b/assets/tiles/rainforest.png differ diff --git a/assets/tiles/ruins.png b/assets/tiles/ruins.png new file mode 100644 index 0000000..47de6e0 Binary files /dev/null and b/assets/tiles/ruins.png differ diff --git a/assets/tiles/sea.png b/assets/tiles/sea.png new file mode 100644 index 0000000..36a3455 Binary files /dev/null and b/assets/tiles/sea.png differ diff --git a/assets/tiles/snow_mountain.png b/assets/tiles/snow_mountain.png new file mode 100644 index 0000000..f21a833 Binary files /dev/null and b/assets/tiles/snow_mountain.png differ diff --git a/assets/tiles/swamp.png b/assets/tiles/swamp.png new file mode 100644 index 0000000..9133632 Binary files /dev/null and b/assets/tiles/swamp.png differ diff --git a/assets/tiles/volcano.png b/assets/tiles/volcano.png new file mode 100644 index 0000000..af856fe Binary files /dev/null and b/assets/tiles/volcano.png differ diff --git a/assets/tiles/water.png b/assets/tiles/water.png new file mode 100644 index 0000000..0c25f0f Binary files /dev/null and b/assets/tiles/water.png differ diff --git a/src/classes/tile.py b/src/classes/tile.py index 0818445..6bd2fa7 100644 --- a/src/classes/tile.py +++ b/src/classes/tile.py @@ -16,6 +16,11 @@ class TileType(Enum): GLACIER = "glacier" # 冰川/冰原 SNOW_MOUNTAIN = "snow_mountain" # 雪山 VOLCANO = "volcano" # 火山 + GRASSLAND = "grassland" # 草原 + SWAMP = "swamp" # 沼泽 + CAVE = "cave" # 洞穴 + RUINS = "ruins" # 遗迹 + FARM = "farm" # 农田 region_id_counter = itertools.count(1) diff --git a/src/front/front.py b/src/front/front.py index a579e78..1dfcac9 100644 --- a/src/front/front.py +++ b/src/front/front.py @@ -74,19 +74,9 @@ class Front: "avatar": (240, 220, 90), } - self.tile_colors: Dict[TileType, Tuple[int, int, int]] = { - TileType.PLAIN: (64, 120, 64), - TileType.FOREST: (24, 96, 48), - TileType.MOUNTAIN: (108, 108, 108), - TileType.WATER: (60, 120, 180), - TileType.SEA: (30, 90, 150), - TileType.CITY: (140, 120, 90), - TileType.DESERT: (210, 180, 60), - TileType.RAINFOREST: (12, 80, 36), - TileType.GLACIER: (210, 230, 240), - TileType.SNOW_MOUNTAIN: (200, 200, 200), - TileType.VOLCANO: (180, 40, 40), # 火山红色 - } + # 加载tile图像 + self.tile_images: Dict[TileType, object] = {} + self._load_tile_images() self.clock = pygame.time.Clock() @@ -159,13 +149,20 @@ class Front: ts = self.tile_size m = self.margin - # 先画网格背景块 + # 先画tile图像 for y in range(map_obj.height): for x in range(map_obj.width): tile = map_obj.get_tile(x, y) - color = self.tile_colors.get(tile.type, (80, 80, 80)) - rect = pygame.Rect(m + x * ts, m + y * ts, ts, ts) - pygame.draw.rect(self.screen, color, rect) + tile_image = self.tile_images.get(tile.type) + if tile_image: + # 使用tile图像 + pos = (m + x * ts, m + y * ts) + self.screen.blit(tile_image, pos) + else: + # 如果没有图像,使用默认颜色块 + color = (80, 80, 80) # 默认灰色 + rect = pygame.Rect(m + x * ts, m + y * ts, ts, ts) + pygame.draw.rect(self.screen, color, rect) # 画网格线 grid_color = self.colors["grid"] @@ -377,6 +374,43 @@ class Front: cursor_y += s.get_height() + spacing + def _load_tile_images(self): + """ + 加载所有tile类型的图像 + """ + import os + pygame = self.pygame + + # 定义所有tile类型 + tile_types = [ + TileType.PLAIN, TileType.WATER, TileType.SEA, TileType.MOUNTAIN, + TileType.FOREST, TileType.CITY, TileType.DESERT, TileType.RAINFOREST, + TileType.GLACIER, TileType.SNOW_MOUNTAIN, TileType.VOLCANO, + TileType.GRASSLAND, TileType.SWAMP, TileType.CAVE, TileType.RUINS, TileType.FARM + ] + + for tile_type in tile_types: + image_path = f"assets/tiles/{tile_type.value}.png" + if os.path.exists(image_path): + try: + # 加载图像并缩放到tile_size + image = pygame.image.load(image_path) + scaled_image = pygame.transform.scale(image, (self.tile_size, self.tile_size)) + self.tile_images[tile_type] = scaled_image + print(f"已加载tile图像: {image_path}") + except Exception as e: + print(f"加载tile图像失败 {image_path}: {e}") + # 如果加载失败,创建一个默认的颜色块 + fallback_surface = pygame.Surface((self.tile_size, self.tile_size)) + fallback_surface.fill((128, 128, 128)) # 灰色作为默认 + self.tile_images[tile_type] = fallback_surface + else: + print(f"tile图像文件不存在: {image_path}") + # 创建默认颜色块 + fallback_surface = pygame.Surface((self.tile_size, self.tile_size)) + fallback_surface.fill((128, 128, 128)) + self.tile_images[tile_type] = fallback_surface + def _create_font(self, size: int): pygame = self.pygame if self.font_path: diff --git a/tests/run_front.py b/tests/run_front.py index 5694cfa..9873213 100644 --- a/tests/run_front.py +++ b/tests/run_front.py @@ -158,6 +158,100 @@ def build_rich_random_map(width: int = 30, height: int = 20, *, seed: int | None game_map.create_tile(x, y, TileType.VOLCANO) volcano_tiles.append((x, y)) + # 8.6) 草原:在平原区域生成一些草原 + grassland_tiles: List[Tuple[int, int]] = [] + for _ in range(random.randint(3, 5)): + cx = random.randint(desert_w + 1, mountain_end_x - 2) + cy = random.randint(north_band + 1, height - south_band - 2) + r = random.randint(2, 4) + for x, y in circle_points(cx, cy, r, width, height): + if x < sea_x0: + current_tile = game_map.get_tile(x, y) + if current_tile.type == TileType.PLAIN: # 只在平原上生成草原 + game_map.create_tile(x, y, TileType.GRASSLAND) + grassland_tiles.append((x, y)) + + # 8.7) 沼泽:在水域附近生成一些沼泽 + swamp_tiles: List[Tuple[int, int]] = [] + for _ in range(random.randint(2, 4)): + cx = random.randint(desert_w + 1, sea_x0 - 2) + cy = random.randint(north_band + 1, height - south_band - 2) + r = random.randint(1, 2) + for x, y in circle_points(cx, cy, r, width, height): + if x < sea_x0: + # 检查周围是否有水域 + has_water_nearby = False + for dx in [-1, 0, 1]: + for dy in [-1, 0, 1]: + nx, ny = x + dx, y + dy + if game_map.is_in_bounds(nx, ny): + nearby_tile = game_map.get_tile(nx, ny) + if nearby_tile.type in (TileType.WATER, TileType.SEA): + has_water_nearby = True + break + if has_water_nearby: + break + + if has_water_nearby: + current_tile = game_map.get_tile(x, y) + if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND): + game_map.create_tile(x, y, TileType.SWAMP) + swamp_tiles.append((x, y)) + + # 8.8) 洞穴:在山脉附近生成一些洞穴 + cave_tiles: List[Tuple[int, int]] = [] + for _ in range(random.randint(2, 4)): + cx = random.randint(desert_w + 1, mountain_end_x - 1) + cy = random.randint(north_band + 1, height - south_band - 2) + # 检查周围是否有山脉 + has_mountain_nearby = False + for dx in [-2, -1, 0, 1, 2]: + for dy in [-2, -1, 0, 1, 2]: + nx, ny = cx + dx, cy + dy + if game_map.is_in_bounds(nx, ny): + nearby_tile = game_map.get_tile(nx, ny) + if nearby_tile.type == TileType.MOUNTAIN: + has_mountain_nearby = True + break + if has_mountain_nearby: + break + + if has_mountain_nearby: + current_tile = game_map.get_tile(cx, cy) + if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND): + game_map.create_tile(cx, cy, TileType.CAVE) + cave_tiles.append((cx, cy)) + + # 8.9) 遗迹:随机在一些地方生成古代遗迹 + ruins_tiles: List[Tuple[int, int]] = [] + for _ in range(random.randint(2, 3)): + cx = random.randint(desert_w + 1, sea_x0 - 2) + cy = random.randint(north_band + 1, height - south_band - 2) + current_tile = game_map.get_tile(cx, cy) + if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND, TileType.DESERT): + game_map.create_tile(cx, cy, TileType.RUINS) + ruins_tiles.append((cx, cy)) + + # 8.10) 农田:在城市附近生成一些农田 + farm_tiles: List[Tuple[int, int]] = [] + # 先收集所有城市位置 + city_positions = [] + for (tx, ty), tile in game_map.tiles.items(): + if tile.type == TileType.CITY: + city_positions.append((tx, ty)) + + # 在每个城市周围生成农田 + for city_x, city_y in city_positions: + for _ in range(random.randint(3, 6)): + # 在城市周围2-4格范围内生成农田 + fx = city_x + random.randint(-4, 4) + fy = city_y + random.randint(-4, 4) + if game_map.is_in_bounds(fx, fy): + current_tile = game_map.get_tile(fx, fy) + if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND): + game_map.create_tile(fx, fy, TileType.FARM) + farm_tiles.append((fx, fy)) + # 9) 城市:2~4个,尽量落在非极端地形 cities = 0 attempts = 0 @@ -166,7 +260,7 @@ def build_rich_random_map(width: int = 30, height: int = 20, *, seed: int | None x = random.randint(0, width - 1) y = random.randint(0, height - 1) t = game_map.get_tile(x, y) - if t.type not in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.GLACIER, TileType.SNOW_MOUNTAIN, TileType.DESERT, TileType.VOLCANO): + if t.type not in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.GLACIER, TileType.SNOW_MOUNTAIN, TileType.DESERT, TileType.VOLCANO, TileType.SWAMP, TileType.CAVE, TileType.RUINS): game_map.create_tile(x, y, TileType.CITY) cities += 1 @@ -359,6 +453,81 @@ def build_rich_random_map(width: int = 30, height: int = 20, *, seed: int | None "tiles": volcano_tiles }) + # 添加草原region + if grassland_tiles: + regions_cfg.append({ + "name": "青青草原", + "description": "广阔的草原地带,适合放牧和修炼", + "essence": Essence(density={ + EssenceType.WOOD: 7, + EssenceType.EARTH: 6, + EssenceType.WATER: 5, + EssenceType.FIRE: 3, + EssenceType.GOLD: 2 + }), + "tiles": grassland_tiles + }) + + # 添加沼泽region + if swamp_tiles: + regions_cfg.append({ + "name": "迷雾沼泽", + "description": "危险的沼泽地带,瘴气弥漫但蕴含特殊灵药", + "essence": Essence(density={ + EssenceType.WATER: 8, + EssenceType.WOOD: 6, + EssenceType.EARTH: 5, + EssenceType.FIRE: 3, + EssenceType.GOLD: 2 + }), + "tiles": swamp_tiles + }) + + # 添加洞穴region + if cave_tiles: + regions_cfg.append({ + "name": "神秘洞穴", + "description": "隐藏在山脉中的神秘洞穴,可能藏有宝物", + "essence": Essence(density={ + EssenceType.EARTH: 9, + EssenceType.GOLD: 8, + EssenceType.FIRE: 4, + EssenceType.WATER: 3, + EssenceType.WOOD: 2 + }), + "tiles": cave_tiles + }) + + # 添加遗迹region + if ruins_tiles: + regions_cfg.append({ + "name": "古代遗迹", + "description": "上古时代留下的神秘遗迹,蕴含古老的力量", + "essence": Essence(density={ + EssenceType.GOLD: 9, + EssenceType.EARTH: 7, + EssenceType.FIRE: 6, + EssenceType.WATER: 5, + EssenceType.WOOD: 4 + }), + "tiles": ruins_tiles + }) + + # 添加农田region + if farm_tiles: + regions_cfg.append({ + "name": "良田", + "description": "肥沃的农田,为城市提供粮食", + "essence": Essence(density={ + EssenceType.WOOD: 8, + EssenceType.EARTH: 7, + EssenceType.WATER: 6, + EssenceType.FIRE: 3, + EssenceType.GOLD: 2 + }), + "tiles": farm_tiles + }) + for i, comp in enumerate(sorted(mountain_clusters, key=len, reverse=True), start=1): regions_cfg.append({ "name": f"高山{i}", @@ -414,7 +583,7 @@ def make_avatars(world: World, count: int = 12) -> list[Avatar]: x = random.randint(0, width - 1) y = random.randint(0, height - 1) t = world.map.get_tile(x, y) - if t.type not in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.VOLCANO): + if t.type not in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.VOLCANO, TileType.SWAMP, TileType.CAVE, TileType.RUINS): break else: x, y = random.randint(0, width - 1), random.randint(0, height - 1)