feat(rendering): GameplayRenderer base class — occlusion for all renderers (D-170)

New GameplayRenderer extends Node2D with built-in occlusion support.
Subclasses override _gameplay_process() and _gameplay_draw() instead
of _process() and _draw() — these are skipped when a fullscreen
implant app covers gameplay.

Migrated all 5 gameplay renderers:
- CursorRenderer: hover detection + bracket drawing paused
- EntityRenderer: position lerping paused
- FogEntities: fog dot rendering paused
- SoundIndicatorRenderer: directional arrows paused
- WorldRenderer: tile/fog/entity updates paused

No more manual occlusion wiring — the base class handles everything.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 11:51:30 +02:00
co-authored by Claude Opus 4.6
parent a01f7c9cfb
commit 34a21d4cd0
6 changed files with 70 additions and 23 deletions
+3 -9
View File
@@ -1,4 +1,4 @@
extends Node2D
extends GameplayRenderer
# World renderer — manages all visual representation from GameState
# Attached to the World node in main.tscn
@@ -14,7 +14,6 @@ extends Node2D
# FogOverlay (Node2D) — z:900 fog shader (OUTSIDE FogGroup)
var _last_tick: int = -1
var _occluded: bool = false # D-170: skip rendering when fullscreen implant app is covering us
@onready var tile_renderer = $FogGroup/FloorTiles
@onready var fog_renderer = $FogOverlay
@@ -22,19 +21,14 @@ var _occluded: bool = false # D-170: skip rendering when fullscreen implant app
@onready var sound_indicator_renderer = $SoundIndicators # #126 D-018 medium-range indicators
func _ready() -> void:
HudGroups.gameplay_occluded.connect(_on_gameplay_occluded)
func _renderer_ready() -> void:
print("WorldRenderer: Initialized (D-049 z-stack)")
func _on_gameplay_occluded(occluded: bool) -> void:
_occluded = occluded
# Called each frame to update visuals from game state.
# Uses tick-based invalidation — re-renders all layers when a new snapshot arrives.
func update_from_state() -> void:
if _occluded:
if gameplay_occluded:
return # D-170: skip rendering while fullscreen implant app is active
var tick := GameState.current_tick
if tick == _last_tick: