ShitboxInfinity/tests/probe.gd
type-two d9b69e688e Brisbane: Queen Street Mall crash-run level from OpenStreetMap
tools/build_level_osm.py extrudes OSM buildings (-col), lays road strips,
Spawn + RacePath empties; osm_level_args.py computes a building-clear spawn on
a named way and race-loop corners from street intersection nodes. game.gd
builds Path3D from GLB RacePath empties, sanitizes spawn bases, and places
bodies BEFORE add_child. Three real bugs fixed: mall canopies (building=roof)
extruded as solid blocks, underground busways rendered at surface, and the
km-wide ground trimesh breaking suspension raycasts (now -convcol). Cars get
continuous_cd for thin building shells. tests/probe.gd is the physics
raycast debugger that found it.

Data (c) OpenStreetMap contributors, ODbL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 23:33:51 +10:00

64 lines
2.7 KiB
GDScript

extends SceneTree
## Physics probe: boot a level headless, raycast forward from the spawn to see
## which colliders exist ahead. Usage:
## Godot --headless --path . --script tests/probe.gd -- level=queen_st_mall
func _initialize() -> void:
_run()
func _run() -> void:
var opts := {}
for a in OS.get_cmdline_user_args():
var kv := a.split("=")
if kv.size() == 2:
opts[kv[0]] = kv[1]
Game.car_path = Registry.cars().values()[0]
var levels := Registry.levels()
Game.level_path = levels.get(opts.get("level", ""), levels.values()[0])
Game.mode = "cruise"
var game: Game = (load("res://src/game.tscn") as PackedScene).instantiate()
root.add_child(game)
await process_frame
var sp := game.get_child(0).find_child("Spawn", true, false)
print("Spawn node: ", sp, " class=", sp.get_class() if sp else "nil",
" global=", (sp as Node3D).global_position if sp is Node3D else Vector3.INF)
print("car right after ready: ", game.car.global_position)
for i in 10:
var p: Vector3 = game.car.global_position
print("tick %d: y=%.3f vy=%.2f" % [i, p.y, game.car.linear_velocity.y])
await physics_frame
var space := game.car.get_world_3d().direct_space_state
var from := game.car.global_position + Vector3.UP * 0.5
var fwd := -game.car.global_basis.z
print("spawn at ", game.car.global_position, " facing ", fwd)
for dist in [5.0, 200.0]:
var q := PhysicsRayQueryParameters3D.create(from, from + fwd * dist)
q.exclude = [game.car.get_rid()]
var hit := space.intersect_ray(q)
if hit:
print("ray %dm: hit %s at %.1fm" % [dist, hit.collider.get_parent().name if hit.collider.get_parent() else hit.collider.name, from.distance_to(hit.position)])
else:
print("ray %dm: clear" % dist)
for off in [Vector3.ZERO, Vector3(20, 0, -18)]:
var down := PhysicsRayQueryParameters3D.create(from + off, from + off + Vector3.DOWN * 100.0)
down.exclude = [game.car.get_rid()]
var dh := space.intersect_ray(down)
if dh:
print("down@%s: hit %s at y=%.2f" % [off, dh.collider.get_parent().name if dh.collider.get_parent() else dh.collider.name, dh.position.y])
else:
print("down@%s: NOTHING within 100m" % off)
var bodies := 0
for n in game.find_children("*", "StaticBody3D", true, false):
bodies += 1
print("static bodies in level: ", bodies)
var car := game.car
print("basis.y = ", car.global_basis.y, " basis.z = ", car.global_basis.z)
for w: Node3D in car.wheels:
var wf := w.global_position
var q2 := PhysicsRayQueryParameters3D.create(wf, wf - car.global_basis.y * Car.REST)
q2.exclude = [car.get_rid()]
var h2 := space.intersect_ray(q2)
print("wheel %s from y=%.2f: %s" % [w.name, wf.y,
("hit %s y=%.2f" % [h2.collider.get_parent().name, h2.position.y]) if h2 else "MISS"])
quit(0)