Sprawą kluczową dla edytora jest wewnętrzna organizacja danych oraz klas. Wraz z ciągłym rozwojem silników, również edytory muszą się zmieniać aby nadąrzyć za nowinkami technicznymi oraz programistycznymi. Dzisiejsze edytory powinny mieć konstrukcję modułową, korzystać z wielowątkowości, używać Inductive UI, umieć operować na coraz większej ilości danych itp itd. Wybór środowiska w którym powstanie edytor ma tutaj ogromne znaczenie. Nieodpowiednie środowisko może spowodować, że pisanie edytora zajmie 2-3 krotnie więcej czasu i energii niż powinno. Przez długi czas MFC, ATL, wxWidgets czy Borlandowy OWL były jednymi z najbardziej popularnych środowisk do tworzenia edytorów. Są to jednak rozwiązania dość wiekowe bo liczące sobie po 10-15 lat. Wraz z rozwojem języków obiektowych takich jak Java czy C# oraz wraz ze zmianą podejścia zarówno w konstrukcji wewnętrznej edytorów jak i konstrukcji UI, warto się przyjrzeć nowym propozycjom, zwłaszcza, że to właśnie nowe rozwiązania będą w najbliższej przyszłości najlepiej rozwijane i wspierane przez nowe kompilatory.

Od pewnego czasu coraz większą popularność zyskuje pisanie edytorów do gier (Neverwinter Nights 2 oraz The Sims 2) w języku C# oraz z użyciem platformy .NET. Język C# oraz .NET posiadają kilka istotnych cech, które znacznie przyśpieszają tworzenie edytorów i sprawiają, że ta platforma staje się bardzo atrakcyjna do stworzenia edytora:

  1. Managed Code – wszystkie klasy, metody oraz zmienne zdefiniowane w programie są dostępne dla edytora dzięki bardzo rozbudowanemu Type Factory zrealizowanym przez System.Reflection. W trakcie działania, edytor potrafi zebrać listę klas i metod, uzyskać informacje o sposobie tworzenia obiektów oraz ich wykorzystania. Dla przykładu, w edytorze bitmapowym może zebrać listę klas posiadających interface „IDrawTool” i przedstawić tą listę użytkownikowi jako zestaw narzędzi do rysowania różnych figur (SquareDrawTool, CircleDrawTool, PointDrawTool itd). Pozwala to na definiowanie narzędzi o których przeznaczeniu edytor nie musi wiedzieć.
  2. Attributes – atrybuty są zdefiniowanymi przez użytkownika specjalnymi obiektami, które kompilator może „dokleić” do definicji klasy, metody lub parametru. W atrybutach można zdefiniować dodatkowe informacje, które są potrzebne tylko edytorowi i nie mają żadnego wpływu na wykonywany program (kompilator nie dodaje dodatkowego kodu). Dla przykładu, atrybut można dodać do jednej ze zmiennych, np. „string Texture”. Dla edytora zmienna typu „string” oznacza jedynie, że użytkownik powinien podać tam jakiś text. Ale dodanie np. atrybutu „[WyborPliku(„dds”)]”, doda informację, którą edytor może zinterpretować jako „zmienna typu string zawierająca nazwę pliku o rozszeżeniu .dds”.
  3. Delegates – delegate’y są rozszeżeniem wskaźników na funkcję. W C++ można jedynie przekazać wskaźnik do statycznej funkcji w klasie. Delegate w C# oprócz wskaźnika na metodę, pozwala również przechować wskaźnik do obiektu co pozwala na wywołanie metody dla jakiegoś konkretnego obiektu (Instance Method).
  4. Wszystkie typy obiektów i zmiennych dziedziczą z podstawowego typu „object”. Edytor jest w stanie w prosty sposób sprawdzić typ zmiennej w dowolnym obiekcie, dowolnej klasy a następnie wywołać odpowiednie narzędzie, które będzie ten parametr modyfikować. W niezwykle prosty sposób można zrealizować budowę modułową i wprowadzać do edytora nowe typy zmiennych (np. zdefiniowane w oddzielnych plikach DLL) bez konieczności wprowadzania zmian w samym edytorze. Jedną z ciekawszych możliwości jest np. pobranie nazw zdefiniowanych w typie „enum” i wyświetlenie ich np. za pomocą ComboBox.
  5. System okien w .NET korzysta z dobrodziejstw Managed Code i zmienia nieco sposób obsługi zdarzeń okienkowych i upraszcza tworzenie własnych kontrolek. Teraz zdarzenie (np. OnLButtonDown) może być obsłużone w dowolnej innej kontrolce a nie tylko w tej do której zdarzenie przychodzi. Redukuje to do minimum, konieczność tworzenia nowych klas obsługujących daną kontrolkę. Wszystkie kontrolki dziedziczą teraz z klasy Control, która jest mocno rozbudowana w stosunku do klasy CWnd w MFC. Zamiast Device Context czyli klasy CDC jest teraz klasa Graphics posiadająca możliwości GDI+ (przeźroczystości, formaty bitmap png, jpg itd).
  6. ApplicationDomain – zawiera definicje wszystkich klas edytora oraz silnika. W prosty sposób można pisać w edytorze skrypty (kompilowane za pomocą kompilatorów dostępnych w .NET) lub poszerzać jego możliwości bez konieczności przekompilowywania kodu.
  7. „Mimo” wszystkich udogodnień, kod C# jest kompilowany do kodu procesora, dzięki czemu posiada on prędkość porównywalną z C++.

Każdy z tych poszczególnych elementów, znacznie upraszcza i przyśpiesza pracę nad tworzeniem edytora. 80% czasu poświęconego przy pisaniu edytora spędza się na obsłudze zdarzeń i tworzenia relacji pomiędzy tym co się przedstawia użytkownikowi a tym co jest w silniku. Ale nie ma róży bez ognia. Jeśli cały kod gry piszemy w starym native C++ to musimy eksportować nasze klasy do kodu managed. Im bardziej zautomatyzujemy ten proces tym lepiej. Najlepiej oczywiście, jeśli wrzucimy wszystkie klasy silnika do kodu managed tak by były one widoczne w .NET.

W kolejnych artykułach będę się posługiwać konstrukcjami z C# i .NET aby skoncentrować się jedynie na najnowszych rozwiązaniach.

Tworzenie edytorów dla gier cz. 2
0 votes, 0.00 avg. rating (0% score)