fix(client): address PR #36 re-review — 7 items from Hoshe + Tyre

Warnings: facing indicator tests use Godot-normalized rotation range
(-PI, PI] instead of raw addition (SW/W/NW in test_rendering,
West in test_client_p3). Suggestions: cache font in world_radial
_draw(), fix docstring on deactivate_insert() trigger, document
tile-coordinate system on _eval_player_near (D-066), add public
reset_facing_state() to InputMapper (D-030 testability).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-18 18:28:37 +01:00
co-authored by Claude Opus 4.6
parent 919ef39cbd
commit 503644beb1
6 changed files with 21 additions and 13 deletions
+7
View File
@@ -120,6 +120,13 @@ func flush_queue() -> Array[Dictionary]:
return queue
## Reset facing state to default (North). Use in tests per D-030 testability.
func reset_facing_state() -> void:
facing_angle = -PI / 2.0
facing_octant = "North"
_last_sent_octant = "North"
# D-054: Compute facing angle from mouse position relative to player screen position.
# Uses viewport canvas transform to convert world coords to screen coords.
# Intentional coupling: reads GameState.player_position directly — InputMapper is an
@@ -160,6 +160,9 @@ func _evaluate_condition(cond: Dictionary) -> bool:
return false
## x/y and radius are in tile coordinates (matching GameState.player_position),
## not pixels. D-066 dual-scale: YAML authors write tile coords, pixel conversion
## happens only at render time.
func _eval_player_near(cond: Dictionary) -> bool:
var tx: float = float(cond.get("x", 0))
var ty: float = float(cond.get("y", 0))
+1 -1
View File
@@ -267,7 +267,7 @@ func test_facing_indicator_rotation_matches_input_mapper_angle() -> void:
-PI / 2.0: 0.0, # North
0.0: PI / 2.0, # East
PI / 2.0: PI, # South
PI: 3.0 * PI / 2.0, # West
PI: -PI / 2.0, # West (3PI/2 normalized to -PI/2 by Godot)
}
for angle in angles:
InputMapper.facing_angle = angle
+1 -4
View File
@@ -116,7 +116,4 @@ func test_wasd_strafe_right_facing_west() -> void:
func after_test() -> void:
# Reset facing to default
InputMapper.facing_angle = -PI / 2.0
InputMapper.facing_octant = "North"
InputMapper._last_sent_octant = "North"
InputMapper.reset_facing_state()
+3 -3
View File
@@ -310,9 +310,9 @@ func test_entity_renderer_facing_indicator_rotation_accuracy() -> void:
0.0: PI / 2.0, # East
PI / 4.0: 3.0 * PI / 4.0, # Southeast
PI / 2.0: PI, # South
3.0 * PI / 4.0: 5.0 * PI / 4.0, # Southwest
PI: 3.0 * PI / 2.0, # West
-3.0 * PI / 4.0: 7.0 * PI / 4.0, # Northwest (note: -PI/2 wraps)
3.0 * PI / 4.0: -3.0 * PI / 4.0, # Southwest (Godot normalizes to (-PI, PI])
PI: -PI / 2.0, # West (3PI/2 normalized to -PI/2)
-3.0 * PI / 4.0: -PI / 4.0, # Northwest (-3PI/4 + PI/2 = -PI/4)
}
renderer.update_entities(_test_entities_v2)
var player_node = renderer.entity_nodes[1]
+6 -5
View File
@@ -5,8 +5,8 @@ extends Control
## Renders on InsertOverlay (CanvasLayer 10).
## Drag-release for power users, click-click for newcomers.
## Insert spoke sends PauseSimulation on activate (#518/D-058).
## Selecting any other spoke (or re-opening the radial) calls deactivate_insert()
## which sends ResumeSimulation. Pause/resume are idempotent.
## Selecting any non-Insert spoke, cancelling, or pressing Escape calls
## deactivate_insert() which sends ResumeSimulation. Pause/resume are idempotent.
signal spoke_selected(spoke_name: String)
@@ -37,6 +37,7 @@ var _origin: Vector2 = Vector2.ZERO
var _hovered_spoke: int = Spoke.NONE
var _drag_mode: bool = false
var _insert_active: bool = false
var _cached_font: Font = null
func _ready() -> void:
@@ -45,6 +46,7 @@ func _ready() -> void:
size = custom_minimum_size
visible = false
mouse_filter = Control.MOUSE_FILTER_STOP
_cached_font = get_theme_default_font()
func _input(event: InputEvent) -> void:
@@ -192,10 +194,9 @@ func _draw() -> void:
# Label
var label: String = SPOKE_NAMES.get(spoke, "")
var font := get_theme_default_font()
var text_size := font.get_string_size(label, HORIZONTAL_ALIGNMENT_CENTER, -1, 11)
var text_size := _cached_font.get_string_size(label, HORIZONTAL_ALIGNMENT_CENTER, -1, 11)
var label_pos := icon_center + Vector2(-text_size.x / 2.0, ICON_SIZE + 14.0)
draw_string(font, label_pos, label, HORIZONTAL_ALIGNMENT_LEFT, -1, 11, color)
draw_string(_cached_font, label_pos, label, HORIZONTAL_ALIGNMENT_LEFT, -1, 11, color)
func _draw_spoke_icon(spoke: int, center: Vector2, color: Color) -> void: