feat: Add a multiplayer-synchronized portal door with visual elements, player detection, and dynamic color.

This commit is contained in:
Yogi Wiguna
2026-03-02 16:49:40 +08:00
parent c16a0043bc
commit e6dceaf173
2 changed files with 53 additions and 6 deletions
+16 -1
View File
@@ -10,6 +10,16 @@ albedo_color = Color(0.1, 0.5, 0.8, 1)
metallic = 0.8 metallic = 0.8
roughness = 0.2 roughness = 0.2
[sub_resource type="PlaneMesh" id="PlaneMesh_ground"]
size = Vector2(1.0, 1.0)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ground"]
transparency = 1
albedo_color = Color(1, 1, 1, 0.4)
emission_enabled = true
emission = Color(1, 1, 1, 1)
emission_energy_multiplier = 1.0
[sub_resource type="PlaneMesh" id="PlaneMesh_vortex"] [sub_resource type="PlaneMesh" id="PlaneMesh_vortex"]
size = Vector2(1.4, 2.1) size = Vector2(1.4, 2.1)
@@ -18,7 +28,7 @@ transparency = 1
albedo_color = Color(0.0, 0.6, 1.0, 0.4) albedo_color = Color(0.0, 0.6, 1.0, 0.4)
emission_enabled = true emission_enabled = true
emission = Color(0.0, 0.4, 1.0, 1) emission = Color(0.0, 0.4, 1.0, 1)
emission_energy_multiplier = 2.0 emission_energy_multiplier = 5.0
[sub_resource type="BoxShape3D" id="BoxShape3D_trigger"] [sub_resource type="BoxShape3D" id="BoxShape3D_trigger"]
size = Vector3(1.4, 2.1, 0.8) size = Vector3(1.4, 2.1, 0.8)
@@ -63,6 +73,11 @@ transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.1
mesh = SubResource("PlaneMesh_vortex") mesh = SubResource("PlaneMesh_vortex")
surface_material_override/0 = SubResource("StandardMaterial3D_vortex") surface_material_override/0 = SubResource("StandardMaterial3D_vortex")
[node name="GroundIndicator" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0.4)
mesh = SubResource("PlaneMesh_ground")
surface_material_override/0 = SubResource("StandardMaterial3D_ground")
[node name="Area3D" type="Area3D" parent="."] [node name="Area3D" type="Area3D" parent="."]
collision_layer = 0 collision_layer = 0
collision_mask = 2 collision_mask = 2
+37 -5
View File
@@ -28,6 +28,9 @@ func _ready():
# Visual feedback: indicate door is active # Visual feedback: indicate door is active
_update_visuals() _update_visuals()
# Adjust GroundIndicator position based on spawn_offset metadata
_adjust_indicator_position()
func _on_body_entered(body: Node3D): func _on_body_entered(body: Node3D):
if not is_active: return if not is_active: return
@@ -76,6 +79,15 @@ func _update_visuals():
var mat = frame.get_surface_override_material(0) var mat = frame.get_surface_override_material(0)
if mat: if mat:
mat.albedo_color = portal_color.lerp(Color.BLACK, 0.4) mat.albedo_color = portal_color.lerp(Color.BLACK, 0.4)
var ground = get_node_or_null("GroundIndicator")
if ground:
var mat = ground.get_surface_override_material(0)
if mat:
mat.albedo_color = portal_color
mat.albedo_color.a = 0.4
mat.emission = portal_color
mat.emission_energy_multiplier = 2.0
func _initialize_unique_materials(): func _initialize_unique_materials():
var vortex = get_node_or_null("Vortex") var vortex = get_node_or_null("Vortex")
@@ -96,9 +108,29 @@ func _initialize_unique_materials():
if mat: if mat:
frame.set_surface_override_material(0, mat.duplicate()) frame.set_surface_override_material(0, mat.duplicate())
var ground = get_node_or_null("GroundIndicator")
if ground:
var mat = ground.get_surface_override_material(0)
if not mat:
mat = ground.mesh.surface_get_material(0)
if mat:
ground.set_surface_override_material(0, mat.duplicate())
func get_teleport_target_position() -> Vector2i: func _adjust_indicator_position():
# This function will be called by the manager to determine WHERE the player spawns # This uses the spawn_offset metadata set by PortalModeManager
# usually just outside the target door's position. # to push the ground indicator "into" the room.
# For now, let's just return a placeholder that the manager will override. if not has_meta("spawn_offset"): return
return Vector2i.ZERO
var ground = get_node_or_null("GroundIndicator")
if not ground: return
var offset_2d = get_meta("spawn_offset") # Vector2i
var offset_3d = Vector3(offset_2d.x, 0, offset_2d.y)
# Convert the global direction (into the room) to local coordinates
var local_dir = to_local(global_position + offset_3d).normalized()
# Nudge the indicator in that direction
ground.position = local_dir * 0.5 # Reduced from 0.6 to close the gap
ground.position.y = 0.05 # Keep it just above the floor