ddu:godot:inventory_system
Indholdsfortegnelse
Inventory system
Her vil vi i fælleskab udvikle et inventory system i Godot C#. Krav til vores inventory er følgende:
- Statisk antal pladser inventory
- 'Stack-able' items. dvs vi skal kunne opsummere items af samme type.
- Inventory GUI kan åbnet og lukkes med tasten 'i'.
Klasser & ansvar
- Item
- Inventory
- InventoryGui
- InvSlotGui
- CollectableGui
Item
- Navn
- Beskrivelse
Opsætning af InputHandler til visning af Inventory
- Project → Project settings → Input Map
- Add new Action fx. 'toggle_inventory'
- click plus og vælg tasten 'i'.
- Og mens vi er der ..så evt. også et input til at interagere med omverdenen. åbne døre, kister, dialoger..etc.
- 'Engage' kalder vi denne. Add action fx. 'player_engage', mappes til tasten 'e'.
Item (Resource)
using Godot; using System; [GlobalClass] public partial class Item : Resource { [Export] public int ID { get; set; } [Export] public String Name { get; set; } [Export] public Texture2D Icon { get; set; } [Export] public int Quantity { get; set; } [Export] public int MaxStackSize { get; set; } [Export] public bool IsStackable { get; set; } }
Collectable
using Godot; using System; public partial class Collectable : Node { [Export] public Item item; // Called when the node enters the scene tree for the first time. public override void _Ready() { GetNode<Sprite2D>("Sprite2D").Texture = item.Icon; } public void OnBodyEntered(Node other) { if (other.Name == "Player") { GD.Print("Collectable was entered by Player."); if (GetNode<Inventory>("/root/World/CanvasLayer/Inventory").Add(this.item) == true) { this.QueueFree(); } } } }
InvSlotGui
Ansvar: Viser indhold af Item i InventoryGui
- Panel ( Visibility, set self-modulate 'A', til 0 )
- Background (Sprite2D)
- Set ønskede Texture
- Offset → Centered = Off
- Label ( til item coint )
- font: Disable Subpixel Positioning in the font’s import settings.
- Juster Panel størrelse til at matche Bagground sprite.
- På panelet sættes 'Custom minimum size', til størrelsen af Transform (som nu er samme størrelse som BG sprite). (Dette gøre for at undgå at Slot Panel bliver „klemt“.
- Gem scene som fx. 'InvSlotUI'
using Godot; using System; public partial class InvSlot : Panel { // Called when the node enters the scene tree for the first time. public override void _Ready() { GetNode<Sprite2D>("ItemDisplayIcon").Visible = false; // Som udgangspunkt er denne skjult } public void UpdateSlot(Item item) { if (item == null) GetNode<Sprite2D>("ItemDisplayIcon").Visible = false; else { GetNode<Sprite2D>("ItemDisplayIcon").Visible = true; GetNode<Sprite2D>("ItemDisplayIcon").Texture = item.Icon; } } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { } }
Inventory
Indeholder alle vores opsamlede items. Håndtere funktionalitet ift. at tilføje og fjerne Items.
InventoryGUI
- inventory-background.png - Til NinePatchRect Using a NinePatchRect
NinePatchRect er en smart Component der deler en Sprite i 9 felter, og bibeholder aspektet på ydre deområder således vi kan bruge den i forskelle størrelse (fx. baggrund til Inventory, Dialoger eller andet) se nedenstående.
Tilføj 8 stk InvSlotUI til denne GridContainer, og juster antal columns på GridContainer til 4.
- Vi ønsker GridContainer skal være centeret ift. vores NinePatchRect. I GridContainer, Layout→LayoutMode sæt til 'Anchors' og vælg 'Center-Center'. Nu bør alle inventorySlots være i centrum af NinePatchRect.
- Sæt afslutningsvis minimum size på inventory, til det samme som tranform size.
Inventory
using Godot; using System; public partial class Inventory : Control { public bool IsOpen = true; [Export] public Item[] items; GridContainer gridContainer; override public void _Ready() { gridContainer = GetNode<GridContainer>("NinePatchRect/GridContainer"); GD.Print("GridContainer check: " + gridContainer); } /* * Opening and Closing the inventory. * Controlled (input captured) from CanvasLayer Script */ public void OpenInventory() { this.Visible = true; IsOpen = true; } public void CloseInventory() { this.Visible = false; IsOpen = false; } public bool Add(Item item) { GD.Print("Adding item: " + item.Name + " to inventory"); for (int x = 0; x < items.Length; x++) { if (items[x] == null) { items[x] = item; UpdateAllInventorySlots(); return true; } else if ( items[x].ID == item.ID && item.IsStackable == true ) { if (items[x].Quantity < items[x].MaxStackSize) { // Der er noget plads !! if (item.Quantity + items[x].Quantity <= items[x].MaxStackSize) { // Der er plads nok i ét slot. items[x].Quantity += item.Quantity; UpdateAllInventorySlots(); return true; } else { // Fyld Slot op, Juster item quantity, og lad os om der plads andre steder item.Quantity -= (items[x].MaxStackSize - items[x].Quantity); items[x].Quantity = items[x].MaxStackSize; UpdateAllInventorySlots(); return true; } } } } GD.Print("Failed to ADD item: " + item.Name + ", to Inventory.. (maybe its full?)"); return false; } public bool HasItem(Item item) { for (int i = 0; i < this.items.Length; i++) { if (items[i].ID == item.ID) { return true; } } return false; // item was not found } public bool RemoveItem(Item item) { bool success = false; for (int i = 0; i < this.items.Length; i++) { if (items[i].ID == item.ID) { items[i] = null; success = true; } } return success; // item was not removed } /* * Updates all visible Slot GUIs so they are in sync with the items array */ public void UpdateAllInventorySlots() { for (int i = 0; i < items.Length; i++) { var slots = gridContainer.GetChildren(); ((InvSlot)slots[i]).UpdateSlot(items[i]); } } }
ItemSlot
using Godot; using System; public partial class InvSlot : Panel { // Called when the node enters the scene tree for the first time. public override void _Ready() { GetNode<Sprite2D>("ItemDisplayIcon").Visible = false; // Som udgangspunkt er denne skjult } public void UpdateSlot(Item item) { if (item == null) GetNode<Sprite2D>("ItemDisplayIcon").Visible = false; else { GetNode<Sprite2D>("ItemDisplayIcon").Visible = true; GetNode<Sprite2D>("ItemDisplayIcon").Texture = item.Icon; } } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { } }
Insert scenarier
- Der er et tomt inventory slot.
- Der er et item af samme type
- (og item kan stackes)
- Der et et item af samme type (og item kan ikke stackes)
- Der er ikke fundet et tomt item slot. (Der er ikke plads)
ddu/godot/inventory_system.txt · Sidst ændret: af 127.0.0.1
