96 lines
2.9 KiB
Python
96 lines
2.9 KiB
Python
from enum import Enum
|
||
from dataclasses import dataclass
|
||
from typing import TYPE_CHECKING
|
||
|
||
if TYPE_CHECKING:
|
||
from src.classes.region import Region
|
||
|
||
class TileType(Enum):
|
||
PLAIN = "plain" # 平原
|
||
WATER = "water" # 水域
|
||
SEA = "sea" # 海洋
|
||
MOUNTAIN = "mountain" # 山脉
|
||
FOREST = "forest" # 森林
|
||
CITY = "city" # 城市
|
||
DESERT = "desert" # 沙漠
|
||
RAINFOREST = "rainforest" # 热带雨林
|
||
GLACIER = "glacier" # 冰川/冰原
|
||
SNOW_MOUNTAIN = "snow_mountain" # 雪山
|
||
VOLCANO = "volcano" # 火山
|
||
GRASSLAND = "grassland" # 草原
|
||
SWAMP = "swamp" # 沼泽
|
||
CAVE = "cave" # 洞穴
|
||
RUINS = "ruins" # 遗迹
|
||
FARM = "farm" # 农田
|
||
|
||
|
||
@dataclass
|
||
class Tile():
|
||
# 实际的地块
|
||
type: TileType
|
||
x: int
|
||
y: int
|
||
region: 'Region' = None # 可以是一个region的一部分,也可以不属于任何region
|
||
|
||
class Map():
|
||
"""
|
||
通过dict记录position 到 tile。
|
||
"""
|
||
def __init__(self, width: int, height: int):
|
||
self.tiles = {}
|
||
self.width = width
|
||
self.height = height
|
||
|
||
# 加载所有region数据到Map中
|
||
self._load_regions()
|
||
|
||
def _load_regions(self):
|
||
"""从配置文件加载所有区域数据到Map实例中"""
|
||
# 延迟导入避免循环导入
|
||
from src.classes.region import load_all_regions
|
||
|
||
self.regions, self.region_names = load_all_regions()
|
||
|
||
def is_in_bounds(self, x: int, y: int) -> bool:
|
||
"""
|
||
判断坐标是否在地图边界内。
|
||
"""
|
||
return 0 <= x < self.width and 0 <= y < self.height
|
||
|
||
def create_tile(self, x: int, y: int, tile_type: TileType):
|
||
self.tiles[(x, y)] = Tile(tile_type, x, y, region=None)
|
||
|
||
def get_tile(self, x: int, y: int) -> Tile:
|
||
return self.tiles[(x, y)]
|
||
|
||
def get_center_locs(self, locs: list[tuple[int, int]]) -> tuple[int, int]:
|
||
"""
|
||
获取locs的中心位置。
|
||
如果几何中心恰好在位置列表中,返回几何中心;
|
||
否则返回距离几何中心最近的实际位置。
|
||
"""
|
||
if not locs:
|
||
return (0, 0)
|
||
|
||
# 分别计算x和y坐标的平均值
|
||
avg_x = sum(loc[0] for loc in locs) // len(locs)
|
||
avg_y = sum(loc[1] for loc in locs) // len(locs)
|
||
center = (avg_x, avg_y)
|
||
|
||
# 如果几何中心恰好在位置列表中,直接返回
|
||
if center in locs:
|
||
return center
|
||
|
||
# 否则找到距离几何中心最近的实际位置
|
||
def distance_squared(loc: tuple[int, int]) -> int:
|
||
"""计算到中心点的距离平方(避免开方运算)"""
|
||
return (loc[0] - avg_x) ** 2 + (loc[1] - avg_y) ** 2
|
||
|
||
return min(locs, key=distance_squared)
|
||
|
||
def get_region(self, x: int, y: int) -> 'Region | None':
|
||
"""
|
||
获取一个region。
|
||
"""
|
||
return self.tiles[(x, y)].region
|