feat(props): integrate Blender GLB props into movement map
- Replace primitive _crate(), _barrel(), _pillar() with GLB scene instances - Add 7 prop preloads: crate, barrel, pillar, ramp, weapon_pickup, health_pack, ammo_pack - Add _load_props() and _place_prop() helpers with null guards - Add pickup placements: weapon (center), health (east/west), ammo (center/NW/SE) - Props load at runtime via load() - appear once Godot editor imports the GLB files - Null guard prevents crashes in headless mode before import
This commit is contained in:
+46
-21
@@ -21,6 +21,7 @@ var _debug_ui_panel: PanelContainer
|
||||
|
||||
func _ready() -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
_load_props()
|
||||
_build_materials()
|
||||
_build_geometry()
|
||||
_build_hud()
|
||||
@@ -102,6 +103,40 @@ func _ramp_static(pos: Vector3, size: Vector3, rot_deg: Vector3, color: Color, n
|
||||
return body
|
||||
|
||||
|
||||
# ── GLB Prop Scenes (generated via Blender headless) ──────────────────────────
|
||||
var prop_crate: PackedScene
|
||||
var prop_barrel: PackedScene
|
||||
var prop_pillar: PackedScene
|
||||
var prop_ramp: PackedScene
|
||||
var prop_weapon_pickup: PackedScene
|
||||
var prop_health_pack: PackedScene
|
||||
var prop_ammo_pack: PackedScene
|
||||
|
||||
func _load_props() -> void:
|
||||
prop_crate = load("res://assets/props/crate.glb")
|
||||
prop_barrel = load("res://assets/props/barrel.glb")
|
||||
prop_pillar = load("res://assets/props/pillar.glb")
|
||||
prop_ramp = load("res://assets/props/ramp.glb")
|
||||
prop_weapon_pickup = load("res://assets/props/weapon_pickup.glb")
|
||||
prop_health_pack = load("res://assets/props/health_pack.glb")
|
||||
prop_ammo_pack = load("res://assets/props/ammo_pack.glb")
|
||||
# Log which props loaded
|
||||
if prop_crate: print("Prop loaded: crate")
|
||||
else: print("WARN: crate.glb not imported yet - run Godot editor once to import")
|
||||
if prop_barrel: print("Prop loaded: barrel")
|
||||
if prop_pillar: print("Prop loaded: pillar")
|
||||
|
||||
|
||||
func _place_prop(scene: PackedScene, pos: Vector3, name: String = "") -> void:
|
||||
if not scene:
|
||||
return # Skip if not imported yet
|
||||
var inst = scene.instantiate()
|
||||
if inst:
|
||||
inst.name = name if not name.is_empty() else scene.resource_path.get_file().get_basename()
|
||||
inst.position = pos
|
||||
add_child(inst)
|
||||
|
||||
|
||||
# ── Color Palette ─────────────────────────────────────────────────────────────
|
||||
|
||||
var C_FLOOR: Color = Color(0.22, 0.22, 0.25)
|
||||
@@ -422,11 +457,11 @@ func _build_cover_system() -> void:
|
||||
|
||||
|
||||
func _crate(pos: Vector3) -> void:
|
||||
_box_static(pos, Vector3(1.2, 1.2, 1.2), C_CRATE, "Crate")
|
||||
_place_prop(prop_crate, pos, "Crate")
|
||||
|
||||
|
||||
func _pillar(pos: Vector3) -> void:
|
||||
_box_static(pos, Vector3(0.8, 7.0, 0.8), C_METAL, "Pillar")
|
||||
_place_prop(prop_pillar, pos, "Pillar")
|
||||
|
||||
|
||||
# ── Speed Corridor ────────────────────────────────────────────────────────────
|
||||
@@ -538,6 +573,14 @@ func _build_decorations() -> void:
|
||||
_barrel(Vector3(-25, 0.5, 25))
|
||||
_barrel(Vector3(25, 0.5, -25))
|
||||
|
||||
# Pickup props (GLB)
|
||||
_place_prop(prop_weapon_pickup, Vector3(0, 0.05, -25), "WeaponPickup_Center")
|
||||
_place_prop(prop_health_pack, Vector3(-20, 0.05, 0), "HealthPack_West")
|
||||
_place_prop(prop_health_pack, Vector3(20, 0.05, 0), "HealthPack_East")
|
||||
_place_prop(prop_ammo_pack, Vector3(0, 0.05, 25), "AmmoPack_Center")
|
||||
_place_prop(prop_ammo_pack, Vector3(-35, 0.05, -35), "AmmoPack_NW")
|
||||
_place_prop(prop_ammo_pack, Vector3(35, 0.05, 35), "AmmoPack_SE")
|
||||
|
||||
# Spawn area lights
|
||||
_spawn_area_light(Vector3(-42, 3, -42), C_ACCENT_WARM, 6.0, 0.8)
|
||||
_spawn_area_light(Vector3(-42, 3, 42), C_ACCENT_WARM, 6.0, 0.8)
|
||||
@@ -548,25 +591,7 @@ func _build_decorations() -> void:
|
||||
|
||||
|
||||
func _barrel(pos: Vector3) -> void:
|
||||
var body := StaticBody3D.new()
|
||||
body.name = "Barrel"
|
||||
body.position = pos
|
||||
add_child(body)
|
||||
var mesh := MeshInstance3D.new()
|
||||
mesh.mesh = CylinderMesh.new()
|
||||
mesh.mesh.top_radius = 0.4
|
||||
mesh.mesh.bottom_radius = 0.4
|
||||
mesh.mesh.height = 1.0
|
||||
var mat := StandardMaterial3D.new()
|
||||
mat.albedo_color = Color(0.50, 0.45, 0.30)
|
||||
mat.roughness = 0.6
|
||||
mesh.mesh.surface_set_material(0, mat)
|
||||
body.add_child(mesh)
|
||||
var shape := CollisionShape3D.new()
|
||||
shape.shape = CylinderShape3D.new()
|
||||
shape.shape.radius = 0.4
|
||||
shape.shape.height = 1.0
|
||||
body.add_child(shape)
|
||||
_place_prop(prop_barrel, pos, "Barrel")
|
||||
|
||||
|
||||
func _spawn_area_light(pos: Vector3, color: Color, radius: float, energy: float) -> void:
|
||||
|
||||
Reference in New Issue
Block a user