Skip to content

feat(fp): solid player car that shoves traffic and knocks props over - #16

Merged
KunalSiyag merged 1 commit into
mainfrom
fp/car-collision
Oct 21, 2026
Merged

KunalSiyag merged 1 commit into
mainfrom
fp/car-collision

Conversation

@KunalSiyag

Copy link
Copy Markdown
Owner

What

The player's car is solid now (user feedback: objects were not rigid and the car stopped dead on anything it touched).

  • Rigid car body (scripts/fp/drive/car_body.gd, on the new shared scripts/fp/obb2d.gd and scripts/fp/body_contacts.gd). The car moves in short substeps and resolves its deepest contacts with walls, posts, water edges, other vehicles and street props. It bounces a little off a head-on hit, scrapes along a wall it meets at a glance and spins when hit off-centre. drive_model.gd gains a knock spin damped by the tyres; the old stop-dead crash() is gone.
  • Shoved traffic (scripts/fp/traffic/shoves.gd). Cars the player hits slide and spin off with the momentum they got and stop against walls and other cars. A lane car brakes, waits (longer the harder it was hit), then steers back onto its lane; lane traffic stops for it meanwhile. A parked car knocked out of its slot stays where it stops and is towed back after 30 s out of sight. TrafficFeature.bodies_near / bump_car connect the two bodies.
  • Knockable props (new integration feature scripts/fp/props/, flag props). Bins, benches, planters, mailboxes, bike racks and parking meters hit hard enough fall: the batched prop is hidden, its collider marked down, and a mesh copy tumbles (tumble.gd), rolls over its edges and lies on a face (long props over a long side). Lamps, trees, bollards, hydrants and signs hold like walls. Fallen props stand up again after 20 s out of sight, at most 24 lie fallen at once.
  • Sounds: new bus signals car_impact and prop_knocked; the audio feature plays crash_light / crash_heavy (louder with the closing speed) and prop_clatter / prop_clang, synthesized by tools/audio/synth_fp_sfx.py (4 WAVs, small).
  • Seams: StreetDressing slots, set_down, kit_of; CityView.street_placements / set_street_prop_down / street_kit; CollisionWorld.invalidate; blockers_near lists only stopped vehicles while driving.

Docs: docs/fp/ARCHITECTURE.md (E, I and driving rows, new props row, seams), docs/fp/S0-foundation.md (bus signals), docs/fp/slices/I-audio.md, README controls, regenerated docs/api/.

Tests

  • fp_drive_test: crash reported on the bus, glancing wall scrape, shoving a lane car that returns to its lane.
  • fp_traffic_test: glance, shove and parked-car paths of shoves.gd.
  • fp_props_test (new): tumble comes to rest on a face (long props on a long side), listing, hold vs knock thresholds, rest, kicks, respawn, tile rebuild, the car hitting props, photo shot, teardown.
  • fp_audio_test: impact sounds.

Local: pre-commit run --all-files PASS, python tools/checks/run_all.py PASS, tools/gate.sh full PASS, photo tour (tools/gate.sh render --only fp_photo) checked by eye.

The player's car is now a rigid box on the ground plane (car_body.gd).
Each frame it moves by the handling model's velocity in short substeps
and resolves its deepest contacts: CollisionWorld's walls, posts and
water edges (body_contacts.gd), other vehicles and street props. A
closing contact pushes it out and gives an impulse at the contact
point, so it bounces a little off what it hits head-on, scrapes along a
wall it meets at a glance and spins when hit off-centre. drive_model.gd
gains a spin the tyres damp out, and its stop-dead crash() is gone.
obb2d.gd holds the oriented-box and circle contacts both bodies use.

Cars it hits are knocked (traffic/shoves.gd): they slide and spin off
with the momentum they were given, braking on their tyres, and stop
against walls and other cars. A lane car brakes hard and waits, longer
the harder it was hit, then steers back onto its lane and drives on;
lane traffic stops for it meanwhile. A parked car knocked out of its
slot rides up curbs, stays where it stops and is towed back once it has
stood 30 s out of sight. TrafficFeature gains bodies_near and bump_car,
and blockers_near lists only stopped vehicles while the player drives.

Bins, benches, planters, mailboxes, bike racks and parking meters hit
hard enough for their kind fall over (props feature, behind the "props"
flag). CityView hides the batched prop and marks its collider down, and
a copy of its meshes tumbles off (tumble.gd), rolls over its edges and
comes to rest on a face, where it can be hit again; long props fall
over a long side. Lamps, trees, bollards, hydrants and signs hold like
walls. A fallen prop stands up again after 20 s out of sight.
StreetDressing gains slots, set_down and kit_of, and
CollisionWorld.invalidate drops a tile's cached colliders.

GameBus gains car_impact and prop_knocked. The audio feature plays a
light or heavy crash, louder with the closing speed, and a clatter or a
clang for each prop knocked over, synthesized by
tools/audio/synth_fp_sfx.py.

fp_drive_test covers the crash report, a glancing scrape and shoving a
lane car that then finds its lane again; fp_traffic_test the glance,
shove and parked-car paths of shoves.gd; fp_props_test the tumble,
thresholds, knocks, rest, kicks, respawn, rebuild, the car hitting
props and a photo shot; fp_audio_test the impact sounds.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Automated review

No new findings on the 49 changed files (gdlint, complexity, TODO policy, dead code).

Run python3 tools/checks/run_all.py locally for the full set of checks.

@KunalSiyag
KunalSiyag merged commit 3c391a1 into main Oct 21, 2026
8 checks passed
@KunalSiyag
KunalSiyag deleted the fp/car-collision branch October 21, 2026 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant