fix(client): address PR review — invalidation, constants, tests
Review feedback from Hoshe + Tyre on PR #8: - Extract shared TILE_SIZE to Constants class_name (Tyre #5, Hoshe #7) - Fix tile invalidation: detect tile/visibility count changes instead of one-shot dirty flag, supports chunk loading (Tyre #3, #4) - Fog dirty tracking: only re-render when visible_positions changes - Add bounds warning for unknown tile types (Hoshe #1) - Add player-not-found warning in GameState (Hoshe #5) - Use Image.fill_rect() instead of pixel loops (Tyre #10) - Document _player_pos as reserved for fog decay #113 (Tyre #6) - Add TODO(#130) for D-033 relationship colors (Hoshe #3, Tyre #8) - Add class_name to EntityRenderer, FogRenderer, TileRenderer - 20 new rendering tests (D-030 Layer 1): entity lifecycle, fog registration, tile type mapping, snapshot completeness, constants - 65 total tests passing, 0 failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
class_name FogRenderer
|
||||
extends TileMapLayer
|
||||
|
||||
# Fog renderer — draws fog overlay on non-visible tiles (D-011)
|
||||
@@ -9,8 +10,12 @@ extends TileMapLayer
|
||||
# Atlas layout:
|
||||
# (0,0) = full fog (opaque black)
|
||||
# (1,0) = fog edge (semi-transparent)
|
||||
#
|
||||
# Note: fog-edge uses 8-directional neighbors for visual smoothness.
|
||||
# Actual visibility boundaries come from the server's shadowcasting (D-011).
|
||||
# Fog-returns-over-time (D-011 decay) is tracked in #113, not here.
|
||||
|
||||
const TILE_SIZE: int = 32
|
||||
const TILE_SIZE: int = Constants.TILE_SIZE
|
||||
|
||||
var _initialized: bool = false
|
||||
var _all_tile_positions: Dictionary = {} # Vector2i -> true, all known map tiles
|
||||
@@ -28,9 +33,9 @@ func _setup_tileset() -> void:
|
||||
var img := Image.create(TILE_SIZE * 2, TILE_SIZE, false, Image.FORMAT_RGBA8)
|
||||
|
||||
# Full fog (0,0) — opaque black
|
||||
_fill_tile(img, 0, Color(0.02, 0.02, 0.05, 1.0))
|
||||
img.fill_rect(Rect2i(0, 0, TILE_SIZE, TILE_SIZE), Color(0.02, 0.02, 0.05, 1.0))
|
||||
# Fog edge (1,0) — semi-transparent dark
|
||||
_fill_tile(img, 1, Color(0.02, 0.02, 0.05, 0.6))
|
||||
img.fill_rect(Rect2i(TILE_SIZE, 0, TILE_SIZE, TILE_SIZE), Color(0.02, 0.02, 0.05, 0.6))
|
||||
|
||||
var tex := ImageTexture.create_from_image(img)
|
||||
source.texture = tex
|
||||
@@ -49,8 +54,8 @@ func register_tile_positions(tiles: Array) -> void:
|
||||
if tile_data.has("x") and tile_data.has("y"):
|
||||
_all_tile_positions[Vector2i(tile_data.x, tile_data.y)] = true
|
||||
|
||||
# Update fog based on visible positions
|
||||
# visible_positions: Dictionary of Vector2i -> true
|
||||
# Update fog based on visible positions.
|
||||
# player_pos reserved for future fog-decay tracking (#113).
|
||||
func update_fog(visible_positions: Dictionary, _player_pos: Vector2) -> void:
|
||||
if not _initialized:
|
||||
return
|
||||
@@ -60,7 +65,7 @@ func update_fog(visible_positions: Dictionary, _player_pos: Vector2) -> void:
|
||||
if _all_tile_positions.is_empty() or visible_positions.is_empty():
|
||||
return
|
||||
|
||||
# Build set of fog-edge positions (adjacent to visible but not visible themselves)
|
||||
# Build set of fog-edge positions (8-directional neighbors of visible tiles)
|
||||
var fog_edge: Dictionary = {}
|
||||
var neighbors := [
|
||||
Vector2i(-1, 0), Vector2i(1, 0), Vector2i(0, -1), Vector2i(0, 1),
|
||||
@@ -81,9 +86,3 @@ func update_fog(visible_positions: Dictionary, _player_pos: Vector2) -> void:
|
||||
set_cell(pos, 0, Vector2i(1, 0)) # Fog edge — semi-transparent
|
||||
else:
|
||||
set_cell(pos, 0, Vector2i(0, 0)) # Full fog — opaque
|
||||
|
||||
func _fill_tile(img: Image, tile_index: int, color: Color) -> void:
|
||||
var x_offset := tile_index * TILE_SIZE
|
||||
for x in range(TILE_SIZE):
|
||||
for y in range(TILE_SIZE):
|
||||
img.set_pixel(x_offset + x, y, color)
|
||||
|
||||
Reference in New Issue
Block a user