feat(hud): compass + depth + biome indicator
Panneau info top-right avec boussole (8 directions FR), profondeur en mètres depuis la surface, et nom de biome courant (Récif Corallien, Forêt de Kelp, Plateau Rocheux, Abysses). Helper biome_name_at dans WorldGenerator pour requête client-side sans relire les chunks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,75 @@
|
||||
extends CanvasLayer
|
||||
|
||||
const WATER_SURFACE_Y: float = 60.0
|
||||
|
||||
@onready var _oxygen_bar: ProgressBar = %OxygenBar
|
||||
@onready var _health_bar: ProgressBar = %HealthBar
|
||||
@onready var _hunger_bar: ProgressBar = %HungerBar
|
||||
|
||||
var _dolphin: Node3D = null
|
||||
var _world_seed: int = 12345
|
||||
|
||||
var _info_panel: PanelContainer = null
|
||||
var _depth_label: Label = null
|
||||
var _biome_label: Label = null
|
||||
var _compass_label: Label = null
|
||||
|
||||
var _biome_cache_pos: Vector3 = Vector3(99999, 99999, 99999)
|
||||
var _biome_cached_name: String = ""
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_style_bar(_oxygen_bar, Color(0.31, 0.76, 0.97))
|
||||
_style_bar(_health_bar, Color(0.91, 0.30, 0.24))
|
||||
_style_bar(_hunger_bar, Color(0.95, 0.61, 0.07))
|
||||
_build_info_panel()
|
||||
|
||||
|
||||
func _build_info_panel() -> void:
|
||||
_info_panel = PanelContainer.new()
|
||||
_info_panel.anchor_left = 1.0
|
||||
_info_panel.anchor_right = 1.0
|
||||
_info_panel.anchor_top = 0.0
|
||||
_info_panel.anchor_bottom = 0.0
|
||||
_info_panel.offset_left = -220.0
|
||||
_info_panel.offset_top = 16.0
|
||||
_info_panel.offset_right = -16.0
|
||||
_info_panel.offset_bottom = 112.0
|
||||
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.05, 0.05, 0.05, 0.7)
|
||||
style.corner_radius_top_left = 10
|
||||
style.corner_radius_top_right = 10
|
||||
style.corner_radius_bottom_left = 10
|
||||
style.corner_radius_bottom_right = 10
|
||||
_info_panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.add_theme_constant_override("separation", 4)
|
||||
_info_panel.add_child(vbox)
|
||||
|
||||
_compass_label = Label.new()
|
||||
_compass_label.text = "⬆ N"
|
||||
_compass_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_compass_label.add_theme_font_size_override("font_size", 20)
|
||||
_compass_label.add_theme_color_override("font_color", Color(0.85, 0.95, 1.0))
|
||||
vbox.add_child(_compass_label)
|
||||
|
||||
_depth_label = Label.new()
|
||||
_depth_label.text = "Prof. 0 m"
|
||||
_depth_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_depth_label.add_theme_font_size_override("font_size", 14)
|
||||
_depth_label.add_theme_color_override("font_color", Color(0.70, 0.88, 1.0))
|
||||
vbox.add_child(_depth_label)
|
||||
|
||||
_biome_label = Label.new()
|
||||
_biome_label.text = "Biome : —"
|
||||
_biome_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_biome_label.add_theme_font_size_override("font_size", 14)
|
||||
_biome_label.add_theme_color_override("font_color", Color(0.85, 0.95, 0.75))
|
||||
vbox.add_child(_biome_label)
|
||||
|
||||
add_child(_info_panel)
|
||||
|
||||
|
||||
func _style_bar(bar: ProgressBar, color: Color) -> void:
|
||||
@@ -31,9 +92,55 @@ func _style_bar(bar: ProgressBar, color: Color) -> void:
|
||||
|
||||
func connect_to_dolphin(dolphin: CharacterBody3D) -> void:
|
||||
dolphin.stats_changed.connect(_on_stats_changed)
|
||||
_dolphin = dolphin
|
||||
|
||||
var main: Node = get_tree().get_first_node_in_group("main")
|
||||
if main != null:
|
||||
var cm: Node = main.get_node_or_null("World/ChunkManager")
|
||||
if cm != null and cm.get("world_seed") != null:
|
||||
_world_seed = cm.world_seed
|
||||
|
||||
|
||||
func _on_stats_changed(oxygen: float, hp: float, hunger: float) -> void:
|
||||
_oxygen_bar.value = oxygen
|
||||
_health_bar.value = hp
|
||||
_hunger_bar.value = hunger
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if not is_instance_valid(_dolphin):
|
||||
return
|
||||
|
||||
var depth_m: int = int(round(WATER_SURFACE_Y - _dolphin.global_position.y))
|
||||
if _depth_label != null:
|
||||
_depth_label.text = "Prof. %d m" % depth_m
|
||||
|
||||
if _compass_label != null:
|
||||
_compass_label.text = _compass_text(_dolphin.rotation.y)
|
||||
|
||||
if _biome_label != null:
|
||||
_update_biome_label()
|
||||
|
||||
|
||||
func _compass_text(yaw: float) -> String:
|
||||
# Player forward is -Z when yaw=0 → North. Yaw rotates counterclockwise in Godot.
|
||||
# Convert yaw to a heading [0, 360) where 0 = North, 90 = East.
|
||||
var heading: float = rad_to_deg(-yaw)
|
||||
heading = fposmod(heading, 360.0)
|
||||
|
||||
var labels: PackedStringArray = PackedStringArray(["N", "NE", "E", "SE", "S", "SO", "O", "NO"])
|
||||
var arrows: PackedStringArray = PackedStringArray([
|
||||
"⬆", "⬈", "➡", "⬊", "⬇", "⬋", "⬅", "⬉"
|
||||
])
|
||||
var idx: int = int(round(heading / 45.0)) % 8
|
||||
return "%s %s" % [arrows[idx], labels[idx]]
|
||||
|
||||
|
||||
func _update_biome_label() -> void:
|
||||
var pos: Vector3 = _dolphin.global_position
|
||||
if pos.distance_to(_biome_cache_pos) < 4.0 and _biome_cached_name != "":
|
||||
_biome_label.text = "Biome : %s" % _biome_cached_name
|
||||
return
|
||||
_biome_cache_pos = pos
|
||||
_biome_cached_name = WorldGenerator.biome_name_at(pos.x, pos.z, pos.y, _world_seed)
|
||||
_biome_label.text = "Biome : %s" % _biome_cached_name
|
||||
|
||||
Reference in New Issue
Block a user