====== Resources i Inventory ======
I et RPG skal spilleren kunne samle våben, potions og armor op og beholde dem, når spilleren skifter scene.
Vi løser det ved at oprette en **global** `InventoryManager` som **Autoload**. Den eksisterer, så længe spillet kører, og kan tilgås fra alle scener.
===== 1. Opret InventoryManager =====
Opret et C#-script med navnet `InventoryManager.cs`.
using Godot;
using Godot.Collections;
public partial class InventoryManager : Node
{
public Array- Items { get; private set; } = new();
public void AddItem(Item item)
{
if (item == null)
return;
Items.Add(item);
GD.Print($"Samlede op: {item.Name}");
}
}
**Hvad sker der?**
* `Array- ` indeholder spillerens items.
* `AddItem()` tilføjer et item til inventory.
* `InventoryManager` indeholder kun data og logik for inventory – ikke selve brugergrænsefladen.
Bemærk, at `Item` er den fælles Resource-klasse fra den foregående øvelse. Både `WeaponItem` og `PotionItem` kan derfor tilføjes.
----
===== 2. Gør InventoryManager global =====
For at inventory overlever sceneskift, skal `InventoryManager` oprettes som en **Autoload**.
- Åbn **Project → Project Settings → Globals → Autoload**. Menunavnet kan variere lidt mellem Godot-versioner.
- Vælg filen `InventoryManager.cs`.
- Angiv navnet `InventoryManager`.
- Aktivér Autoload. (markér checkbox 'Enabled')
Godot opretter nu en global instans af `InventoryManager`, som ikke bliver fjernet, når en almindelig scene skiftes ud.
Du kan tilgå den fra C# med:
GetNode("/root/InventoryManager");
----
===== 3. Opret ItemPickup =====
Opret et script med navnet `ItemPickup.cs`. Det sættes på en `Area2D`, som spilleren kan gå ind i for at samle et item op.
using Godot;
public partial class ItemPickup : Area2D
{
[Export]
public Item Data { get; set; }
public override void _Ready()
{
_sprite = GetNode("Sprite2D");
if (item != null)
{
_sprite.Texture = item.Icon;
}
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node2D other)
{
if (other is Player)
{
var inventory = GetNode("/root/InventoryManager");
inventory.AddItem(Data);
QueueFree();
}
}
}
**Bemærk:** `Player` skal svare til navnet på jeres spillers C#-klasse.
----
===== 4. Opsæt pickup-scenen =====
Opret følgende nodestruktur:
ItemPickup (Area2D)
├── Sprite2D
└── CollisionShape2D
- Tilføj `ItemPickup.cs` til `Area2D`.
- Opret en `CollisionShape2D`, der dækker det område, spilleren skal ramme.
- Sørg for, at `Area2D` har `Monitoring` aktiveret.
- Forbind signalet `body_entered` til metoden `OnBodyEntered`.
- Tildel en konkret `Item`-resource til egenskaben `Data` i Inspector.
Du kan nu genbruge samme pickup-scene til eksempelvis `Sword.tres`, `HealthPotion.tres` og `IronArmor.tres`.
----
===== 5. Test sceneskift =====
- Start spillet i en scene med et item.
- Gå hen til item'et, og saml det op.
- Skift til en anden scene.
- Undersøg `InventoryManager.Items`, eller udskriv indholdet i Output.
Tilføj eventuelt denne metode til `InventoryManager` for at teste indholdet:
public void PrintItems()
{
foreach (Item item in Items)
{
GD.Print(item.Name);
}
}
Kald metoden fra et passende sted i spillet, når du vil kontrollere inventory.
----
===== 6. Hvorfor virker det? =====
En almindelig scene bliver fjernet, når spillet skifter til en anden scene. En Autoload-instans lever derimod videre, mens spillet kører.
Inventory ligger derfor ikke i den scene, spilleren forlader, men i en global instans.
++++ Vigtigt: Hvad gemmes egentlig? |
InventoryManager gemmer referencer til de `Item`-resources, spilleren har samlet op. Det betyder ikke, at spillet automatisk gemmer fremskridtet på disken.
Hvis spilleren også skal beholde inventory efter at have lukket spillet, skal I senere implementere et save/load-system.
++++
===== Opgave =====
- Opret en `HealthPotion.tres` baseret på `PotionItem`.
- Placér en potion i én scene og et sværd i en anden.
- Saml begge items op.
- Skift mellem scenerne, og kontrollér, at inventory stadig indeholder begge items.
- Forklar, hvorfor `InventoryManager` skal være en Autoload, og hvorfor det er praktisk at lade inventory indeholde `Item` i stedet for kun `WeaponItem`.
===== Opsummering =====
* `Item` er basisklassen for alle items.
* `InventoryManager` holder styr på spillerens items.
* Autoload gør inventory tilgængeligt fra alle scener og bevarer det under sceneskift.
* Et save/load-system er nødvendigt, hvis inventory også skal overleve, at spillet lukkes.