tilemap-parser 3.1.9__tar.gz → 3.1.10__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 (33) hide show
  1. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/PKG-INFO +1 -1
  2. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/pyproject.toml +1 -1
  3. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/renderer.py +70 -25
  4. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser.egg-info/PKG-INFO +1 -1
  5. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/LICENSE +0 -0
  6. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/README.md +0 -0
  7. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/setup.cfg +0 -0
  8. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/__init__.py +0 -0
  9. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/__init__.py +0 -0
  10. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/animation.py +0 -0
  11. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/collision.py +0 -0
  12. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/collision_loader.py +0 -0
  13. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/map_parse.py +0 -0
  14. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/parser/node_parse.py +0 -0
  15. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/__init__.py +0 -0
  16. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/animation_player.py +0 -0
  17. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/area_node.py +0 -0
  18. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/collision_cache.py +0 -0
  19. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/map_loader.py +0 -0
  20. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/object_collision.py +0 -0
  21. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/runtime/tile_collision.py +0 -0
  22. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/utils/__init__.py +0 -0
  23. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser/utils/geometry.py +0 -0
  24. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser.egg-info/SOURCES.txt +0 -0
  25. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser.egg-info/dependency_links.txt +0 -0
  26. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser.egg-info/requires.txt +0 -0
  27. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/src/tilemap_parser.egg-info/top_level.txt +0 -0
  28. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/tests/test_collision.py +0 -0
  29. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/tests/test_geometry.py +0 -0
  30. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/tests/test_map_loader.py +0 -0
  31. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/tests/test_object_collision.py +0 -0
  32. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/tests/test_render_scale.py +0 -0
  33. {tilemap_parser-3.1.9 → tilemap_parser-3.1.10}/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.9
3
+ Version: 3.1.10
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.9"
7
+ version = "3.1.10"
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"
@@ -1,13 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
- from typing import Dict, Optional, Tuple, Union
4
+ from typing import Dict, List, Optional, Tuple, Union
5
5
 
6
6
  import pygame
7
7
  from pygame import Rect, Surface, transform
8
8
 
9
9
  from .map_loader import TilemapData
10
10
 
11
+ CHUNK_SIZE = 32
12
+
11
13
 
12
14
  @dataclass(frozen=True)
13
15
  class LayerRenderStats:
@@ -28,7 +30,9 @@ class TileLayerRenderer:
28
30
  self.tile_layers.keys(),
29
31
  key=lambda lid: (self.tile_layers[lid].z_index, lid),
30
32
  )
33
+
31
34
  self._variant_cache: Dict[Tuple[int, int], Optional[Surface]] = {}
35
+
32
36
  self._tile_w, self._tile_h = data.tile_size
33
37
  self._rs = data.render_scale
34
38
  if self._rs <= 0:
@@ -52,15 +56,26 @@ class TileLayerRenderer:
52
56
  "animation_mode": ts.animation.animation_mode,
53
57
  }
54
58
 
59
+ self._layer_chunks: Dict[int, Dict[Tuple[int, int], List[Tuple[int, int]]]] = {}
60
+ for layer_id, layer in self.tile_layers.items():
61
+ chunks: Dict[Tuple[int, int], List[Tuple[int, int]]] = {}
62
+ for (x, y), tile in layer.tiles.items():
63
+ if not isinstance(tile.ttype, int):
64
+ continue
65
+ cx, cy = x // CHUNK_SIZE, y // CHUNK_SIZE
66
+ chunk_key = (cx, cy)
67
+ if chunk_key not in chunks:
68
+ chunks[chunk_key] = []
69
+ chunks[chunk_key].append((x, y))
70
+ self._layer_chunks[layer_id] = chunks
71
+
55
72
  def get_layer_dict(self) -> Dict[int, object]:
56
73
  return dict(self.tile_layers)
57
74
 
58
75
  def _get_cached_variant(self, ttype: int, variant: int) -> Optional[Surface]:
59
76
  key = (ttype, variant)
60
77
  if key not in self._variant_cache:
61
- cell = self.data.get_tile_surface(
62
- ttype, variant, copy_surface=True
63
- )
78
+ cell = self.data.get_tile_surface(ttype, variant, copy_surface=True)
64
79
  if cell is not None and self._rs != 1.0:
65
80
  cell = transform.scale(cell, (self._eff_w, self._eff_h))
66
81
  self._variant_cache[key] = cell
@@ -70,7 +85,15 @@ class TileLayerRenderer:
70
85
  for layer_id in self._sorted_layer_ids:
71
86
  layer = self.tile_layers[layer_id]
