fix(arena): contain goal pockets

This commit is contained in:
Josh Creek
2026-08-08 15:03:46 +01:00
parent 341a67f6da
commit d229bccd19
+29
View File
@@ -14,6 +14,14 @@ signal goal_scored(team: int)
# wall is thick or it pokes out the back of the arena. ArenaBoundary cuts the
# matching aperture in the hull (see its GOAL_APERTURE_* constants).
const POCKET_DEPTH := ArenaBoundary.SURFACE_THICKNESS
# Physical back wall for the goal pocket. The arena end wall has a real hole
# at the scoring aperture; without this, the visual-only net lets ships and
# the ball leave the enclosure after crossing the sensor. A small overlap
# into the surrounding end-wall panels closes numerical seams at the rim.
const BACKSTOP_THICKNESS := 0.4
const BACKSTOP_EDGE_OVERLAP := 0.25
const ARENA_COLLISION_LAYER := 1 << 2
const ARENA_COLLISION_MASK := (1 << 0) | (1 << 1)
# Clearance between the mouth and the pocket shell, so the pocket's side walls
# stay hidden behind the hull rather than showing at the aperture edge.
const POCKET_CLEARANCE := 0.2
@@ -32,6 +40,7 @@ var _goal_burst: GPUParticles3D
func _ready():
# Group lets AI controllers and game modes discover goals
add_to_group("goal")
_build_backstop()
# Everything below _on_body_entered is decoration, and training spawns
# headless arenas that never render it. The sensor is unaffected.
if DisplayServer.get_name() != "headless":
@@ -46,6 +55,26 @@ func _on_body_entered(body):
goal_scored.emit(team)
func _build_backstop() -> void:
var mouth := ($CollisionShape3D.shape as BoxShape3D).size
var body := StaticBody3D.new()
body.name = "PocketBackstop"
body.collision_layer = ARENA_COLLISION_LAYER
body.collision_mask = ARENA_COLLISION_MASK
var collision := CollisionShape3D.new()
collision.name = "CollisionShape3D"
var box := BoxShape3D.new()
box.size = Vector3(
mouth.x + BACKSTOP_EDGE_OVERLAP * 2.0,
mouth.y + BACKSTOP_EDGE_OVERLAP * 2.0,
BACKSTOP_THICKNESS
)
collision.shape = box
collision.position = Vector3(0.0, 0.0, POCKET_DEPTH)
body.add_child(collision)
add_child(body)
# --- visuals -----------------------------------------------------------------
# Cosmetic only. The mouth is measured off the sensor's own collision shape, so
# the frame can never drift from the volume that actually scores.