Menu
Coddy logo textTech

Komponent postaci w grze

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 69 z 70.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system postaci w grze, korzystając ze wzorca architektury opartej na komponentach! Zamiast tworzyć sztywne hierarchie dziedziczenia, będziesz składać postacie, dołączając niezależne komponenty obsługujące określone zachowania — to elastyczne podejście jest powszechnie stosowane w tworzeniu gier.

Rozmieścisz kod w pięciu plikach:

  • IComponent.cs: Zdefiniuj interfejs IComponent w przestrzeni nazw Game.Components. Każdy komponent musi mieć metodę Update(), która wyświetla, co robi dany komponent.
  • HealthComponent.cs: Utwórz klasę HealthComponent, która implementuje IComponent. Powinna śledzić aktualną i maksymalną liczbę punktów zdrowia oraz udostępniać metody TakeDamage(int amount) i Heal(int amount). Zdrowie nigdy nie powinno spaść poniżej 0 ani przekroczyć wartości maksymalnej. Dodaj zdarzenie event Action<int> HealthChanged, które jest wywoływane za każdym razem, gdy zmienia się poziom zdrowia, i przekazuje jego nową wartość. Metoda Update() powinna wyświetlać aktualny stan zdrowia.
  • InventoryComponent.cs: Utwórz klasę InventoryComponent, która implementuje IComponent. Zarządza ona listą nazw przedmiotów i udostępnia metody AddItem(string item) oraz RemoveItem(string item) (zwraca bool wskazujący, czy operacja się powiodła). Metoda Update() powinna wyświetlać zawartość ekwipunku.
  • Character.cs: Utwórz klasę Character w przestrzeni nazw Game, która przechowuje kolekcję komponentów. Twoja postać powinna mieć właściwość Name oraz następujące metody:
    • AddComponent(IComponent component) — dołącza komponent do postaci
    • GetComponent<T>() where T : IComponent — zwraca pierwszy komponent typu T albo null, jeśli nie znaleziono takiego komponentu
    • UpdateAll() — wywołuje Update() dla każdego dołączonego komponentu
  • Program.cs: Połącz wszystko w całość, tworząc postać, dołączając komponenty i przetwarzając polecenia.

Otrzymasz następujące dane wejściowe:

  • Nazwa postaci
  • Początkowa maksymalna liczba punktów zdrowia dla HealthComponent
  • Liczba poleceń do przetworzenia
  • Dla każdego polecenia: akcja, a następnie odpowiednie dane

Formaty poleceń:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

Formaty danych wyjściowych:

  • Gdy zmienia się poziom zdrowia (za pośrednictwem zdarzenia): Health changed: {newHealth}
  • Podczas dodawania przedmiotu: Added: {itemName}
  • Podczas usuwania przedmiotu: Removed: {itemName} lub Item not found: {itemName}
  • Metoda Update() klasy HealthComponent: Health: {current}/{max}
  • Metoda Update() klasy InventoryComponent: Inventory: {item1}, {item2}, ... lub Inventory: empty

Na przykład, jeśli dane wejściowe to:

Hero
100
7
add_item
Sword
add_item
Shield
damage
30
heal
10
remove_item
Potion
remove_item
Sword
update

Dane wyjściowe powinny być następujące:

Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: Shield

Zauważ, że postać nie dziedziczy po żadnej specjalnej klasie — po prostu przechowuje komponenty, które zapewniają jej zachowania. Metoda GetComponent<T>() używa typów generycznych, aby pobieranie komponentów było bezpieczne pod względem typów, a zdarzenia informują o zmianie poziomu zdrowia. To podejście oparte na kompozycji pozwala swobodnie łączyć różne komponenty!

Spróbuj swoich sił

using System;
using Game;
using Game.Components;

class Program
{
    public static void Main(string[] args)
    {
        // Wczytaj imię postaci
        string characterName = Console.ReadLine();
        
        // Wczytaj początkową maksymalną wartość zdrowia
        int maxHealth = Convert.ToInt32(Console.ReadLine());
        
        // Wczytaj liczbę poleceń
        int numCommands = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Utwórz Character o podanym imieniu
        
        // TODO: Utwórz HealthComponent z maxHealth oraz InventoryComponent
        
        // TODO: Zasubskrybuj zdarzenie HealthChanged, aby wyświetlać: Health changed: {newHealth}
        
        // TODO: Dodaj oba komponenty do postaci
        
        // TODO: Przetwórz każde polecenie
        for (int i = 0; i < numCommands; i++)
        {
            string command = Console.ReadLine();
            
            // TODO: Obsłuż każdy typ polecenia:
            // - "damage": wczytaj wartość, wywołaj TakeDamage na komponencie zdrowia
            // - "heal": wczytaj wartość, wywołaj Heal na komponencie zdrowia
            // - "add_item": wczytaj nazwę przedmiotu, wywołaj AddItem na komponencie ekwipunku
            // - "remove_item": odczytaj nazwę przedmiotu, wywołaj RemoveItem na komponencie ekwipunku
            // - "update": wywołaj UpdateAll na postaci
        }
    }
}

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online