tilemap-parser 4.2.5__tar.gz → 4.2.7__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.
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/PKG-INFO +1 -1
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/pyproject.toml +1 -1
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/map_object.py +32 -23
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/renderer.py +2 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/PKG-INFO +1 -1
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_map_object.py +90 -35
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/LICENSE +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/README.md +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/setup.cfg +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/__init__.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/__init__.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/animation.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/collision_loader.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/map_parse.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/node_parse.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/particle.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/parser/tmx_converter.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/__init__.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/animation_player.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/area_node.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/camera.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/collision_cache.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/map_loader.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/object_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/particles.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/protocols.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/tile_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/utils/__init__.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/utils/geometry.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/SOURCES.txt +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/dependency_links.txt +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/requires.txt +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/top_level.txt +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_camera.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_geometry.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_gid_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_integration_animation.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_integration_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_integration_map_loader.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_map_loader.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_move_grounded.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_object_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_object_surfaces.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_particle_emitter.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_render_scale.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_tile_collision.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_tile_layer_renderer_y_sort.py +0 -0
- {tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/tests/test_tmx_converter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-parser
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.7
|
|
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 = "4.2.
|
|
7
|
+
version = "4.2.7"
|
|
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"
|
|
@@ -16,7 +16,7 @@ Usage::
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import Dict, List, Optional, Union
|
|
19
|
+
from typing import Dict, List, Optional, Union, final
|
|
20
20
|
|
|
21
21
|
import pygame
|
|
22
22
|
from pygame import Surface
|
|
@@ -27,6 +27,7 @@ from .collision_cache import CollisionCache
|
|
|
27
27
|
from .map_loader import TilemapData
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
@final
|
|
30
31
|
class MapObject:
|
|
31
32
|
"""
|
|
32
33
|
A game object loaded from a tilemap, carrying a surface for
|
|
@@ -48,28 +49,34 @@ class MapObject:
|
|
|
48
49
|
shape pairs when either object has multiple shapes.
|
|
49
50
|
"""
|
|
50
51
|
|
|
51
|
-
__slots__ = (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
__slots__ = tuple(
|
|
53
|
+
sorted(
|
|
54
|
+
(
|
|
55
|
+
"x",
|
|
56
|
+
"y",
|
|
57
|
+
"surface",
|
|
58
|
+
"collision_shape",
|
|
59
|
+
"collision_shapes",
|
|
60
|
+
"collision_layer",
|
|
61
|
+
"collision_mask",
|
|
62
|
+
"y_sort_origin",
|
|
63
|
+
"ttype",
|
|
64
|
+
)
|
|
65
|
+
)
|
|
60
66
|
)
|
|
61
67
|
|
|
62
68
|
def __init__(
|
|
63
69
|
self,
|
|
64
70
|
x: float,
|
|
65
71
|
y: float,
|
|
66
|
-
surface:
|
|
67
|
-
collision_shape:
|
|
72
|
+
surface: Surface | None = None,
|
|
73
|
+
collision_shape: CollisionPolygon | None = None,
|
|
68
74
|
*,
|
|
69
|
-
collision_shapes:
|
|
75
|
+
collision_shapes: list[CollisionPolygon] | None = None,
|
|
70
76
|
collision_layer: int = 1,
|
|
71
77
|
collision_mask: int = 0xFFFFFFFF,
|
|
72
|
-
y_sort_origin:
|
|
78
|
+
y_sort_origin: int | None = None,
|
|
79
|
+
ttype: int = -1,
|
|
73
80
|
) -> None:
|
|
74
81
|
self.x = x
|
|
75
82
|
self.y = y
|
|
@@ -86,13 +93,14 @@ class MapObject:
|
|
|
86
93
|
self.collision_layer = collision_layer
|
|
87
94
|
self.collision_mask = collision_mask
|
|
88
95
|
self.y_sort_origin = y_sort_origin
|
|
96
|
+
self.ttype = ttype
|
|
89
97
|
|
|
90
98
|
@property
|
|
91
99
|
def has_collision(self) -> bool:
|
|
92
100
|
return len(self.collision_shapes) > 0
|
|
93
101
|
|
|
94
102
|
|
|
95
|
-
def _resolve_object_collision_filename(tileset_path:
|
|
103
|
+
def _resolve_object_collision_filename(tileset_path: str | Path) -> str:
|
|
96
104
|
"""Extract the object collision filename for a given tileset path.
|
|
97
105
|
|
|
98
106
|
Example: ``"building7.png"`` → ``"building7.object_collision.json"``
|
|
@@ -102,11 +110,11 @@ def _resolve_object_collision_filename(tileset_path: Union[str, Path]) -> str:
|
|
|
102
110
|
|
|
103
111
|
def load_map_objects(
|
|
104
112
|
tilemap_data: TilemapData,
|
|
105
|
-
collision_dir:
|
|
113
|
+
collision_dir: str | Path,
|
|
106
114
|
*,
|
|
107
|
-
cache:
|
|
115
|
+
cache: CollisionCache | None = None,
|
|
108
116
|
require_collision: bool = True,
|
|
109
|
-
) ->
|
|
117
|
+
) -> list[MapObject]:
|
|
110
118
|
"""Load objects from a tilemap.
|
|
111
119
|
|
|
112
120
|
Iterates every object layer in *tilemap_data*, resolves the
|
|
@@ -149,10 +157,10 @@ def load_map_objects(
|
|
|
149
157
|
List of :class:`MapObject` instances.
|
|
150
158
|
"""
|
|
151
159
|
collision_dir = Path(collision_dir)
|
|
152
|
-
objects:
|
|
160
|
+
objects: list[MapObject] = []
|
|
153
161
|
object_layers = tilemap_data.get_layers(layer_type="object")
|
|
154
162
|
|
|
155
|
-
loaded_collision:
|
|
163
|
+
loaded_collision: dict[int, ObjectCollisionData | None] = {}
|
|
156
164
|
|
|
157
165
|
for layer in object_layers:
|
|
158
166
|
for obj_id, obj in layer.objects.items():
|
|
@@ -171,9 +179,7 @@ def load_map_objects(
|
|
|
171
179
|
|
|
172
180
|
ttype = obj.ttype
|
|
173
181
|
if ttype not in loaded_collision:
|
|
174
|
-
collision_data = _load_collision_for_tileset(
|
|
175
|
-
tilemap_data, ttype, collision_dir, cache
|
|
176
|
-
)
|
|
182
|
+
collision_data = _load_collision_for_tileset(tilemap_data, ttype, collision_dir, cache)
|
|
177
183
|
loaded_collision[ttype] = collision_data
|
|
178
184
|
|
|
179
185
|
collision_data = loaded_collision[ttype]
|
|
@@ -186,6 +192,7 @@ def load_map_objects(
|
|
|
186
192
|
surface=surf,
|
|
187
193
|
collision_shape=None,
|
|
188
194
|
collision_shapes=[],
|
|
195
|
+
ttype=obj.ttype,
|
|
189
196
|
)
|
|
190
197
|
objects.append(game_obj)
|
|
191
198
|
continue
|
|
@@ -209,6 +216,7 @@ def load_map_objects(
|
|
|
209
216
|
surface=surf,
|
|
210
217
|
collision_shape=None,
|
|
211
218
|
collision_shapes=[],
|
|
219
|
+
ttype=obj.ttype,
|
|
212
220
|
)
|
|
213
221
|
objects.append(game_obj)
|
|
214
222
|
continue
|
|
@@ -221,6 +229,7 @@ def load_map_objects(
|
|
|
221
229
|
collision_shapes=world_shapes,
|
|
222
230
|
collision_layer=region_layer,
|
|
223
231
|
collision_mask=region_mask,
|
|
232
|
+
ttype=obj.ttype,
|
|
224
233
|
)
|
|
225
234
|
objects.append(game_obj)
|
|
226
235
|
|
|
@@ -178,6 +178,8 @@ class TileLayerRenderer:
|
|
|
178
178
|
tile_iter = sorted(chunk, key=lambda p: p[1] * self._eff_h + origin)
|
|
179
179
|
|
|
180
180
|
for x, y in tile_iter:
|
|
181
|
+
if not (min_x <= x <= max_x and min_y <= y <= max_y):
|
|
182
|
+
continue
|
|
181
183
|
tile = layer.tiles[(x, y)]
|
|
182
184
|
display_variant = self._compute_display_variant(tile.variant, tile.ttype, x, y, time_ms)
|
|
183
185
|
cell = self._get_cached_variant(tile.ttype, display_variant)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-parser
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.7
|
|
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
|
|
@@ -8,14 +8,13 @@ Covers:
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
+
import sys
|
|
11
12
|
import tempfile
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
|
|
14
15
|
import pygame
|
|
15
16
|
import pytest
|
|
16
17
|
|
|
17
|
-
import sys
|
|
18
|
-
|
|
19
18
|
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
|
20
19
|
|
|
21
20
|
from tilemap_parser.parser.collision import CollisionPolygon
|
|
@@ -250,14 +249,14 @@ def map_multiple_objects():
|
|
|
250
249
|
"ttype": 0,
|
|
251
250
|
"tileset_type": "object",
|
|
252
251
|
"variant": 0,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
252
|
+
"properties": {},
|
|
253
|
+
},
|
|
254
|
+
"2": {
|
|
255
|
+
"area": {"x": 300, "y": 400, "w": 16, "h": 16},
|
|
256
|
+
"ttype": 0,
|
|
257
|
+
"tileset_type": "object",
|
|
258
|
+
"variant": 1,
|
|
259
|
+
"properties": {},
|
|
261
260
|
},
|
|
262
261
|
},
|
|
263
262
|
"next_object_id": 3,
|
|
@@ -415,6 +414,7 @@ class TestLoadMapObjects:
|
|
|
415
414
|
nonlocal call_count
|
|
416
415
|
call_count += 1
|
|
417
416
|
from tilemap_parser.parser.collision_loader import load_object_collision
|
|
417
|
+
|
|
418
418
|
return load_object_collision(path)
|
|
419
419
|
|
|
420
420
|
monkeypatch.setattr(
|
|
@@ -438,6 +438,7 @@ class TestLoadMapObjects:
|
|
|
438
438
|
nonlocal call_count
|
|
439
439
|
call_count += 1
|
|
440
440
|
from tilemap_parser.parser.collision_loader import load_object_collision
|
|
441
|
+
|
|
441
442
|
return load_object_collision(path)
|
|
442
443
|
|
|
443
444
|
# CollisionCache.get_object_collision calls its own module-level
|
|
@@ -506,21 +507,27 @@ class TestLoadMapObjects:
|
|
|
506
507
|
"region_id": "region_top",
|
|
507
508
|
"region_rect": [0, 0, 32, 16],
|
|
508
509
|
"name": "Top",
|
|
509
|
-
"shapes": [
|
|
510
|
+
"shapes": [
|
|
511
|
+
{"type": "polygon", "vertices": [[0, 0], [32, 0], [32, 16], [0, 16]], "one_way": False}
|
|
512
|
+
],
|
|
510
513
|
"properties": {},
|
|
511
514
|
},
|
|
512
515
|
"region_bot": {
|
|
513
516
|
"region_id": "region_bot",
|
|
514
517
|
"region_rect": [0, 16, 32, 16],
|
|
515
518
|
"name": "Bottom",
|
|
516
|
-
"shapes": [
|
|
519
|
+
"shapes": [
|
|
520
|
+
{"type": "polygon", "vertices": [[0, 0], [32, 0], [32, 16], [0, 16]], "one_way": False}
|
|
521
|
+
],
|
|
517
522
|
"properties": {},
|
|
518
523
|
},
|
|
519
524
|
"region_extra": {
|
|
520
525
|
"region_id": "region_extra",
|
|
521
526
|
"region_rect": [0, 0, 16, 32],
|
|
522
527
|
"name": "Extra",
|
|
523
|
-
"shapes": [
|
|
528
|
+
"shapes": [
|
|
529
|
+
{"type": "polygon", "vertices": [[0, 0], [16, 0], [16, 32], [0, 32]], "one_way": False}
|
|
530
|
+
],
|
|
524
531
|
"properties": {},
|
|
525
532
|
},
|
|
526
533
|
},
|
|
@@ -546,7 +553,7 @@ class TestLoadMapObjects:
|
|
|
546
553
|
surf = pygame.Surface((16, 16))
|
|
547
554
|
# shape_a: 0-10, 0-10
|
|
548
555
|
shape_a = CollisionPolygon(vertices=[(0, 0), (10, 0), (10, 10), (0, 10)])
|
|
549
|
-
# shape_b: 20-30, 0-10
|
|
556
|
+
# shape_b: 20-30, 0-10
|
|
550
557
|
shape_b = CollisionPolygon(vertices=[(20, 0), (30, 0), (30, 10), (20, 10)])
|
|
551
558
|
|
|
552
559
|
obj1 = MapObject(x=0, y=0, surface=surf, collision_shape=shape_a, collision_shapes=[shape_a, shape_b])
|
|
@@ -627,7 +634,9 @@ class TestLoadMapObjects:
|
|
|
627
634
|
"region_id": "region_r",
|
|
628
635
|
"region_rect": [5, 10, 16, 16],
|
|
629
636
|
"name": "R",
|
|
630
|
-
"shapes": [
|
|
637
|
+
"shapes": [
|
|
638
|
+
{"type": "polygon", "vertices": [[0, 0], [16, 0], [16, 16], [0, 16]], "one_way": False}
|
|
639
|
+
],
|
|
631
640
|
"properties": {},
|
|
632
641
|
},
|
|
633
642
|
},
|
|
@@ -671,8 +680,8 @@ class TestLoadMapObjects:
|
|
|
671
680
|
|
|
672
681
|
def test_render_scale_3x(self):
|
|
673
682
|
"""render_scale=3.0 scales positions and polygon vertices."""
|
|
674
|
-
from tilemap_parser.runtime.map_object import load_map_objects
|
|
675
683
|
from tilemap_parser.runtime.map_loader import TilemapData
|
|
684
|
+
from tilemap_parser.runtime.map_object import load_map_objects
|
|
676
685
|
|
|
677
686
|
with tempfile.TemporaryDirectory() as tmp:
|
|
678
687
|
tmp = Path(tmp)
|
|
@@ -693,7 +702,9 @@ class TestLoadMapObjects:
|
|
|
693
702
|
"region_id": "region_r",
|
|
694
703
|
"region_rect": [5, 10, 16, 16],
|
|
695
704
|
"name": "R",
|
|
696
|
-
"shapes": [
|
|
705
|
+
"shapes": [
|
|
706
|
+
{"type": "polygon", "vertices": [[0, 0], [16, 0], [16, 16], [0, 16]], "one_way": False}
|
|
707
|
+
],
|
|
697
708
|
"properties": {},
|
|
698
709
|
},
|
|
699
710
|
},
|
|
@@ -792,7 +803,9 @@ class TestLoadMapObjects:
|
|
|
792
803
|
"region_id": "region_r",
|
|
793
804
|
"region_rect": [0, 0, 16, 16],
|
|
794
805
|
"name": "R",
|
|
795
|
-
"shapes": [
|
|
806
|
+
"shapes": [
|
|
807
|
+
{"type": "polygon", "vertices": [[0, 0], [16, 0], [16, 16], [0, 16]], "one_way": False}
|
|
808
|
+
],
|
|
796
809
|
"properties": {},
|
|
797
810
|
},
|
|
798
811
|
},
|
|
@@ -845,8 +858,9 @@ class TestLoadMapObjects:
|
|
|
845
858
|
objects = load_map_objects(td, collision_dir)
|
|
846
859
|
assert len(objects) == 1
|
|
847
860
|
obj = objects[0]
|
|
848
|
-
assert obj.surface.get_size() == (expected_w, expected_h),
|
|
861
|
+
assert obj.surface.get_size() == (expected_w, expected_h), (
|
|
849
862
|
f"rs={rs_val}: expected ({expected_w},{expected_h}) got {obj.surface.get_size()}"
|
|
863
|
+
)
|
|
850
864
|
assert obj.x == 10 * rs_val, f"rs={rs_val}: x={obj.x} != {10 * rs_val}"
|
|
851
865
|
assert obj.y == 20 * rs_val, f"rs={rs_val}: y={obj.y} != {20 * rs_val}"
|
|
852
866
|
|
|
@@ -863,7 +877,9 @@ class TestLoadMapObjects:
|
|
|
863
877
|
"region_id": "region_r",
|
|
864
878
|
"region_rect": [0, 0, 17, 35],
|
|
865
879
|
"name": "R",
|
|
866
|
-
"shapes": [
|
|
880
|
+
"shapes": [
|
|
881
|
+
{"type": "polygon", "vertices": [[0, 0], [17, 0], [17, 35], [0, 35]], "one_way": False}
|
|
882
|
+
],
|
|
867
883
|
"properties": {},
|
|
868
884
|
},
|
|
869
885
|
},
|
|
@@ -917,8 +933,9 @@ class TestLoadMapObjects:
|
|
|
917
933
|
obj = objects_odd[0]
|
|
918
934
|
assert obj.x == 11 * 1.5, f"fractional x: {obj.x} != {11 * 1.5}"
|
|
919
935
|
assert obj.y == 21 * 1.5, f"fractional y: {obj.y} != {21 * 1.5}"
|
|
920
|
-
assert obj.surface.get_size() == (25, 52),
|
|
936
|
+
assert obj.surface.get_size() == (25, 52), (
|
|
921
937
|
f"truncated surface: {obj.surface.get_size()} != (25, 52) [int(17*1.5)=25, int(35*1.5)=52]"
|
|
938
|
+
)
|
|
922
939
|
|
|
923
940
|
def test_render_scale_collision_consistency(self):
|
|
924
941
|
"""At render_scale=3.0, a loaded object collides with a manually-placed
|
|
@@ -943,7 +960,9 @@ class TestLoadMapObjects:
|
|
|
943
960
|
"region_id": "region_r",
|
|
944
961
|
"region_rect": [0, 0, 16, 16],
|
|
945
962
|
"name": "R",
|
|
946
|
-
"shapes": [
|
|
963
|
+
"shapes": [
|
|
964
|
+
{"type": "polygon", "vertices": [[0, 0], [16, 0], [16, 16], [0, 16]], "one_way": False}
|
|
965
|
+
],
|
|
947
966
|
"properties": {},
|
|
948
967
|
},
|
|
949
968
|
},
|
|
@@ -1115,8 +1134,8 @@ class TestLoadMapObjects:
|
|
|
1115
1134
|
def test_render_scale_visual_collision_alignment(self):
|
|
1116
1135
|
"""At render_scale=N, collision AABB is fully inside visual rect
|
|
1117
1136
|
and vertex positions are pixel-accurate for known values."""
|
|
1118
|
-
from tilemap_parser.runtime.map_object import load_map_objects
|
|
1119
1137
|
from tilemap_parser.runtime.map_loader import TilemapData
|
|
1138
|
+
from tilemap_parser.runtime.map_object import load_map_objects
|
|
1120
1139
|
|
|
1121
1140
|
with tempfile.TemporaryDirectory() as tmp:
|
|
1122
1141
|
tmp = Path(tmp)
|
|
@@ -1144,10 +1163,18 @@ class TestLoadMapObjects:
|
|
|
1144
1163
|
"shapes": [
|
|
1145
1164
|
{
|
|
1146
1165
|
"type": "polygon",
|
|
1147
|
-
"vertices": [
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1166
|
+
"vertices": [
|
|
1167
|
+
[32.0, 2.75],
|
|
1168
|
+
[8.0, 30.0],
|
|
1169
|
+
[10.5, 58.75],
|
|
1170
|
+
[22.5, 65.25],
|
|
1171
|
+
[20.0, 88.25],
|
|
1172
|
+
[33.5, 81.75],
|
|
1173
|
+
[47.5, 87.75],
|
|
1174
|
+
[41.5, 65.75],
|
|
1175
|
+
[58.5, 48.75],
|
|
1176
|
+
[52.0, 25.0],
|
|
1177
|
+
],
|
|
1151
1178
|
"one_way": False,
|
|
1152
1179
|
}
|
|
1153
1180
|
],
|
|
@@ -1207,8 +1234,9 @@ class TestLoadMapObjects:
|
|
|
1207
1234
|
# Verify surface size is pixel-accurate at integer render_scale
|
|
1208
1235
|
expected_w = int(64 * rs_val)
|
|
1209
1236
|
expected_h = int(96 * rs_val)
|
|
1210
|
-
assert obj.surface.get_size() == (expected_w, expected_h),
|
|
1237
|
+
assert obj.surface.get_size() == (expected_w, expected_h), (
|
|
1211
1238
|
f"rs={rs_val}: surface {obj.surface.get_size()} != ({expected_w},{expected_h})"
|
|
1239
|
+
)
|
|
1212
1240
|
|
|
1213
1241
|
# Verify position is pixel-accurate (float)
|
|
1214
1242
|
assert obj.x == 27 * rs_val, f"rs={rs_val}: x={obj.x} != {27 * rs_val}"
|
|
@@ -1219,10 +1247,12 @@ class TestLoadMapObjects:
|
|
|
1219
1247
|
# First vertex: (32.0, 2.75) + region_rect (0, 3) = world (32*rs, (3+2.75)*rs)
|
|
1220
1248
|
expected_v0 = (32.0 * rs_val, (3.0 + 2.75) * rs_val)
|
|
1221
1249
|
actual_v0 = shape.vertices[0]
|
|
1222
|
-
assert abs(actual_v0[0] - expected_v0[0]) < 0.001,
|
|
1250
|
+
assert abs(actual_v0[0] - expected_v0[0]) < 0.001, (
|
|
1223
1251
|
f"rs={rs_val}: vertex[0].x {actual_v0[0]} != {expected_v0[0]}"
|
|
1224
|
-
|
|
1252
|
+
)
|
|
1253
|
+
assert abs(actual_v0[1] - expected_v0[1]) < 0.001, (
|
|
1225
1254
|
f"rs={rs_val}: vertex[0].y {actual_v0[1]} != {expected_v0[1]}"
|
|
1255
|
+
)
|
|
1226
1256
|
|
|
1227
1257
|
# Verify collision AABB is inside visual rect
|
|
1228
1258
|
xs = [v[0] for v in shape.vertices]
|
|
@@ -1238,14 +1268,16 @@ class TestLoadMapObjects:
|
|
|
1238
1268
|
vis_bottom = obj.y + expected_h
|
|
1239
1269
|
|
|
1240
1270
|
margin = -0.001 # allow 0px floating point tolerance
|
|
1241
|
-
assert coll_min_x >= vis_left + margin,
|
|
1271
|
+
assert coll_min_x >= vis_left + margin, (
|
|
1242
1272
|
f"rs={rs_val}: collision left {coll_min_x} < visual left {vis_left}"
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
assert coll_max_x <= vis_right - margin,
|
|
1273
|
+
)
|
|
1274
|
+
assert coll_min_y >= vis_top + margin, f"rs={rs_val}: collision top {coll_min_y} < visual top {vis_top}"
|
|
1275
|
+
assert coll_max_x <= vis_right - margin, (
|
|
1246
1276
|
f"rs={rs_val}: collision right {coll_max_x} > visual right {vis_right}"
|
|
1247
|
-
|
|
1277
|
+
)
|
|
1278
|
+
assert coll_max_y <= vis_bottom - margin, (
|
|
1248
1279
|
f"rs={rs_val}: collision bottom {coll_max_y} > visual bottom {vis_bottom}"
|
|
1280
|
+
)
|
|
1249
1281
|
|
|
1250
1282
|
def test_invalid_tileset_index_skipped(self):
|
|
1251
1283
|
"""Object with ttype out of range is skipped."""
|
|
@@ -1320,5 +1352,28 @@ class TestLoadMapObjects:
|
|
|
1320
1352
|
assert obj.collision_shapes == []
|
|
1321
1353
|
assert obj.has_collision is False
|
|
1322
1354
|
|
|
1355
|
+
def test_ttype_default_minus_one(self):
|
|
1356
|
+
"""Direct MapObject creation without ttype defaults to -1."""
|
|
1357
|
+
surf = pygame.Surface((16, 16))
|
|
1358
|
+
obj = MapObject(x=0, y=0, surface=surf)
|
|
1359
|
+
assert obj.ttype == -1
|
|
1323
1360
|
|
|
1361
|
+
def test_ttype_set_on_construction(self):
|
|
1362
|
+
"""ttype is stored when passed to MapObject.__init__."""
|
|
1363
|
+
surf = pygame.Surface((16, 16))
|
|
1364
|
+
obj = MapObject(x=0, y=0, surface=surf, ttype=3)
|
|
1365
|
+
assert obj.ttype == 3
|
|
1324
1366
|
|
|
1367
|
+
def test_ttype_on_loaded_object(self, basic_map):
|
|
1368
|
+
"""load_map_objects sets ttype from ParsedObject.ttype."""
|
|
1369
|
+
td, collision_dir, _ = basic_map
|
|
1370
|
+
objects = load_map_objects(td, collision_dir)
|
|
1371
|
+
assert len(objects) == 1
|
|
1372
|
+
assert objects[0].ttype == 0
|
|
1373
|
+
|
|
1374
|
+
def test_ttype_on_visual_only_object(self, map_no_collision_file):
|
|
1375
|
+
"""Visual-only objects (require_collision=False) carry ttype."""
|
|
1376
|
+
td, collision_dir = map_no_collision_file
|
|
1377
|
+
objects = load_map_objects(td, collision_dir, require_collision=False)
|
|
1378
|
+
assert len(objects) == 1
|
|
1379
|
+
assert objects[0].ttype == 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/animation_player.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser/runtime/object_collision.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-4.2.5 → tilemap_parser-4.2.7}/src/tilemap_parser.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|