map.py 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. # coding: utf-8
  2. import typing
  3. import tmx
  4. from synergine2_xyz.exceptions import ImproperlyConfiguredMap
  5. class XYZTile(object):
  6. def __init__(self, tile: tmx.Tile) -> None:
  7. self.tile = tile
  8. def property(self, name: str) -> typing.Union[str, int, float]:
  9. for property in self.tile.properties:
  10. if property.name == name:
  11. return property.value
  12. raise ImproperlyConfiguredMap('Tile with id "{}" don\'t contains "{}" property'.format(
  13. self.tile.id,
  14. name,
  15. ))
  16. class UnconstructedTile(XYZTile):
  17. pass
  18. class TMXMap(object):
  19. xyz_tile_class = XYZTile
  20. def __init__(self, map_file_path: str) -> None:
  21. self.tmx_map = tmx.TileMap.load(map_file_path)
  22. self.tmx_layers = {} # type: typing.Dict[str, tmx.Layer]
  23. self.tmx_layer_tiles = {} # type: typing.Dict[str, typing.Dict[str, XYZTile]]
  24. self.tmx_tilesets = {} # type: typing.Dict[str, tmx.Tileset]
  25. self.tmx_tiles = {} # type: typing.Dict[int, XYZTile]
  26. self._load()
  27. @property
  28. def height(self) -> int:
  29. return self.tmx_map.height
  30. @property
  31. def width(self) -> int:
  32. return self.tmx_map.width
  33. def get_default_tileset(self) -> tmx.Tileset:
  34. return list(self.tmx_tilesets.values())[0]
  35. def get_default_tile(self) -> XYZTile:
  36. tileset = self.get_default_tileset()
  37. return self.xyz_tile_class(tileset.tiles[0])
  38. def _load(self) -> None:
  39. self._load_layers()
  40. self._load_tilesets()
  41. self._load_tiles()
  42. def _load_layers(self) -> None:
  43. for layer in self.tmx_map.layers:
  44. self.tmx_layers[layer.name] = layer
  45. def _load_tilesets(self) -> None:
  46. for tileset in self.tmx_map.tilesets:
  47. self.tmx_tilesets[tileset.name] = tileset
  48. for tile in tileset.tiles:
  49. self.tmx_tiles[tileset.firstgid + tile.id] = self.xyz_tile_class(tile)
  50. def _load_tiles(self) -> None:
  51. for layer_name, layer in self.tmx_layers.items():
  52. x, y = -1, 0
  53. self.tmx_layer_tiles[layer_name] = {}
  54. # no tiles
  55. if not isinstance(layer, tmx.Layer):
  56. continue
  57. for layer_tile in layer.tiles:
  58. x += 1
  59. if x == self.width:
  60. x = 0
  61. y += 1
  62. position_key = '{}.{}'.format(x, y)
  63. if not layer_tile.gid:
  64. tile = self.get_default_tile()
  65. elif not layer_tile.gid in self.tmx_tiles:
  66. # tile = UnconstructedTile()
  67. tile = self.get_default_tile()
  68. else:
  69. tile = self.tmx_tiles[layer_tile.gid]
  70. self.tmx_layer_tiles[layer_name][position_key] = tile
  71. def layer(self, name: str) -> tmx.Layer:
  72. return self.tmx_layers[name]
  73. def tileset(self, name: str) -> tmx.Tileset:
  74. return self.tmx_tilesets[name]
  75. def tile(self, gid: int) -> XYZTile:
  76. return self.tmx_tiles[gid]
  77. def layer_tiles(self, name: str) -> typing.Dict[str, XYZTile]:
  78. return self.tmx_layer_tiles[name]