72
87
  for tile in layer.tiles.values():
73
- if isinstance(tile.ttype, int):
88
+ if not isinstance(tile.ttype, int):
89
+ continue
90
+ anim = self._tileset_animations.get(tile.ttype)
91
+ if anim is not None:
92
+ frame_count = anim["frame_count"]
93
+ stride = anim["frame_stride"]
94
+ for f in range(frame_count):
95
+ self._get_cached_variant(tile.ttype, tile.variant + f * stride)
96
+ else:
74
97
  self._get_cached_variant(tile.ttype, tile.variant)
75
98
  self.data = None
76
99
 
@@ -85,13 +108,15 @@ class TileLayerRenderer:
85
108
  anim = self._tileset_animations.get(ttype)
86
109
  if anim is None:
87
110
  return variant
88
- stride = anim["frame_stride"]
111
+
89
112
  frame_count = anim["frame_count"]
90
- frame_idx = int(time_ms / anim["frame_duration_ms"]) % frame_count
113
+ frame_idx = (time_ms // anim["frame_duration_ms"]) % frame_count
114
+
91
115
  if anim.get("animation_mode") == "random_start_times":
92
- phase = hash((x, y, ttype)) % frame_count
116
+ phase = ((x * 73856093) ^ (y * 19349663) ^ (ttype * 83492791)) % frame_count
93
117
  frame_idx = (frame_idx + phase) % frame_count
94
- return variant + frame_idx * stride
118
+
119
+ return variant + frame_idx * anim["frame_stride"]
95
120
 
96
121
  def render(
97
122
  self,
@@ -101,6 +126,13 @@ class TileLayerRenderer:
101
126
  *,
102
127
  current_time_ms: Optional[float] = None,
103
128
  ) -> LayerRenderStats:
129
+ """Render visible tile layers.
130
+
131
+ Note: ``skipped_tiles`` is a debugging indicator, not a whole-map
132
+ accumulated count. It tracks null surfaces and invalid tiles within
133
+ the active chunk range — enough to spot rendering issues without
134
+ the cost of a full scan.
135
+ """
104
136
  cam_x, cam_y = float(camera_xy[0]), float(camera_xy[1])
105
137
  if viewport_size is None:
106
138
  viewport = target.get_rect()
@@ -120,27 +152,40 @@ class TileLayerRenderer:
120
152
  skipped = 0
121
153
  visible_layers = 0
122
154
 
155
+ min_cx = min_x // CHUNK_SIZE
156
+ max_cx = max_x // CHUNK_SIZE
157
+ min_cy = min_y // CHUNK_SIZE
158
+ max_cy = max_y // CHUNK_SIZE
159
+
123
160
  for layer_id in self._sorted_layer_ids:
124
161
  layer = self.tile_layers[layer_id]
125
162
  if not layer.visible:
126
163
  continue
127
164
  visible_layers += 1
128
- for (x, y), tile in layer.tiles.items():
129
- if x < min_x or x > max_x or y < min_y or y > max_y:
130
- skipped += 1
131
- continue
132
- if not isinstance(tile.ttype, int):
133
- skipped += 1
134
- continue
135
- display_variant = self._compute_display_variant(
136
- tile.variant, tile.ttype, x, y, time_ms
137
- )
138
- cell = self._get_cached_variant(tile.ttype, display_variant)
139
- if cell is None:
140
- skipped += 1
141
- continue
142
- target.blit(cell, (x * self._eff_w - cam_x, y * self._eff_h - cam_y))
143
- drawn += 1
165
+
166
+ chunks = self._layer_chunks[layer_id]
167
+
168
+ for cx in range(min_cx, max_cx + 1):
169
+ for cy in range(min_cy, max_cy + 1):
170
+ chunk = chunks.get((cx, cy))
171
+ if not chunk:
172
+ continue
173
+
174
+ for x, y in chunk:
175
+ tile = layer.tiles[(x, y)]
176
+ display_variant = self._compute_display_variant(
177
+ tile.variant, tile.ttype, x, y, time_ms
178
+ )
179
+ cell = self._get_cached_variant(tile.ttype, display_variant)
180
+ if cell is None:
181
+ skipped += 1
182
+ continue
183
+
184
+ target.blit(
185
+ cell,
186
+ (x * self._eff_w - cam_x, y * self._eff_h - cam_y),
187
+ )
188
+ drawn += 1
144
189
 
145
190
  return LayerRenderStats(
146
191
  drawn_tiles=drawn, skipped_tiles=skipped, visible_layers=visible_layers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tilemap-parser
3
- Version: 3.1.9
3
+ Version: 3.1.10
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
File without changes