HTX Frederikshavn & Hjørring

Det har aldrig været sjovere at være nørd

Brugerværktøjer

Webstedsværktøjer


ddu:godot:inventory_system

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

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