Powszechnie przyjętym wzorcem postępowania przy programowaniu jest tworzenie reprezentacji danych zagadnienia, na przykład poleceń postaci, które można przekazywać i traktować jako dane w swoim kodzie. W tej minigrze polecenia muszą być traktowane jako dane generowane w trakcie interakcji z UI i przekazywane postaci w celu wykonania czynności.
W tym projekcie polecenie reprezentowane jest jako klasa abstrakcyjna, a każde konkretne polecenie jest podklasą tej klasy command, na przykład forward_command czy turnright_command. Zastosowanie klasy abstrakcyjnej do polecenia oznacza, że jedynymi prawidłowymi poleceniami są podklasy nieabstrakcyjne. Jeśli spróbujesz utworzyć instancję klasy command bezpośrednio, napotkasz błąd przy próbie skompilowania kodu.
Polecenia postaci są podklasami klasy command, więc można ich używać wszędzie tam, gdzie oczekiwana jest klasa command, na przykład w funkcji ExecuteCommand() postaci z poprzedniego kroku. Pierwszy parametr funkcji ExecuteCommand() oczekuje typu polecenia, co oznacza, że bez problemu możesz użyć instancji podklasy command jako argumentu.
Każda podklasa ma własną implementację DebugString(), więc gdy zapiszesz w dzienniku wartość polecenia, będzie z nią powiązany właściwy tekst, jednak w razie potrzeby możesz dodać do klas więcej różnic.
Klasy te mają również specyfikator unique, dzięki czemu możemy porównywać instancje klas. Specyfikator ten umożliwia ich porównywanie.
Ponadto klasy te mają specyfikator computes, dzięki czemu możesz tworzyć ich instancje na poziomie zakresu modułu (bezpośrednio w module Commands). Oznacza to możliwość utworzenia jednej unikalnej instancji reprezentującej każde polecenie, na przykład instancji Commands.Forward dla polecenia ruchu do przodu.
Ten przykład wykorzystuje instancje podklas polecenia, zamiast typu enum, co pozwala dodać na dalszym etapie więcej poleceń poprzez utworzenie dodatkowych podklas. W przypadku użycia typu enum po opublikowaniu początkowej wersji projektu nie można wprowadzać zmian ani dodawać dodatkowych wartości, dlatego typ enum lepiej sprawdza się, gdy nie spodziewasz się wprowadzania zmian w danych po opublikowaniu projektu.
Poniżej przedstawiono kompletny kod implementacji polecenia.
# This file contains the data representation of all the commands that the NPC can receive
# and utilities for the data to help with debugging and troubleshooting issues.
# Each type of command that the NPC can perform will be an instance of this class.
# The class has the unique specifier to make instances of the class comparable.
# The class has the computes specifier to be able to instantiate it at module-scope.
# The class has the abstract specifier so it cannot be instantiated directly, and
# requires subclasses to implement any non-initialized functions, like DebugString().
command := class<computes><unique><abstract>:
DebugString():string
Następny krok
Zdefiniowaliśmy polecenia i pokazaliśmy, w jaki sposób można dodać dowolną ich liczbę.
W kolejnym kroku nauczysz się stosować te polecenia w UI i dodawać niestandardowe UI do sterowania postacią.