update map
This commit is contained in:
@@ -31,7 +31,7 @@ def load_avatar_images(pygame_mod, tile_size: int):
|
||||
if filename.endswith('.png') and filename != 'original.png' and filename.replace('.png', '').isdigit():
|
||||
image_path = os.path.join(male_dir, filename)
|
||||
image = pygame_mod.image.load(image_path)
|
||||
avatar_size = max(26, int((tile_size * 4 // 3) * 1.5))
|
||||
avatar_size = max(26, int((tile_size * 4 // 3) * 1.2))
|
||||
scaled = pygame_mod.transform.scale(image, (avatar_size, avatar_size))
|
||||
male_avatars.append(scaled)
|
||||
|
||||
|
||||
@@ -5,16 +5,43 @@ from src.classes.sect_region import SectRegion
|
||||
from src.classes.region import Shape
|
||||
from src.classes.sect import Sect
|
||||
|
||||
BASE_W = 70
|
||||
BASE_H = 50
|
||||
|
||||
def _scale_x(x: int, width: int) -> int:
|
||||
# 将以 BASE_W 为参考的 x 坐标按比例缩放到当前 width
|
||||
return int(round(x / BASE_W * width))
|
||||
|
||||
def _scale_y(y: int, height: int) -> int:
|
||||
# 将以 BASE_H 为参考的 y 坐标按比例缩放到当前 height
|
||||
return int(round(y / BASE_H * height))
|
||||
|
||||
def _scaled_range_x(x0: int, x1_exclusive: int, width: int) -> range:
|
||||
sx0 = max(0, min(width, _scale_x(x0, width)))
|
||||
sx1 = max(sx0, min(width, _scale_x(x1_exclusive, width)))
|
||||
return range(sx0, sx1)
|
||||
|
||||
def _scaled_range_y(y0: int, y1_exclusive: int, height: int) -> range:
|
||||
sy0 = max(0, min(height, _scale_y(y0, height)))
|
||||
sy1 = max(sy0, min(height, _scale_y(y1_exclusive, height)))
|
||||
return range(sy0, sy1)
|
||||
|
||||
|
||||
def create_cultivation_world_map() -> Map:
|
||||
"""
|
||||
创建修仙世界地图
|
||||
尺寸: 70x50
|
||||
创建修仙世界地图(按 0.8 比例缩小格子数量,保持构造不变)
|
||||
基准尺寸: 70x50 -> 实际尺寸: 56x40(约减少 36% 的 tile 数量)
|
||||
西部大漠,南部雨林,北边冰原,最东部和最南部海洋
|
||||
横向大河从大漠东部流向东南入海
|
||||
北方纵向山脉
|
||||
"""
|
||||
game_map = Map(width=70, height=50)
|
||||
# 将总格子数在宽高两个维度各缩小到 0.8 倍
|
||||
width = int(round(BASE_W * 0.8))
|
||||
height = int(round(BASE_H * 0.8))
|
||||
game_map = Map(width=width, height=height)
|
||||
|
||||
# 缩放从配置中加载的区域到新地图尺度
|
||||
_scale_loaded_regions(game_map)
|
||||
# 创建基础地形
|
||||
_create_base_terrain(game_map)
|
||||
|
||||
@@ -31,15 +58,15 @@ def add_sect_headquarters(game_map: Map, enabled_sects: list[Sect]):
|
||||
# 为九个宗门设计坐标(根据地图地形大势和叙事):
|
||||
# 仅登记矩形区域的西北角与东南角
|
||||
locs: dict[str, tuple[tuple[int, int], tuple[int, int]]] = {
|
||||
"明心剑宗": ((36, 10), (37, 11)), # 北部山脉以南的名门仙山
|
||||
"百兽宗": ((22, 22), (23, 23)), # 中西部靠近山林
|
||||
"水镜宗": ((58, 22), (59, 23)), # 湖心三岛——近东海内陆湖
|
||||
"冥王宗": ((66, 8), (67, 9)), # 东北近海的群岛
|
||||
"朱勾宗": ((48, 8), (49, 9)), # 东北内陆山地近雪域
|
||||
"合欢宗": ((62, 40), (63, 41)), # 东南近海桃花岛
|
||||
"镇魂宗": ((30, 46), (31, 47)), # 极南海上礁岛
|
||||
"幽魂噬影宗":((44, 38), (45, 39)), # 南部雨林深处
|
||||
"千帆城": ((60, 28), (61, 29)), # 海上浮岛靠近入海口
|
||||
"明心剑宗": ((36, 10), (37, 11)),
|
||||
"百兽宗": ((22, 22), (23, 23)),
|
||||
"水镜宗": ((58, 22), (59, 23)),
|
||||
"冥王宗": ((66, 8), (67, 9)),
|
||||
"朱勾宗": ((48, 8), (49, 9)),
|
||||
"合欢宗": ((62, 40), (63, 41)),
|
||||
"镇魂宗": ((30, 46), (31, 47)),
|
||||
"幽魂噬影宗":((44, 38), (45, 39)),
|
||||
"千帆城": ((60, 28), (61, 29)),
|
||||
}
|
||||
|
||||
name_to_sect = {s.name: s for s in enabled_sects}
|
||||
@@ -51,13 +78,21 @@ def add_sect_headquarters(game_map: Map, enabled_sects: list[Sect]):
|
||||
# 名称与描述来自 sect.headquarter;若为空则用 sect 名称/描述
|
||||
hq_name = getattr(sect.headquarter, "name", sect.name) or sect.name
|
||||
hq_desc = getattr(sect.headquarter, "desc", sect.desc) or sect.desc
|
||||
# 按比例缩放左上角坐标,保持区域尺寸(如2x2)不变
|
||||
base_w, base_h = BASE_W, BASE_H
|
||||
size_w = se[0] - nw[0]
|
||||
size_h = se[1] - nw[1]
|
||||
nw_x = max(0, min(game_map.width - 1, _scale_x(nw[0], game_map.width)))
|
||||
nw_y = max(0, min(game_map.height - 1, _scale_y(nw[1], game_map.height)))
|
||||
se_x = max(nw_x, min(game_map.width - 1, nw_x + size_w))
|
||||
se_y = max(nw_y, min(game_map.height - 1, nw_y + size_h))
|
||||
region = SectRegion(
|
||||
id=400 + sect.id, # 4xx 预留给宗门总部区域id
|
||||
id=400 + sect.id,
|
||||
name=hq_name,
|
||||
desc=hq_desc,
|
||||
shape=Shape.RECTANGLE,
|
||||
north_west_cor=f"{nw[0]},{nw[1]}",
|
||||
south_east_cor=f"{se[0]},{se[1]}",
|
||||
north_west_cor=f"{nw_x},{nw_y}",
|
||||
south_east_cor=f"{se_x},{se_y}",
|
||||
image_path=str(getattr(sect.headquarter, "image", None)),
|
||||
)
|
||||
game_map.regions[region.id] = region
|
||||
@@ -76,91 +111,93 @@ def _create_base_terrain(game_map: Map):
|
||||
game_map.create_tile(x, y, TileType.PLAIN)
|
||||
|
||||
# 西部大漠 (x: 0-18)
|
||||
for x in range(19):
|
||||
for x in _scaled_range_x(0, 19, width):
|
||||
for y in range(height):
|
||||
game_map.tiles[(x, y)].type = TileType.DESERT
|
||||
|
||||
# 南部雨林 (y: 35-49)
|
||||
for x in range(width):
|
||||
for y in range(35, height):
|
||||
for y in _scaled_range_y(35, BASE_H, height):
|
||||
if game_map.tiles[(x, y)].type != TileType.DESERT:
|
||||
game_map.tiles[(x, y)].type = TileType.RAINFOREST
|
||||
|
||||
# 北边冰原 (y: 0-8)
|
||||
for x in range(width):
|
||||
for y in range(9):
|
||||
for y in _scaled_range_y(0, 9, height):
|
||||
if game_map.tiles[(x, y)].type != TileType.DESERT:
|
||||
game_map.tiles[(x, y)].type = TileType.GLACIER
|
||||
|
||||
# 最东部海洋 (x: 65-69)
|
||||
for x in range(65, width):
|
||||
for x in _scaled_range_x(65, BASE_W, width):
|
||||
for y in range(height):
|
||||
game_map.tiles[(x, y)].type = TileType.SEA
|
||||
|
||||
# 最南部海洋 (y: 46-49)
|
||||
for x in range(width):
|
||||
for y in range(46, height):
|
||||
for y in _scaled_range_y(46, BASE_H, height):
|
||||
game_map.tiles[(x, y)].type = TileType.SEA
|
||||
|
||||
# 横向大河:从大漠东部(18, 25)流向东南入海,河流更宽
|
||||
river_tiles = _calculate_wide_river_tiles()
|
||||
# 横向大河:从大漠东部(18,25)比例位置流向东南入海,河流更宽
|
||||
river_tiles = _calculate_wide_river_tiles(game_map)
|
||||
for x, y in river_tiles:
|
||||
if game_map.is_in_bounds(x, y):
|
||||
game_map.tiles[(x, y)].type = TileType.WATER
|
||||
|
||||
# 北方纵向山脉 (x: 28-32, y: 5-20)
|
||||
for x in range(28, 33):
|
||||
for y in range(5, 21):
|
||||
for x in _scaled_range_x(28, 33, width):
|
||||
for y in _scaled_range_y(5, 21, height):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.MOUNTAIN
|
||||
|
||||
# 添加其他地形类型
|
||||
_add_other_terrains(game_map)
|
||||
|
||||
def _calculate_wide_river_tiles():
|
||||
"""计算宽阔大河的所有水域tiles:从(18, 25)流向东南到海洋,宽度为3-4格"""
|
||||
def _calculate_wide_river_tiles(game_map: Map):
|
||||
"""计算宽阔大河的所有水域tiles(按比例缩放)"""
|
||||
w, h = game_map.width, game_map.height
|
||||
river_tiles = []
|
||||
|
||||
# 计算河流中心线
|
||||
# 按比例的关键节点
|
||||
start_x = _scale_x(18, w)
|
||||
start_y = _scale_y(25, h)
|
||||
phase_split_x = _scale_x(40, w)
|
||||
end1_x = _scale_x(65, w)
|
||||
end1_y = _scale_y(46, h)
|
||||
end2_x = _scale_x(68, w)
|
||||
end2_y = _scale_y(48, h)
|
||||
|
||||
center_path = []
|
||||
x, y = 18, 25
|
||||
x, y = start_x, start_y
|
||||
|
||||
while x < 65 and y < 46:
|
||||
while x < end1_x and y < end1_y:
|
||||
center_path.append((x, y))
|
||||
# 向东南流淌
|
||||
if x < 40:
|
||||
if x < phase_split_x:
|
||||
x += 1
|
||||
if y < 35:
|
||||
if y < _scale_y(35, h):
|
||||
y += 1
|
||||
else:
|
||||
x += 2
|
||||
x += max(1, int(round(w / BASE_W * 2))) # 按比例放大步幅
|
||||
y += 1
|
||||
|
||||
# 连接到海洋
|
||||
while x < 68 and y < 48:
|
||||
while x < end2_x and y < end2_y:
|
||||
center_path.append((x, y))
|
||||
x += 1
|
||||
y += 1
|
||||
|
||||
# 根据中心线生成宽阔的河流
|
||||
for i, (cx, cy) in enumerate(center_path):
|
||||
# 河流宽度随位置变化:源头较窄,入海口较宽
|
||||
width = 1 if i < len(center_path) // 3 else 2 if i < 2 * len(center_path) // 3 else 3
|
||||
|
||||
# 为每个中心点添加周围的水域
|
||||
for dx in range(-width//2, width//2 + 1):
|
||||
for dy in range(-width//2, width//2 + 1):
|
||||
nx, ny = cx + dx, cy + dy
|
||||
river_tiles.append((nx, ny))
|
||||
width_sel = 1 if i < len(center_path) // 3 else 2 if i < 2 * len(center_path) // 3 else 3
|
||||
for dx in range(-width_sel // 2, width_sel // 2 + 1):
|
||||
for dy in range(-width_sel // 2, width_sel // 2 + 1):
|
||||
river_tiles.append((cx + dx, cy + dy))
|
||||
|
||||
return list(set(river_tiles)) # 去重
|
||||
return list(set(river_tiles))
|
||||
|
||||
def _create_2x2_cities(game_map: Map):
|
||||
"""创建2*2的城市区域"""
|
||||
cities = [
|
||||
{"name": "青云城", "base_x": 34, "base_y": 21, "description": "繁华都市的中心"},
|
||||
{"name": "沙月城", "base_x": 14, "base_y": 19, "description": "沙漠绿洲中的贸易重镇"},
|
||||
{"name": "翠林城", "base_x": 54, "base_y": 14, "description": "森林深处的修仙重镇"}
|
||||
{"name": "青云城", "base_x": _scale_x(34, game_map.width), "base_y": _scale_y(21, game_map.height), "description": "繁华都市的中心"},
|
||||
{"name": "沙月城", "base_x": _scale_x(14, game_map.width), "base_y": _scale_y(19, game_map.height), "description": "沙漠绿洲中的贸易重镇"},
|
||||
{"name": "翠林城", "base_x": _scale_x(54, game_map.width), "base_y": _scale_y(14, game_map.height), "description": "森林深处的修仙重镇"}
|
||||
]
|
||||
|
||||
for city in cities:
|
||||
@@ -176,11 +213,11 @@ def _create_2x2_wuxing_caves(game_map: Map):
|
||||
"""创建2*2的五行洞府区域"""
|
||||
# 五行洞府配置:金木水火土
|
||||
wuxing_caves = [
|
||||
{"name": "太白金府", "base_x": 26, "base_y": 12, "element": EssenceType.GOLD, "description": "青峰山脉深处的金行洞府"},
|
||||
{"name": "青木洞天", "base_x": 48, "base_y": 18, "element": EssenceType.WOOD, "description": "青云林海中的木行洞府"},
|
||||
{"name": "玄水秘境", "base_x": 67, "base_y": 25, "element": EssenceType.WATER, "description": "无边碧海深处的水行洞府"},
|
||||
{"name": "离火洞府", "base_x": 48, "base_y": 33, "element": EssenceType.FIRE, "description": "炎狱火山旁的火行洞府"},
|
||||
{"name": "厚土玄宫", "base_x": 30, "base_y": 16, "element": EssenceType.EARTH, "description": "青峰山脉的土行洞府"}
|
||||
{"name": "太白金府", "base_x": _scale_x(26, game_map.width), "base_y": _scale_y(12, game_map.height), "element": EssenceType.GOLD, "description": "青峰山脉深处的金行洞府"},
|
||||
{"name": "青木洞天", "base_x": _scale_x(48, game_map.width), "base_y": _scale_y(18, game_map.height), "element": EssenceType.WOOD, "description": "青云林海中的木行洞府"},
|
||||
{"name": "玄水秘境", "base_x": _scale_x(67, game_map.width), "base_y": _scale_y(25, game_map.height), "element": EssenceType.WATER, "description": "无边碧海深处的水行洞府"},
|
||||
{"name": "离火洞府", "base_x": _scale_x(48, game_map.width), "base_y": _scale_y(33, game_map.height), "element": EssenceType.FIRE, "description": "炎狱火山旁的火行洞府"},
|
||||
{"name": "厚土玄宫", "base_x": _scale_x(30, game_map.width), "base_y": _scale_y(16, game_map.height), "element": EssenceType.EARTH, "description": "青峰山脉的土行洞府"}
|
||||
]
|
||||
|
||||
for cave in wuxing_caves:
|
||||
@@ -195,8 +232,8 @@ def _create_2x2_wuxing_caves(game_map: Map):
|
||||
def _create_2x2_ruins(game_map: Map):
|
||||
"""创建2*2的遗迹区域"""
|
||||
ruins = [
|
||||
{"name": "古越遗迹", "base_x": 25, "base_y": 40, "description": "雨林深处的上古遗迹"},
|
||||
{"name": "沧海遗迹", "base_x": 66, "base_y": 47, "description": "沉没在海中的远古文明遗迹"}
|
||||
{"name": "古越遗迹", "base_x": _scale_x(25, game_map.width), "base_y": _scale_y(40, game_map.height), "description": "雨林深处的上古遗迹"},
|
||||
{"name": "沧海遗迹", "base_x": _scale_x(66, game_map.width), "base_y": _scale_y(47, game_map.height), "description": "沉没在海中的远古文明遗迹"}
|
||||
]
|
||||
|
||||
for ruin in ruins:
|
||||
@@ -208,29 +245,85 @@ def _create_2x2_ruins(game_map: Map):
|
||||
if game_map.is_in_bounds(x, y):
|
||||
game_map.tiles[(x, y)].type = TileType.RUINS
|
||||
|
||||
def _scale_loaded_regions(game_map: Map) -> None:
|
||||
"""按比例缩放从 CSV 加载到 Map 的区域坐标。
|
||||
- 小型 2x2(或 1x2/2x1)保持尺寸不变,仅移动锚点
|
||||
- 其他矩形/正方形区域按比例缩放两角
|
||||
- 蜿蜒区域按比例缩放其包围框
|
||||
"""
|
||||
new_regions: dict[int, object] = {}
|
||||
new_region_names: dict[str, object] = {}
|
||||
for region in list(game_map.regions.values()):
|
||||
try:
|
||||
nw_x, nw_y = map(int, str(region.north_west_cor).split(","))
|
||||
se_x, se_y = map(int, str(region.south_east_cor).split(","))
|
||||
except Exception:
|
||||
# 坐标异常的保持原样
|
||||
new_regions[region.id] = region
|
||||
new_region_names[region.name] = region
|
||||
continue
|
||||
width = game_map.width
|
||||
height = game_map.height
|
||||
cls = region.__class__
|
||||
shape = region.shape
|
||||
# 计算尺寸(包含端点,故差值为尺寸-1)
|
||||
span_w = max(0, se_x - nw_x)
|
||||
span_h = max(0, se_y - nw_y)
|
||||
if shape.name in ("RECTANGLE", "SQUARE") and span_w <= 1 and span_h <= 1:
|
||||
# 小区域保持尺寸:仅缩放左上角
|
||||
new_nw_x = max(0, min(width - 1, _scale_x(nw_x, width)))
|
||||
new_nw_y = max(0, min(height - 1, _scale_y(nw_y, height)))
|
||||
new_se_x = max(new_nw_x, min(width - 1, new_nw_x + span_w))
|
||||
new_se_y = max(new_nw_y, min(height - 1, new_nw_y + span_h))
|
||||
else:
|
||||
# 一般区域按比例缩放两角
|
||||
new_nw_x = max(0, min(width - 1, _scale_x(nw_x, width)))
|
||||
new_nw_y = max(0, min(height - 1, _scale_y(nw_y, height)))
|
||||
new_se_x = max(new_nw_x, min(width - 1, _scale_x(se_x, width)))
|
||||
new_se_y = max(new_nw_y, min(height - 1, _scale_y(se_y, height)))
|
||||
params = {
|
||||
"id": region.id,
|
||||
"name": region.name,
|
||||
"desc": region.desc,
|
||||
"shape": shape,
|
||||
"north_west_cor": f"{new_nw_x},{new_nw_y}",
|
||||
"south_east_cor": f"{new_se_x},{new_se_y}",
|
||||
}
|
||||
# 附带子类特有字段
|
||||
if hasattr(region, "essence_type"):
|
||||
params["essence_type"] = getattr(region, "essence_type")
|
||||
if hasattr(region, "essence_density"):
|
||||
params["essence_density"] = getattr(region, "essence_density")
|
||||
new_region = cls(**params) # 重新构建以刷新 cors/area/center
|
||||
new_regions[new_region.id] = new_region
|
||||
new_region_names[new_region.name] = new_region
|
||||
game_map.regions = new_regions
|
||||
game_map.region_names = new_region_names
|
||||
|
||||
def _add_other_terrains(game_map: Map):
|
||||
"""添加其他地形类型到合适位置"""
|
||||
"""添加其他地形类型到合适位置(按比例缩放区域范围)"""
|
||||
w, h = game_map.width, game_map.height
|
||||
# 草原 (中部区域)
|
||||
for x in range(20, 40):
|
||||
for y in range(12, 25):
|
||||
for x in _scaled_range_x(20, 40, w):
|
||||
for y in _scaled_range_y(12, 25, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.GRASSLAND
|
||||
|
||||
# 森林 (东中部区域)
|
||||
for x in range(40, 60):
|
||||
for y in range(10, 30):
|
||||
for x in _scaled_range_x(40, 60, w):
|
||||
for y in _scaled_range_y(10, 30, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.FOREST
|
||||
|
||||
# 雪山 (北部山脉附近)
|
||||
for x in range(25, 35):
|
||||
for y in range(2, 8):
|
||||
for x in _scaled_range_x(25, 35, w):
|
||||
for y in _scaled_range_y(2, 8, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.GLACIER:
|
||||
game_map.tiles[(x, y)].type = TileType.SNOW_MOUNTAIN
|
||||
|
||||
# 火山 (单独区域)
|
||||
for x in range(52, 55):
|
||||
for y in range(32, 35):
|
||||
for x in _scaled_range_x(52, 55, w):
|
||||
for y in _scaled_range_y(32, 35, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.VOLCANO
|
||||
|
||||
@@ -244,14 +337,14 @@ def _add_other_terrains(game_map: Map):
|
||||
_create_2x2_ruins(game_map)
|
||||
|
||||
# 农田 (城市附近,改为不与草原重叠的区域)
|
||||
for x in range(33, 38):
|
||||
for y in range(25, 30):
|
||||
for x in _scaled_range_x(33, 38, w):
|
||||
for y in _scaled_range_y(25, 30, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.FARM
|
||||
|
||||
# 沼泽 (河流附近的低洼地区,避开雨林区域)
|
||||
for x in range(42, 46):
|
||||
for y in range(30, 34):
|
||||
for x in _scaled_range_x(42, 46, w):
|
||||
for y in _scaled_range_y(30, 34, h):
|
||||
if game_map.tiles[(x, y)].type == TileType.PLAIN:
|
||||
game_map.tiles[(x, y)].type = TileType.SWAMP
|
||||
|
||||
|
||||
@@ -147,11 +147,11 @@ async def main():
|
||||
|
||||
front = Front(
|
||||
simulator=sim,
|
||||
tile_size=19, # 减小20%的tile大小 (24 * 0.8 ≈ 19)
|
||||
tile_size=24, # 每个tile扩大约25%像素(与tile数量缩减相抵,窗口不变)
|
||||
margin=8,
|
||||
step_interval_ms=750,
|
||||
window_title="Cultivation World — Front Demo",
|
||||
sidebar_width=350, # 新增:设置侧边栏宽度
|
||||
sidebar_width=350,
|
||||
)
|
||||
await front.run_async()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user