tilemap-parser 3.1.16__tar.gz → 3.1.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/PKG-INFO +1 -1
  2. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/pyproject.toml +1 -1
  3. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/map_loader.py +31 -1
  4. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser.egg-info/PKG-INFO +1 -1
  5. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser.egg-info/SOURCES.txt +1 -0
  6. tilemap_parser-3.1.17/tests/test_object_surfaces.py +200 -0
  7. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/LICENSE +0 -0
  8. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/README.md +0 -0
  9. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/setup.cfg +0 -0
  10. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/__init__.py +0 -0
  11. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/__init__.py +0 -0
  12. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/animation.py +0 -0
  13. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/collision.py +0 -0
  14. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/collision_loader.py +0 -0
  15. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/map_parse.py +0 -0
  16. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/node_parse.py +0 -0
  17. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/parser/particle.py +0 -0
  18. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/__init__.py +0 -0
  19. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/animation_player.py +0 -0
  20. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/area_node.py +0 -0
  21. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/collision_cache.py +0 -0
  22. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/object_collision.py +0 -0
  23. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/particles.py +0 -0
  24. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/renderer.py +0 -0
  25. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/runtime/tile_collision.py +0 -0
  26. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/utils/__init__.py +0 -0
  27. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser/utils/geometry.py +0 -0
  28. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser.egg-info/dependency_links.txt +0 -0
  29. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser.egg-info/requires.txt +0 -0
  30. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/src/tilemap_parser.egg-info/top_level.txt +0 -0
  31. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_collision.py +0 -0
  32. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_geometry.py +0 -0
  33. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_map_loader.py +0 -0
  34. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_object_collision.py +0 -0
  35. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_render_scale.py +0 -0
  36. {tilemap_parser-3.1.16 → tilemap_parser-3.1.17}/tests/test_tile_collision.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-parser
3
- Version: 3.1.16
3
+ Version: 3.1.17
4
4
  Summary: Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime.
5
5
  Author: tilemap parser contributors
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tilemap-parser"
7
- version = "3.1.16"
7
+ version = "3.1.17"
8
8
  description = "Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -8,7 +8,7 @@ from typing import Dict, List, Optional, Tuple, Union
8
8
  import pygame
9
9
  from pygame import Rect, Surface
10
10
 
11
- from ..parser.map_parse import MapParseError, ParsedLayer, ParsedMap, ParsedTile, parse_map_file
11
+ from ..parser.map_parse import MapParseError, ParsedLayer, ParsedMap, ParsedObject, ParsedTile, parse_map_file
12
12
  from ..parser.node_parse import parse_nodes_dict
13
13
  from .area_node import AreaNode
14
14
  from .particles import ParticleEmitterNode
@@ -234,6 +234,36 @@ class TilemapData:
234
234
  return None
235
235
  return self.get_tile_surface(tile.ttype, tile.variant)
236
236
 
237
+ def get_object_surface(self, obj: ParsedObject, *, copy_surface: bool = True) -> Optional[Surface]:
238
+ return self.get_image(variant=obj.variant, ttype=obj.ttype, copy_surface=copy_surface)
239
+
240
+ def get_object_surface_by_id(
241
+ self, layer_id_or_name: Union[int, str], object_id: int, *, copy_surface: bool = True
242
+ ) -> Optional[Tuple[Surface, int, int]]:
243
+ layer = self.get_layer(layer_id_or_name)
244
+ if layer is None or layer.layer_type != "object":
245
+ return None
246
+ obj = layer.objects.get(object_id)
247
+ if obj is None:
248
+ return None
249
+ surf = self.get_object_surface(obj, copy_surface=copy_surface)
250
+ if surf is None:
251
+ return None
252
+ return surf, obj.area.x, obj.area.y
253
+
254
+ def get_object_surfaces(
255
+ self, layer_id_or_name: Union[int, str], *, copy_surface: bool = True
256
+ ) -> List[Tuple[Surface, int, int, int]]:
257
+ layer = self.get_layer(layer_id_or_name)
258
+ if layer is None or layer.layer_type != "object":
259
+ return []
260
+ result: List[Tuple[Surface, int, int, int]] = []
261
+ for oid, obj in layer.objects.items():
262
+ surf = self.get_object_surface(obj, copy_surface=copy_surface)
263
+ if surf is not None:
264
+ result.append((surf, obj.area.x, obj.area.y, oid))
265
+ return result
266
+
237
267
  def get_tileset_animation(self, ttype: int) -> Optional[dict]:
