fix(client): address PR #54 review — 7 items across Hoshe and Tyre
Critical: DIALOGUE_MAX_WIDTH 1200 → 640 to match D-076 spec. tile_renderer: clarify z = server floor level, not scene z_index. Add z-filter unit test (tiles at z!=0 must be skipped). Camera test: is_equal → distance check for float safety, convergence test frames 40 → 120 for robustness at lower smoothing speeds. Teleport: remove redundant first snap in _teleport_transition (the camera block in _process handles it via _teleport_in_progress flag). entity_renderer: document y-sort bottom-anchor migration path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -94,7 +94,7 @@ const FACING_INDICATOR_OFFSET: float = 14.0
|
||||
# 640px = 20 × TILE_SIZE (32px) — grid-aligned, ~33% of 1920px viewport.
|
||||
# Tyre architecture review 2026-02-19: readability over max-width; fits
|
||||
# two columns of text comfortably, leaves world game visible alongside.
|
||||
const DIALOGUE_MAX_WIDTH: int = 1200
|
||||
const DIALOGUE_MAX_WIDTH: int = 640
|
||||
|
||||
# Default camera zoom — used as fallback when get_camera_2d() returns null
|
||||
const CAMERA_DEFAULT_ZOOM: Vector2 = Vector2(2.0, 2.0)
|
||||
|
||||
@@ -425,10 +425,8 @@ func _detect_teleport(old_pos: Vector2, new_pos: Vector2) -> bool:
|
||||
# Clears dialogue/monologue/interaction state (server clears its side too).
|
||||
# Scoped to Gauntlet testing only — production fast-travel uses diegetic gates.
|
||||
func _teleport_transition() -> void:
|
||||
# Snap camera immediately to new position. _teleport_in_progress causes
|
||||
# the lerp block in _process() to snap again on the same frame (in case
|
||||
# player_position updates after this call) and skip lerp next frame.
|
||||
camera.global_position = GameState.player_position * Constants.TILE_SIZE
|
||||
# Set teleport flag — the camera tracking block in _process() will snap
|
||||
# to the player's new position this frame (no lerp). Flag clears after snap.
|
||||
_camera_anchored = true
|
||||
_teleport_in_progress = true
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ const TILE_SIZE: int = Constants.TILE_SIZE
|
||||
const ENTITY_WIDTH: int = 24
|
||||
const ENTITY_HEIGHT: int = 32
|
||||
const ENTITY_OFFSET_X: float = (TILE_SIZE - ENTITY_WIDTH) / 2.0 # center horizontally
|
||||
const ENTITY_OFFSET_Y: float = (TILE_SIZE - ENTITY_HEIGHT) / 2.0 # center vertically (bottom-aligned for y-sort would use TILE_SIZE - ENTITY_HEIGHT, but center is correct for placeholder)
|
||||
const ENTITY_OFFSET_Y: float = (TILE_SIZE - ENTITY_HEIGHT) / 2.0 # center vertically for placeholder. Migration: when real sprites land, switch to bottom-anchor (TILE_SIZE - ENTITY_HEIGHT) for correct y-sort ordering.
|
||||
|
||||
# Lerp speed — framerate-independent exponential smoothing.
|
||||
# At 12.0: ~70% there after 0.1s, ~95% after 0.25s.
|
||||
|
||||
@@ -64,8 +64,10 @@ func _setup_tileset() -> void:
|
||||
|
||||
# Update tiles from snapshot data
|
||||
# tiles: Array of {x: int, y: int, z: int, type: String}
|
||||
# Only renders z=0 tiles (ground floor). z=1 (FloorObjects) and z>1 (upper floors)
|
||||
# are handled by separate nodes — skipped here until those layers are implemented.
|
||||
# z here is the server-side FLOOR LEVEL (0 = ground, 1 = first floor, etc.),
|
||||
# NOT the Godot scene z_index (which controls render order within a floor).
|
||||
# This node only renders floor-level 0. Higher floor levels will be handled
|
||||
# by separate TileMapLayer nodes when multi-floor rendering is implemented.
|
||||
func update_tiles(tiles: Array) -> void:
|
||||
if not _initialized:
|
||||
return
|
||||
@@ -76,8 +78,8 @@ func update_tiles(tiles: Array) -> void:
|
||||
if not tile_data.has("x") or not tile_data.has("y") or not tile_data.has("type"):
|
||||
continue
|
||||
|
||||
# Multi-layer support: FloorTiles only renders z=0 (ground floor).
|
||||
# z=1 → FloorObjects node, z=2 → YSortGroup furniture (future layers).
|
||||
# Floor-level filter: only render tiles at floor level 0 (ground).
|
||||
# Floor level 1+ tiles are for upper floors (future multi-floor nodes).
|
||||
var tile_z: int = tile_data.get("z", 0)
|
||||
if tile_z != 0:
|
||||
continue
|
||||
|
||||
@@ -100,8 +100,8 @@ func test_camera_converges_to_player_over_multiple_frames() -> void:
|
||||
|
||||
var target := GameState.player_position * Constants.TILE_SIZE
|
||||
|
||||
# Run 40 frames (~0.67s at 60fps) — well past convergence for any speed ≥ 2.0
|
||||
for i in range(40):
|
||||
# Run 120 frames (~2s at 60fps) — converges within 1px for any speed ≥ 2.0
|
||||
for i in range(120):
|
||||
_instance._process(0.016)
|
||||
|
||||
var camera: Camera2D = _instance.get_node("Camera2D")
|
||||
@@ -123,8 +123,9 @@ func test_camera_stationary_player_no_drift() -> void:
|
||||
for i in range(10):
|
||||
_instance._process(0.016)
|
||||
|
||||
# Camera should still be at anchored position (target = same point)
|
||||
assert_that(camera.global_position).is_equal(initial_pos)
|
||||
# Camera should still be at anchored position (target = same point).
|
||||
# Use distance check — lerp toward same point may introduce float rounding.
|
||||
assert_that(camera.global_position.distance_to(initial_pos) < 0.01).is_true()
|
||||
|
||||
|
||||
# --- Teleport snap ---
|
||||
|
||||
@@ -270,3 +270,34 @@ func test_entities_in_ysort_group() -> void:
|
||||
add_child(_instance)
|
||||
|
||||
assert_that(_instance.get_node_or_null("World/FogGroup/YSortGroup/Entities")).is_not_null()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# #71: Tilemap z-filter — FloorTiles only renders floor level 0
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
func test_tile_renderer_skips_nonzero_z() -> void:
|
||||
# #71: Tiles with z != 0 must be filtered out by update_tiles().
|
||||
var scene := load("res://scenes/main.tscn")
|
||||
_instance = scene.instantiate()
|
||||
auto_free(_instance)
|
||||
add_child(_instance)
|
||||
|
||||
var tile_renderer: TileMapLayer = _instance.get_node("World/FogGroup/FloorTiles")
|
||||
assert_that(tile_renderer).is_not_null()
|
||||
|
||||
# Feed tiles at z=0 and z=1
|
||||
var tiles: Array = [
|
||||
{"x": 0, "y": 0, "z": 0, "type": "floor"},
|
||||
{"x": 1, "y": 0, "z": 1, "type": "floor"},
|
||||
{"x": 2, "y": 0, "z": 0, "type": "wall"},
|
||||
{"x": 3, "y": 0, "z": 2, "type": "door"},
|
||||
]
|
||||
tile_renderer.update_tiles(tiles)
|
||||
|
||||
# z=0 tiles should be present
|
||||
assert_that(tile_renderer.get_cell_source_id(Vector2i(0, 0))).is_not_equal(-1)
|
||||
assert_that(tile_renderer.get_cell_source_id(Vector2i(2, 0))).is_not_equal(-1)
|
||||
# z=1 and z=2 tiles should NOT be present (-1 = no cell)
|
||||
assert_that(tile_renderer.get_cell_source_id(Vector2i(1, 0))).is_equal(-1)
|
||||
assert_that(tile_renderer.get_cell_source_id(Vector2i(3, 0))).is_equal(-1)
|
||||
|
||||
Reference in New Issue
Block a user