add tiles
BIN
assets/tiles/cave.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/tiles/city.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
assets/tiles/desert.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
assets/tiles/farm.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
assets/tiles/forest.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
assets/tiles/glacier.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
assets/tiles/grassland.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/tiles/mountain.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
assets/tiles/original.jpg
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
assets/tiles/plain.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
assets/tiles/rainforest.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
assets/tiles/ruins.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
assets/tiles/sea.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
assets/tiles/snow_mountain.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
assets/tiles/swamp.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
assets/tiles/volcano.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
assets/tiles/water.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
@@ -16,6 +16,11 @@ class TileType(Enum):
|
|||||||
GLACIER = "glacier" # 冰川/冰原
|
GLACIER = "glacier" # 冰川/冰原
|
||||||
SNOW_MOUNTAIN = "snow_mountain" # 雪山
|
SNOW_MOUNTAIN = "snow_mountain" # 雪山
|
||||||
VOLCANO = "volcano" # 火山
|
VOLCANO = "volcano" # 火山
|
||||||
|
GRASSLAND = "grassland" # 草原
|
||||||
|
SWAMP = "swamp" # 沼泽
|
||||||
|
CAVE = "cave" # 洞穴
|
||||||
|
RUINS = "ruins" # 遗迹
|
||||||
|
FARM = "farm" # 农田
|
||||||
|
|
||||||
region_id_counter = itertools.count(1)
|
region_id_counter = itertools.count(1)
|
||||||
|
|
||||||
|
|||||||
@@ -74,19 +74,9 @@ class Front:
|
|||||||
"avatar": (240, 220, 90),
|
"avatar": (240, 220, 90),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tile_colors: Dict[TileType, Tuple[int, int, int]] = {
|
# 加载tile图像
|
||||||
TileType.PLAIN: (64, 120, 64),
|
self.tile_images: Dict[TileType, object] = {}
|
||||||
TileType.FOREST: (24, 96, 48),
|
self._load_tile_images()
|
||||||
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), # 火山红色
|
|
||||||
}
|
|
||||||
|
|
||||||
self.clock = pygame.time.Clock()
|
self.clock = pygame.time.Clock()
|
||||||
|
|
||||||
@@ -159,13 +149,20 @@ class Front:
|
|||||||
ts = self.tile_size
|
ts = self.tile_size
|
||||||
m = self.margin
|
m = self.margin
|
||||||
|
|
||||||
# 先画网格背景块
|
# 先画tile图像
|
||||||
for y in range(map_obj.height):
|
for y in range(map_obj.height):
|
||||||
for x in range(map_obj.width):
|
for x in range(map_obj.width):
|
||||||
tile = map_obj.get_tile(x, y)
|
tile = map_obj.get_tile(x, y)
|
||||||
color = self.tile_colors.get(tile.type, (80, 80, 80))
|
tile_image = self.tile_images.get(tile.type)
|
||||||
rect = pygame.Rect(m + x * ts, m + y * ts, ts, ts)
|
if tile_image:
|
||||||
pygame.draw.rect(self.screen, color, rect)
|
# 使用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"]
|
grid_color = self.colors["grid"]
|
||||||
@@ -377,6 +374,43 @@ class Front:
|
|||||||
cursor_y += s.get_height() + spacing
|
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):
|
def _create_font(self, size: int):
|
||||||
pygame = self.pygame
|
pygame = self.pygame
|
||||||
if self.font_path:
|
if self.font_path:
|
||||||
|
|||||||
@@ -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)
|
game_map.create_tile(x, y, TileType.VOLCANO)
|
||||||
volcano_tiles.append((x, y))
|
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个,尽量落在非极端地形
|
# 9) 城市:2~4个,尽量落在非极端地形
|
||||||
cities = 0
|
cities = 0
|
||||||
attempts = 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)
|
x = random.randint(0, width - 1)
|
||||||
y = random.randint(0, height - 1)
|
y = random.randint(0, height - 1)
|
||||||
t = game_map.get_tile(x, y)
|
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)
|
game_map.create_tile(x, y, TileType.CITY)
|
||||||
cities += 1
|
cities += 1
|
||||||
|
|
||||||
@@ -359,6 +453,81 @@ def build_rich_random_map(width: int = 30, height: int = 20, *, seed: int | None
|
|||||||
"tiles": volcano_tiles
|
"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):
|
for i, comp in enumerate(sorted(mountain_clusters, key=len, reverse=True), start=1):
|
||||||
regions_cfg.append({
|
regions_cfg.append({
|
||||||
"name": f"高山{i}",
|
"name": f"高山{i}",
|
||||||
@@ -414,7 +583,7 @@ def make_avatars(world: World, count: int = 12) -> list[Avatar]:
|
|||||||
x = random.randint(0, width - 1)
|
x = random.randint(0, width - 1)
|
||||||
y = random.randint(0, height - 1)
|
y = random.randint(0, height - 1)
|
||||||
t = world.map.get_tile(x, y)
|
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
|
break
|
||||||
else:
|
else:
|
||||||
x, y = random.randint(0, width - 1), random.randint(0, height - 1)
|
x, y = random.randint(0, width - 1), random.randint(0, height - 1)
|
||||||
|
|||||||