238
268
  if 0 <= ttype < len(self.parsed.tilesets):
239
269
  anim = self.parsed.tilesets[ttype].animation
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-parser
3
- Version: 3.1.16
3
+ Version: 3.1.17
4
4
  Summary: Standalone parser/loader for tilemap-editor JSON maps, sprite animations, and collision detection runtime.
5
5
  Author: tilemap parser contributors
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -29,5 +29,6 @@ tests/test_collision.py
29
29
  tests/test_geometry.py
30
30
  tests/test_map_loader.py
31
31
  tests/test_object_collision.py
32
+ tests/test_object_surfaces.py
32
33
  tests/test_render_scale.py
33
34
  tests/test_tile_collision.py
@@ -0,0 +1,200 @@
1
+ import json
2
+ import tempfile
3
+ from pathlib import Path
4
+
5
+ import pygame
6
+ import pytest
7
+
8
+ import sys
9
+ sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
10
+
11
+ from tilemap_parser.runtime.map_loader import TilemapData
12
+ from tilemap_parser.parser.map_parse import ParsedObject, ParsedObjectArea
13
+
14
+
15
+ MINIMAL_MAP_META = {
16
+ "tile_size": "16;16",
17
+ "map_size": "10;10",
18
+ "version": "1.1",
19
+ }
20
+
21
+
22
+ def _make_minimal_png(path: Path, size: tuple[int, int] = (32, 16)) -> None:
23
+ surf = pygame.Surface(size)
24
+ surf.fill((255, 0, 255))
25
+ pygame.image.save(surf, str(path))
26
+
27
+
28
+ def _make_map_json_with_objects(tileset_path: str, data_dir: Path) -> Path:
29
+ payload = {
30
+ "meta": {**MINIMAL_MAP_META},
31
+ "resources": {"tilesets": [{"path": tileset_path, "type": "tile"}]},
32
+ "project_state": {"rules": [], "groups": []},
33
+ "data": {
34
+ "ongrid": {},
35
+ "layers": [
36
+ {
37
+ "name": "Object Layer 1",
38
+ "type": "object",
39
+ "visible": True,
40
+ "locked": False,
41
+ "opacity": 1.0,
42
+ "z_index": 1,
43
+ "properties": {},
44
+ "tiles": {},
45
+ "objects": {
46
+ "1": {
47
+ "area": {"x": 10, "y": 20, "w": 16, "h": 16},
48
+ "ttype": 0,
49
+ "tileset_type": "object",
50
+ "variant": 0,
51
+ "properties": {},
52
+ },
53
+ "2": {
54
+ "area": {"x": 50, "y": 60, "w": 32, "h": 32},
55
+ "ttype": 0,
56
+ "tileset_type": "object",
57
+ "variant": 1,
58
+ "properties": {"name": "foo"},
59
+ },
60
+ },
61
+ "next_object_id": 3,
62
+ },
63
+ {
64
+ "name": "Tile Layer",
65
+ "type": "tile",
66
+ "visible": True,
67
+ "locked": False,
68
+ "opacity": 1.0,
69
+ "z_index": 0,
70
+ "properties": {},
71
+ "tiles": {},
72
+ "objects": {},
73
+ },
74
+ ],
75
+ },
76
+ }
77
+ map_path = data_dir / "test_map_objects.json"
78
+ with open(map_path, "w") as f:
79
+ json.dump(payload, f, indent=2)
80
+ return map_path
81
+
82
+
83
+ @pytest.fixture(autouse=True)
84
+ def pygame_init():
85
+ pygame.display.init()
86
+ pygame.display.set_mode((1, 1))
87
+ yield
88
+ pygame.quit()
89
+
90
+
91
+ @pytest.fixture
92
+ def map_data():
93
+ with tempfile.TemporaryDirectory() as tmp:
94
+ tmp = Path(tmp)
95
+ data_dir = tmp / "data"
96
+ assets_dir = tmp / "assets"
97
+ data_dir.mkdir()
98
+ assets_dir.mkdir()
99
+ png = assets_dir / "tileset.png"
100
+ _make_minimal_png(png)
101
+ map_path = _make_map_json_with_objects("../assets/tileset.png", data_dir)
102
+ td = TilemapData.load(map_path)
103
+ yield td, data_dir, assets_dir, png
104
+
105
+
106
+ class TestObjectSurfaces:
107
+ def test_get_object_surface_returns_surface(self, map_data):
108
+ td, *_ = map_data
109
+ obj = ParsedObject(
110
+ area=ParsedObjectArea(x=10, y=20, w=16, h=16),
111
+ ttype=0,
112
+ tileset_type="object",
113
+ variant=0,
114
+ )
115
+ surf = td.get_object_surface(obj)
116
+ assert surf is not None
117
+ assert isinstance(surf, pygame.Surface)
118
+ assert surf.get_size() == (16, 16)
119
+
120
+ def test_get_object_surface_from_parsed_object(self, map_data):
121
+ td, *_ = map_data
122
+ layer = td.get_layer("Object Layer 1")
123
+ assert layer is not None
124
+ obj = layer.objects.get(1)
125
+ assert obj is not None
126
+ surf = td.get_object_surface(obj)
127
+ assert surf is not None
128
+ assert isinstance(surf, pygame.Surface)
129
+
130
+ def test_get_object_surface_by_id_returns_surface_xy(self, map_data):
131
+ td, *_ = map_data
132
+ result = td.get_object_surface_by_id("Object Layer 1", 1)
133
+ assert result is not None
134
+ surf, x, y = result
135
+ assert isinstance(surf, pygame.Surface)
136
+ assert x == 10
137
+ assert y == 20
138
+
139
+ def test_get_object_surface_by_id_second_object(self, map_data):
140
+ td, *_ = map_data
141
+ result = td.get_object_surface_by_id("Object Layer 1", 2)
142
+ assert result is not None
143
+ surf, x, y = result
144
+ assert isinstance(surf, pygame.Surface)
145
+ assert surf.get_size() == (16, 16)
146
+ assert x == 50
147
+ assert y == 60
148
+
149
+ def test_get_object_surface_by_id_bad_layer_returns_none(self, map_data):
150
+ td, *_ = map_data
151
+ result = td.get_object_surface_by_id("Tile Layer", 1)
152
+ assert result is None
153
+
154
+ def test_get_object_surface_by_id_bad_layer_name(self, map_data):
155
+ td, *_ = map_data
156
+ result = td.get_object_surface_by_id("Nonexistent", 1)
157
+ assert result is None
158
+
159
+ def test_get_object_surface_by_id_bad_object_id(self, map_data):
160
+ td, *_ = map_data
161
+ result = td.get_object_surface_by_id("Object Layer 1", 999)
162
+ assert result is None
163
+
164
+ def test_get_object_surfaces_returns_all(self, map_data):
165
+ td, *_ = map_data
166
+ results = td.get_object_surfaces("Object Layer 1")
167
+ assert len(results) == 2
168
+
169
+ surf1, x1, y1, oid1 = results[0]
170
+ assert isinstance(surf1, pygame.Surface)
171
+ assert x1 == 10
172
+ assert y1 == 20
173
+ assert oid1 == 1
174
+
175
+ surf2, x2, y2, oid2 = results[1]
176
+ assert isinstance(surf2, pygame.Surface)
177
+ assert x2 == 50
178
+ assert y2 == 60
179
+ assert oid2 == 2
180
+
181
+ def test_get_object_surfaces_bad_layer(self, map_data):
182
+ td, *_ = map_data
183
+ results = td.get_object_surfaces("Tile Layer")
184
+ assert results == []
185
+
186
+ def test_get_object_surfaces_nonexistent_layer(self, map_data):
187
+ td, *_ = map_data
188
+ results = td.get_object_surfaces("Nonexistent")
189
+ assert results == []
190
+
191
+ def test_get_object_surface_with_out_of_range_ttype_returns_none(self, map_data):
192
+ td, *_ = map_data
193
+ obj = ParsedObject(
194
+ area=ParsedObjectArea(x=0, y=0, w=16, h=16),
195
+ ttype=999,
196
+ tileset_type="object",
197
+ variant=0,
198
+ )
199
+ surf = td.get_object_surface(obj)
200
+ assert surf is None
File without changes