HUD (Heads-Up Display)
Altijd zichtbare interface elementen tijdens gameplay.
Overzicht
┌─────────────────────────────────────────────────────────────────┐
│ ┌─────────────┐ ┌───────────────┐ │
│ │ 🌰 1,234 │ │ ┌───────┐ │ │
│ │ 🥜 5,678 │ │ │MiniMap│ │ │
│ │ 🪵 342 │ │ └───────┘ │ │
│ └─────────────┘ └───────────────┘ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ ┌───┬───┬───┬───┬───┬───┐ ┌───────────────┐ │
│ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ Quick Slots │ 🕐 14:35 │ │
│ └───┴───┴───┴───┴───┴───┘ └───────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Resource HUD
Scene Structuur
ResourceHUD (Control)
├── Background (NinePatchRect)
└── VBoxContainer
├── EikelsRow (HBoxContainer)
│ ├── EikelsIcon (TextureRect)
│ └── EikelsLabel (Label)
├── BeukenootjesRow (HBoxContainer)
│ ├── BeukenootjesIcon (TextureRect)
│ └── BeukenootjesLabel (Label)
└── HoutRow (HBoxContainer)
├── HoutIcon (TextureRect)
└── HoutLabel (Label)
Script
# resource_hud.gd
extends Control
@onready var eikels_label: Label = $VBoxContainer/EikelsRow/EikelsLabel
@onready var beukenootjes_label: Label = $VBoxContainer/BeukenootjesRow/BeukenootjesLabel
var inventory_manager: InventoryManager
func setup(manager: InventoryManager) -> void:
inventory_manager = manager
inventory_manager.resources_changed.connect(_update_display)
_update_display()
func _update_display() -> void:
eikels_label.text = _format_number(inventory_manager.get_eikels())
beukenootjes_label.text = _format_number(inventory_manager.get_beukenootjes())
func _format_number(value: int) -> String:
if value >= 1000000:
return "%.1fM" % (value / 1000000.0)
elif value >= 1000:
return "%.1fK" % (value / 1000.0)
return str(value)
Animatie bij Wijziging
var _previous_values: Dictionary = {}
func _update_display() -> void:
_animate_change("eikels", inventory_manager.get_eikels(), eikels_label)
_animate_change("beukenootjes", inventory_manager.get_beukenootjes(), beukenootjes_label)
func _animate_change(key: String, new_value: int, label: Label) -> void:
var old_value = _previous_values.get(key, new_value)
_previous_values[key] = new_value
label.text = _format_number(new_value)
if new_value != old_value:
# Flash animation
var color = Color.GREEN if new_value > old_value else Color.RED
label.modulate = color
var tween = create_tween()
tween.tween_property(label, "modulate", Color.WHITE, 0.5)
# Scale pop
label.scale = Vector2(1.2, 1.2)
tween.parallel().tween_property(label, "scale", Vector2.ONE, 0.3)
Quick Slots
Scene Structuur
QuickSlots (Control)
├── Background
└── HBoxContainer
├── Slot1 (ItemSlot)
├── Slot2 (ItemSlot)
├── Slot3 (ItemSlot)
├── Slot4 (ItemSlot)
├── Slot5 (ItemSlot)
└── Slot6 (ItemSlot)
Script
# quick_slots.gd
extends Control
@onready var slots: Array[ItemSlot] = [
$HBoxContainer/Slot1,
$HBoxContainer/Slot2,
$HBoxContainer/Slot3,
$HBoxContainer/Slot4,
$HBoxContainer/Slot5,
$HBoxContainer/Slot6
]
var assigned_items: Array[Dictionary] = [{}, {}, {}, {}, {}, {}]
func _ready() -> void:
for i in range(slots.size()):
slots[i].slot_index = i
slots[i].item_used.connect(_on_item_used.bind(i))
func _input(event: InputEvent) -> void:
# Number keys 1-6
for i in range(6):
if event.is_action_pressed("slot_%d" % (i + 1)):
_use_slot(i)
func _use_slot(index: int) -> void:
if assigned_items[index].is_empty():
return
var item = assigned_items[index]
_use_item(item)
func assign_item(slot_index: int, item: Dictionary) -> void:
assigned_items[slot_index] = item
slots[slot_index].set_item(item.item_id, item.quantity, item.icon)
Keybindings
# project.godot input map
slot_1 = Key 1
slot_2 = Key 2
slot_3 = Key 3
slot_4 = Key 4
slot_5 = Key 5
slot_6 = Key 6
Clock Display
Script
# clock.gd
extends Control
@onready var time_label: Label = $TimeLabel
@onready var day_label: Label = $DayLabel
var game_time: float = 0.0 # In-game seconds
const MINUTES_PER_REAL_SECOND = 10.0
func _process(delta: float) -> void:
game_time += delta * MINUTES_PER_REAL_SECOND
_update_display()
func _update_display() -> void:
var total_minutes = int(game_time)
var hours = (total_minutes / 60) % 24
var minutes = total_minutes % 60
time_label.text = "%02d:%02d" % [hours, minutes]
# Day number
var day = int(game_time / (24 * 60)) + 1
day_label.text = "Dag %d" % day
Mini Map
Scene Structuur
MiniMap (Control)
├── Background (TextureRect)
├── MapContainer (SubViewportContainer)
│ └── SubViewport
│ └── MapCamera
├── PlayerMarker (TextureRect)
└── NPCMarkers (Node2D)
Script
# minimap.gd
extends Control
@onready var player_marker: TextureRect = $PlayerMarker
@onready var map_container: SubViewportContainer = $MapContainer
var world_size: Vector2 = Vector2(2000, 2000)
var map_size: Vector2 = Vector2(150, 150)
func update_player_position(world_pos: Vector2) -> void:
var normalized = world_pos / world_size
var map_pos = normalized * map_size
player_marker.position = map_pos - player_marker.size / 2
func add_npc_marker(npc_id: String, world_pos: Vector2, icon: Texture2D) -> void:
var marker = TextureRect.new()
marker.texture = icon
marker.name = "NPC_" + npc_id
$NPCMarkers.add_child(marker)
_update_marker_position(marker, world_pos)
Notification System
Toast Notificaties
# notification_manager.gd
extends CanvasLayer
@onready var notification_container: VBoxContainer = $NotificationContainer
const NOTIFICATION_SCENE = preload("res://scenes/ui/notification.tscn")
func show_notification(text: String, type: String = "info") -> void:
var notification = NOTIFICATION_SCENE.instantiate()
notification.setup(text, type)
notification_container.add_child(notification)
# Auto remove after delay
await get_tree().create_timer(3.0).timeout
_remove_notification(notification)
func _remove_notification(notification: Control) -> void:
var tween = create_tween()
tween.tween_property(notification, "modulate:a", 0.0, 0.3)
tween.tween_callback(notification.queue_free)
Notification Types
| Type | Kleur | Icoon |
|---|---|---|
| info | Blauw | ℹ️ |
| success | Groen | ✓ |
| warning | Oranje | ⚠️ |
| error | Rood | ✕ |