tilemap-parser 3.1.20__tar.gz → 3.1.21__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-3.1.20 → tilemap_parser-3.1.21}/PKG-INFO +1 -1
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/pyproject.toml +1 -1
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/object_collision.py +20 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser.egg-info/PKG-INFO +1 -1
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_object_collision.py +72 -18
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_tile_collision.py +2 -2
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/LICENSE +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/README.md +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/setup.cfg +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/__init__.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/__init__.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/animation.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/collision.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/collision_loader.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/map_parse.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/node_parse.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/particle.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/__init__.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/animation_player.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/area_node.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/collision_cache.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/map_loader.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/particles.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/renderer.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/tile_collision.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/utils/__init__.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/utils/geometry.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser.egg-info/SOURCES.txt +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser.egg-info/dependency_links.txt +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser.egg-info/requires.txt +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser.egg-info/top_level.txt +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_collision.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_geometry.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_map_loader.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_object_surfaces.py +0 -0
- {tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/tests/test_render_scale.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-parser
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.21
|
|
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.
|
|
7
|
+
version = "3.1.21"
|
|
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"
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/object_collision.py
RENAMED
|
@@ -455,3 +455,23 @@ class ObjectCollisionManager:
|
|
|
455
455
|
if hit is not None:
|
|
456
456
|
hits.append(hit)
|
|
457
457
|
return hits
|
|
458
|
+
|
|
459
|
+
def check_object_first(self, obj: ICollidableObject) -> Optional[CollisionHit]:
|
|
460
|
+
"""
|
|
461
|
+
Check one object against all others and return the first collision hit.
|
|
462
|
+
|
|
463
|
+
The queried object does not need to be managed. If it is managed,
|
|
464
|
+
comparison with itself is skipped by identity.
|
|
465
|
+
|
|
466
|
+
Candidate iteration follows insertion order among the spatially relevant
|
|
467
|
+
managed objects.
|
|
468
|
+
"""
|
|
469
|
+
objects, grid = self._build_spatial_index()
|
|
470
|
+
for index in sorted(self._candidate_indices(obj, grid)):
|
|
471
|
+
other = objects[index]
|
|
472
|
+
if other is obj:
|
|
473
|
+
continue
|
|
474
|
+
hit = check_collision(obj, other)
|
|
475
|
+
if hit is not None:
|
|
476
|
+
return hit
|
|
477
|
+
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tilemap-parser
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.21
|
|
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,32 +8,33 @@ Covers:
|
|
|
8
8
|
- ObjectCollisionManager (add/remove, queries, duplicates, warnings)
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
import sys
|
|
11
12
|
import warnings
|
|
12
|
-
import pytest
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
15
16
|
|
|
16
17
|
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
|
17
18
|
|
|
19
|
+
import tilemap_parser.runtime.object_collision as object_collision_runtime
|
|
18
20
|
from tilemap_parser.parser.collision import (
|
|
19
21
|
CapsuleShape,
|
|
20
22
|
CircleShape,
|
|
21
23
|
CollisionPolygon,
|
|
22
24
|
RectangleShape,
|
|
23
25
|
)
|
|
24
|
-
import tilemap_parser.runtime.object_collision as object_collision_runtime
|
|
25
26
|
from tilemap_parser.runtime.object_collision import (
|
|
26
27
|
CollisionHit,
|
|
27
28
|
ObjectCollisionManager,
|
|
28
|
-
should_collide,
|
|
29
29
|
check_collision,
|
|
30
|
+
should_collide,
|
|
30
31
|
)
|
|
31
32
|
|
|
32
|
-
|
|
33
33
|
# ---------------------------------------------------------------------------
|
|
34
34
|
# Helpers — concrete objects implementing ICollidableObject
|
|
35
35
|
# ---------------------------------------------------------------------------
|
|
36
36
|
|
|
37
|
+
|
|
37
38
|
class _DummyObject:
|
|
38
39
|
"""Minimal collidable object for tests."""
|
|
39
40
|
|
|
@@ -68,6 +69,7 @@ def _make_poly(x, y, vertices, collision_layer=1, collision_mask=0xFFFFFFFF):
|
|
|
68
69
|
# should_collide
|
|
69
70
|
# ---------------------------------------------------------------------------
|
|
70
71
|
|
|
72
|
+
|
|
71
73
|
class TestShouldCollide:
|
|
72
74
|
def test_default_layers_collide(self):
|
|
73
75
|
a = _make_rect(0, 0, 10, 10)
|
|
@@ -94,6 +96,7 @@ class TestShouldCollide:
|
|
|
94
96
|
x = 0.0
|
|
95
97
|
y = 0.0
|
|
96
98
|
collision_shape = RectangleShape(width=10, height=10)
|
|
99
|
+
|
|
97
100
|
assert should_collide(BareObject(), BareObject()) is True
|
|
98
101
|
|
|
99
102
|
|
|
@@ -101,6 +104,7 @@ class TestShouldCollide:
|
|
|
101
104
|
# check_collision
|
|
102
105
|
# ---------------------------------------------------------------------------
|
|
103
106
|
|
|
107
|
+
|
|
104
108
|
class TestCheckCollisionCircleCircle:
|
|
105
109
|
def test_colliding(self):
|
|
106
110
|
a = _make_circle(0, 0, 10)
|
|
@@ -237,6 +241,7 @@ class TestCheckCollisionPolygon:
|
|
|
237
241
|
# ObjectCollisionManager
|
|
238
242
|
# ---------------------------------------------------------------------------
|
|
239
243
|
|
|
244
|
+
|
|
240
245
|
class TestManagerAddRemove:
|
|
241
246
|
def test_add_and_remove(self):
|
|
242
247
|
mgr = ObjectCollisionManager()
|
|
@@ -439,10 +444,44 @@ class TestManagerCheckObject:
|
|
|
439
444
|
assert hits[0].object_b is managed
|
|
440
445
|
|
|
441
446
|
|
|
447
|
+
class TestManagerCheckObjectFirst:
|
|
448
|
+
def test_returns_first_hit(self):
|
|
449
|
+
mgr = ObjectCollisionManager()
|
|
450
|
+
query = _make_circle(0, 0, 10)
|
|
451
|
+
first = _make_circle(15, 0, 10)
|
|
452
|
+
second = _make_circle(18, 0, 10)
|
|
453
|
+
far = _make_circle(100, 0, 10)
|
|
454
|
+
mgr.add_object(first)
|
|
455
|
+
mgr.add_object(second)
|
|
456
|
+
mgr.add_object(far)
|
|
457
|
+
|
|
458
|
+
hit = mgr.check_object_first(query)
|
|
459
|
+
|
|
460
|
+
assert hit is not None
|
|
461
|
+
assert hit.object_a is query
|
|
462
|
+
assert hit.object_b is first
|
|
463
|
+
|
|
464
|
+
def test_returns_none_when_no_hit(self):
|
|
465
|
+
mgr = ObjectCollisionManager()
|
|
466
|
+
query = _make_rect(0, 0, 10, 10)
|
|
467
|
+
far = _make_rect(100, 0, 10, 10)
|
|
468
|
+
mgr.add_object(far)
|
|
469
|
+
|
|
470
|
+
assert mgr.check_object_first(query) is None
|
|
471
|
+
|
|
472
|
+
def test_skips_self(self):
|
|
473
|
+
mgr = ObjectCollisionManager()
|
|
474
|
+
obj = _make_rect(0, 0, 10, 10)
|
|
475
|
+
mgr.add_object(obj)
|
|
476
|
+
|
|
477
|
+
assert mgr.check_object_first(obj) is None
|
|
478
|
+
|
|
479
|
+
|
|
442
480
|
# ---------------------------------------------------------------------------
|
|
443
481
|
# CollisionHit helpers
|
|
444
482
|
# ---------------------------------------------------------------------------
|
|
445
483
|
|
|
484
|
+
|
|
446
485
|
class TestCollisionHitHelpers:
|
|
447
486
|
def test_resolve_separates(self):
|
|
448
487
|
a = _make_circle(0, 0, 10)
|
|
@@ -486,8 +525,10 @@ class TestCollisionHitHelpers:
|
|
|
486
525
|
def test_slide_head_on(self):
|
|
487
526
|
"""Directly into surface → zero tangential motion."""
|
|
488
527
|
hit = CollisionHit(
|
|
489
|
-
object_a=None,
|
|
490
|
-
|
|
528
|
+
object_a=None,
|
|
529
|
+
object_b=None,
|
|
530
|
+
normal=(1.0, 0.0),
|
|
531
|
+
depth=5.0,
|
|
491
532
|
)
|
|
492
533
|
sx, sy = hit.slide_velocity(10.0, 0.0)
|
|
493
534
|
assert sx == 0.0
|
|
@@ -496,8 +537,10 @@ class TestCollisionHitHelpers:
|
|
|
496
537
|
def test_slide_angled(self):
|
|
497
538
|
"""Diagonal into surface → only perpendicular component removed."""
|
|
498
539
|
hit = CollisionHit(
|
|
499
|
-
object_a=None,
|
|
500
|
-
|
|
540
|
+
object_a=None,
|
|
541
|
+
object_b=None,
|
|
542
|
+
normal=(1.0, 0.0),
|
|
543
|
+
depth=5.0,
|
|
501
544
|
)
|
|
502
545
|
sx, sy = hit.slide_velocity(10.0, 5.0)
|
|
503
546
|
assert sx == 0.0 # x component fully removed
|
|
@@ -506,8 +549,10 @@ class TestCollisionHitHelpers:
|
|
|
506
549
|
def test_slide_parallel(self):
|
|
507
550
|
"""Velocity along the surface → unchanged."""
|
|
508
551
|
hit = CollisionHit(
|
|
509
|
-
object_a=None,
|
|
510
|
-
|
|
552
|
+
object_a=None,
|
|
553
|
+
object_b=None,
|
|
554
|
+
normal=(0.0, 1.0),
|
|
555
|
+
depth=5.0,
|
|
511
556
|
)
|
|
512
557
|
sx, sy = hit.slide_velocity(10.0, 0.0)
|
|
513
558
|
assert sx == 10.0
|
|
@@ -516,8 +561,10 @@ class TestCollisionHitHelpers:
|
|
|
516
561
|
def test_slide_away(self):
|
|
517
562
|
"""Velocity pointing away from surface → unchanged."""
|
|
518
563
|
hit = CollisionHit(
|
|
519
|
-
object_a=None,
|
|
520
|
-
|
|
564
|
+
object_a=None,
|
|
565
|
+
object_b=None,
|
|
566
|
+
normal=(1.0, 0.0),
|
|
567
|
+
depth=5.0,
|
|
521
568
|
)
|
|
522
569
|
sx, sy = hit.slide_velocity(-10.0, 0.0)
|
|
523
570
|
assert sx == -10.0
|
|
@@ -526,8 +573,10 @@ class TestCollisionHitHelpers:
|
|
|
526
573
|
def test_slide_zero(self):
|
|
527
574
|
"""Zero velocity → zero."""
|
|
528
575
|
hit = CollisionHit(
|
|
529
|
-
object_a=None,
|
|
530
|
-
|
|
576
|
+
object_a=None,
|
|
577
|
+
object_b=None,
|
|
578
|
+
normal=(1.0, 0.0),
|
|
579
|
+
depth=5.0,
|
|
531
580
|
)
|
|
532
581
|
sx, sy = hit.slide_velocity(0.0, 0.0)
|
|
533
582
|
assert sx == 0.0
|
|
@@ -536,10 +585,13 @@ class TestCollisionHitHelpers:
|
|
|
536
585
|
def test_slide_diagonal_normal(self):
|
|
537
586
|
"""Normal at 45°, velocity into surface → slide along surface."""
|
|
538
587
|
import math
|
|
588
|
+
|
|
539
589
|
n = (1.0 / math.sqrt(2), 1.0 / math.sqrt(2))
|
|
540
590
|
hit = CollisionHit(
|
|
541
|
-
object_a=None,
|
|
542
|
-
|
|
591
|
+
object_a=None,
|
|
592
|
+
object_b=None,
|
|
593
|
+
normal=n,
|
|
594
|
+
depth=5.0,
|
|
543
595
|
)
|
|
544
596
|
sx, sy = hit.slide_velocity(1.0, 0.0)
|
|
545
597
|
# Dot = 1/sqrt(2) ≈ 0.707
|
|
@@ -552,6 +604,7 @@ class TestCollisionHitHelpers:
|
|
|
552
604
|
# Capsule collision
|
|
553
605
|
# ---------------------------------------------------------------------------
|
|
554
606
|
|
|
607
|
+
|
|
555
608
|
def _make_capsule(
|
|
556
609
|
x: float = 0.0,
|
|
557
610
|
y: float = 0.0,
|
|
@@ -563,7 +616,8 @@ def _make_capsule(
|
|
|
563
616
|
collision_mask: int = 0xFFFFFFFF,
|
|
564
617
|
) -> _DummyObject:
|
|
565
618
|
return _DummyObject(
|
|
566
|
-
x=x,
|
|
619
|
+
x=x,
|
|
620
|
+
y=y,
|
|
567
621
|
shape=CapsuleShape(radius=radius, height=height, offset=(ox, oy)),
|
|
568
622
|
collision_layer=collision_layer,
|
|
569
623
|
collision_mask=collision_mask,
|
|
@@ -142,9 +142,9 @@ class TestShapeBounds:
|
|
|
142
142
|
sprite = MockSprite(x=100, y=200, shape=CapsuleShape(radius=8, height=48, offset=(0, 0)))
|
|
143
143
|
left, top, right, bottom = get_shape_bounds(sprite)
|
|
144
144
|
assert left == 92
|
|
145
|
-
assert top ==
|
|
145
|
+
assert top == 192
|
|
146
146
|
assert right == 108
|
|
147
|
-
assert bottom ==
|
|
147
|
+
assert bottom == 256
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
# ===========================================================================
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/parser/collision_loader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/animation_player.py
RENAMED
|
File without changes
|
|
File without changes
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/collision_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/src/tilemap_parser/runtime/tile_collision.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tilemap_parser-3.1.20 → tilemap_parser-3.1.21}/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
|