feat: parked cars across the city (Kenney Car Kit, CC0)
Streets are now populated: seeded parking lanes hug the curbs of every N-S street with sedans, taxis, vans, SUVs, hatchbacks, delivery trucks and the occasional police car (~100+ across the city). - Wheels attach at the models' wheel-socket empties at spawn - Metal-tagged box colliders: cars are cover that sounds like cover - Toonified + darkened base tint (kit albedo clips under the map light) with per-car hue jitter for varied paint jobs - Slight rotation jitter so parking reads natural, not stamped Verified via street capture (colored cars parked down the avenue, no clipping/glow); movement 11/11, smoke 0 failures, acoustics ALL PASSED. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
04d91dea31
commit
56db9eea59
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
Car Kit (3.1)
|
||||||
|
|
||||||
|
Created/distributed by Kenney (www.kenney.nl)
|
||||||
|
Creation date: 02-04-2026 14:03
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
License: (Creative Commons Zero, CC0)
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
You can use this content for personal, educational, and commercial purposes.
|
||||||
|
|
||||||
|
Support by crediting 'Kenney' or 'www.kenney.nl' (this is not a requirement)
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
• Website : www.kenney.nl
|
||||||
|
• Donate : www.kenney.nl/donate
|
||||||
|
|
||||||
|
• Patreon : patreon.com/kenney
|
||||||
|
|
||||||
|
Follow on social media for updates:
|
||||||
|
|
||||||
|
• Twitter: twitter.com/KenneyNL
|
||||||
|
• BlueSky: kenney.bsky.social
|
||||||
|
• Instagram: instagram.com/kenney_nl
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -270,6 +270,7 @@ func _build_geometry() -> void:
|
|||||||
_build_rail_line()
|
_build_rail_line()
|
||||||
_build_streets()
|
_build_streets()
|
||||||
_build_avenues()
|
_build_avenues()
|
||||||
|
_build_parked_cars()
|
||||||
|
|
||||||
if _spawn_points.is_empty():
|
if _spawn_points.is_empty():
|
||||||
_spawn_points.append(Vector3(0, 2, 0))
|
_spawn_points.append(Vector3(0, 2, 0))
|
||||||
@@ -665,6 +666,59 @@ func _build_avenues() -> void:
|
|||||||
Vector3(x, 0, z2), 0.0 if side > 0 else 180.0, lamp_scale)
|
Vector3(x, 0, z2), 0.0 if side > 0 else 180.0, lamp_scale)
|
||||||
|
|
||||||
|
|
||||||
|
# ── Parked cars (Kenney Car Kit) ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
const CAR_KEYS := ["sedan", "sedan", "taxi", "van", "suv", "hatchback-sports",
|
||||||
|
"delivery", "sedan-sports", "police"]
|
||||||
|
const CAR_SCALE := 1.8
|
||||||
|
|
||||||
|
## A parked car: metal-tagged collider, kit body, wheels attached to the
|
||||||
|
## model's wheel sockets, slight per-car tint.
|
||||||
|
func _parked_car(pos: Vector3, yaw_deg: float) -> void:
|
||||||
|
var key: String = CAR_KEYS[_rng.randi() % CAR_KEYS.size()]
|
||||||
|
var body := StaticBody3D.new()
|
||||||
|
body.name = "Car_%d" % _rng.randi()
|
||||||
|
body.set_meta("acoustic_material", "metal")
|
||||||
|
add_child(body)
|
||||||
|
body.global_position = pos
|
||||||
|
body.rotation_degrees.y = yaw_deg + _rng.randf_range(-3.0, 3.0)
|
||||||
|
var shape := CollisionShape3D.new()
|
||||||
|
var bs := BoxShape3D.new()
|
||||||
|
bs.size = Vector3(2.8, 2.6, 5.0)
|
||||||
|
shape.shape = bs
|
||||||
|
shape.position = Vector3(0, 1.3, 0)
|
||||||
|
body.add_child(shape)
|
||||||
|
|
||||||
|
var inst: Node3D = _kit_scene_at("res://assets/props/cars/" + key + ".glb").instantiate()
|
||||||
|
inst.scale = Vector3.ONE * CAR_SCALE
|
||||||
|
inst.position.y = 0.55 # wheel contact at ground after scaling
|
||||||
|
body.add_child(inst)
|
||||||
|
var wheel_scene := _kit_scene_at("res://assets/props/cars/wheel-default.glb")
|
||||||
|
for n in inst.find_children("wheel*", "Node3D", true, false):
|
||||||
|
if n.get_child_count() == 0 and not (n is MeshInstance3D):
|
||||||
|
var wheel: Node3D = wheel_scene.instantiate()
|
||||||
|
n.add_child(wheel)
|
||||||
|
LevelMaterials.apply_toon_recursive(inst, 0.0)
|
||||||
|
# Darken under the map lighting (kit albedo clips) + per-car hue
|
||||||
|
_tint_recursive(inst, Color(0.62, 0.62, 0.66) * Color(1, 1, 1).lerp(Color.from_hsv(_rng.randf(), 0.6, 1.0), 0.35))
|
||||||
|
|
||||||
|
|
||||||
|
## Seeded parking lanes hugging the curbs of the N-S streets.
|
||||||
|
func _build_parked_cars() -> void:
|
||||||
|
for x in _street_lines():
|
||||||
|
for row in GRID:
|
||||||
|
_rng.seed = hash(Vector2i(int(x), row)) + 913
|
||||||
|
if _rng.randf() < 0.45:
|
||||||
|
continue
|
||||||
|
var z_base := (float(row) - float(GRID - 1) * 0.5) * PITCH
|
||||||
|
var cars := 1 + _rng.randi() % 3
|
||||||
|
for i in cars:
|
||||||
|
var side := 1.0 if _rng.randi() % 2 == 0 else -1.0
|
||||||
|
var cx := x + side * (ROAD_W * 0.5 - 1.8)
|
||||||
|
var cz := z_base + _rng.randf_range(-18.0, 18.0)
|
||||||
|
_parked_car(Vector3(cx, 0.02, cz), 0.0 if _rng.randi() % 2 == 0 else 180.0)
|
||||||
|
|
||||||
|
|
||||||
func _kit_prop_path(path: String, pos: Vector3, yaw_deg: float, scale_f: float) -> void:
|
func _kit_prop_path(path: String, pos: Vector3, yaw_deg: float, scale_f: float) -> void:
|
||||||
var inst: Node3D = _kit_scene_at(path).instantiate()
|
var inst: Node3D = _kit_scene_at(path).instantiate()
|
||||||
inst.scale = Vector3.ONE * scale_f
|
inst.scale = Vector3.ONE * scale_f
|
||||||
|
|||||||
Reference in New Issue
Block a user