Add interactive mushroom pickup and highlight mechanics with pop sound
Some checks failed
Deploy Promiscuity Auth API / deploy (push) Successful in 1m1s
Deploy Promiscuity Character API / deploy (push) Has been cancelled
Deploy Promiscuity Crafting API / deploy (push) Has been cancelled
Deploy Promiscuity Inventory API / deploy (push) Has been cancelled
Deploy Promiscuity Locations API / deploy (push) Has been cancelled
Deploy Promiscuity Mail API / deploy (push) Has been cancelled
Deploy Promiscuity World API / deploy (push) Has been cancelled
k8s smoke test / test (push) Has been cancelled
Some checks failed
Deploy Promiscuity Auth API / deploy (push) Successful in 1m1s
Deploy Promiscuity Character API / deploy (push) Has been cancelled
Deploy Promiscuity Crafting API / deploy (push) Has been cancelled
Deploy Promiscuity Inventory API / deploy (push) Has been cancelled
Deploy Promiscuity Locations API / deploy (push) Has been cancelled
Deploy Promiscuity Mail API / deploy (push) Has been cancelled
Deploy Promiscuity World API / deploy (push) Has been cancelled
k8s smoke test / test (push) Has been cancelled
This commit is contained in:
parent
e6a442c98b
commit
09e6b4cc90
@ -6,11 +6,20 @@ extends Node3D
|
||||
@export var max_mushrooms_in_radius := 3
|
||||
@export var check_radius := 1.5
|
||||
@export var max_total_mushrooms := 50
|
||||
@export var interact_radius := 2.0
|
||||
@export var look_at_threshold := 0.95
|
||||
|
||||
static var total_mushrooms := 0
|
||||
|
||||
@onready var spread_timer: Timer = $SpreadTimer
|
||||
@onready var ground_ray: RayCast3D = $GroundRay
|
||||
@onready var cap: MeshInstance3D = $Cap
|
||||
@onready var stem: MeshInstance3D = $Stem
|
||||
|
||||
var _player_in_range := false
|
||||
var _is_highlighted := false
|
||||
var highlight_mat: StandardMaterial3D
|
||||
var _audio_player: AudioStreamPlayer3D
|
||||
|
||||
func _ready() -> void:
|
||||
total_mushrooms += 1
|
||||
@ -20,6 +29,111 @@ func _ready() -> void:
|
||||
scale = Vector3.ONE * randf_range(0.8, 1.2)
|
||||
rotation.y = randf_range(0, TAU)
|
||||
|
||||
# Setup interaction area
|
||||
var area = Area3D.new()
|
||||
add_child(area)
|
||||
var shape = CollisionShape3D.new()
|
||||
var sphere = SphereShape3D.new()
|
||||
sphere.radius = interact_radius
|
||||
shape.shape = sphere
|
||||
area.add_child(shape)
|
||||
|
||||
area.body_entered.connect(_on_body_entered)
|
||||
area.body_exited.connect(_on_body_exited)
|
||||
|
||||
highlight_mat = StandardMaterial3D.new()
|
||||
highlight_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
highlight_mat.albedo_color = Color(1.0, 1.0, 1.0, 0.3)
|
||||
highlight_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
||||
|
||||
_audio_player = AudioStreamPlayer3D.new()
|
||||
_audio_player.stream = preload("res://assets/audio/pop.ogg")
|
||||
add_child(_audio_player)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if not _player_in_range:
|
||||
_set_highlight(false)
|
||||
return
|
||||
|
||||
var cam = get_viewport().get_camera_3d()
|
||||
if not cam:
|
||||
_set_highlight(false)
|
||||
return
|
||||
|
||||
var dir_to_mushroom = (global_position - cam.global_position).normalized()
|
||||
var forward = -cam.global_transform.basis.z
|
||||
var my_dot = forward.dot(dir_to_mushroom)
|
||||
|
||||
if my_dot > look_at_threshold:
|
||||
# Check if we are the most directly looked-at mushroom in range
|
||||
var is_best = true
|
||||
for mushroom in get_tree().get_nodes_in_group("mushrooms"):
|
||||
if mushroom == self or not mushroom.get("_player_in_range"):
|
||||
continue
|
||||
|
||||
var m_dir = (mushroom.global_position - cam.global_position).normalized()
|
||||
var m_dot = forward.dot(m_dir)
|
||||
|
||||
if m_dot > my_dot:
|
||||
is_best = false
|
||||
break
|
||||
elif m_dot == my_dot and mushroom.get_instance_id() > get_instance_id():
|
||||
# Tie breaker
|
||||
is_best = false
|
||||
break
|
||||
|
||||
_set_highlight(is_best)
|
||||
else:
|
||||
_set_highlight(false)
|
||||
|
||||
func _set_highlight(value: bool) -> void:
|
||||
if _is_highlighted == value: return
|
||||
_is_highlighted = value
|
||||
|
||||
if value:
|
||||
if cap: cap.material_overlay = highlight_mat
|
||||
if stem: stem.material_overlay = highlight_mat
|
||||
else:
|
||||
if cap: cap.material_overlay = null
|
||||
if stem: stem.material_overlay = null
|
||||
|
||||
func _on_body_entered(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
_player_in_range = true
|
||||
|
||||
func _on_body_exited(body: Node3D) -> void:
|
||||
if body.is_in_group("player"):
|
||||
_player_in_range = false
|
||||
_set_highlight(false)
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if _is_highlighted and event.is_action_pressed("interact"):
|
||||
get_viewport().set_input_as_handled()
|
||||
_collect_mushroom()
|
||||
|
||||
func _collect_mushroom() -> void:
|
||||
# Disable interaction and visuals
|
||||
_is_highlighted = false
|
||||
_set_highlight(false)
|
||||
_player_in_range = false
|
||||
|
||||
if cap: cap.visible = false
|
||||
if stem: stem.visible = false
|
||||
|
||||
# Stop spreading logic
|
||||
spread_timer.stop()
|
||||
|
||||
# Disable processing so it can't be interacted with again
|
||||
set_process_unhandled_input(false)
|
||||
set_process(false)
|
||||
|
||||
# Play sound
|
||||
_audio_player.play()
|
||||
|
||||
# Wait for sound to finish, then free
|
||||
await _audio_player.finished
|
||||
queue_free()
|
||||
|
||||
func _setup_timer() -> void:
|
||||
spread_timer.wait_time = randf_range(spread_interval_min, spread_interval_max)
|
||||
spread_timer.start()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user