class_name ArenaBoundary extends StaticBody3D # The standard arena play volume (inner faces of the enclosure). Every arena # instances objects/arena_boundary.tscn so all arenas share one size; code # that needs field dimensions derives them from these constants rather than # restating numbers. const INNER_HALF_X := 12.0 const INNER_HALF_Z := 18.0 const INNER_HEIGHT := 12.0 # Goal-centre distance from arena centre; the end walls sit 1 m behind, so a # ball pinned against them still overlaps the goal sensor. const GOAL_LINE_Z := 17.0 @onready var _wall_pos_x: MeshInstance3D = $WallPosXMesh @onready var _wall_neg_x: MeshInstance3D = $WallNegXMesh @onready var _wall_pos_z: MeshInstance3D = $WallPosZMesh @onready var _wall_neg_z: MeshInstance3D = $WallNegZMesh @onready var _ceiling: MeshInstance3D = $CeilingMesh func _process(_delta: float) -> void: # The translucent field material tints everything behind it, so any face # the camera has crossed to the outside of is hidden entirely — looking # into the arena from outside stays clear, while faces seen from inside # keep their tint. Collision is untouched; only the meshes toggle. var camera := get_viewport().get_camera_3d() if camera == null: return # headless (RL/CI) has no camera var p := to_local(camera.global_position) _wall_pos_x.visible = p.x < INNER_HALF_X _wall_neg_x.visible = p.x > -INNER_HALF_X _wall_pos_z.visible = p.z < INNER_HALF_Z _wall_neg_z.visible = p.z > -INNER_HALF_Z _ceiling.visible = p.y < INNER_HEIGHT