Ga naar hoofdinhoud

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

TypeKleurIcoon
infoBlauwℹ️
successGroen
warningOranje⚠️
errorRood

Volgende