Tworząc gry, często tworzysz następujący obiekt gry, z którego dziedziczą wszystkie byty:
public class GameObject{
abstract void Update(...);
abstract void Draw(...);
}
Tak więc podczas aktualizacji pętli iterujesz wszystkie obiekty gry i dajesz im szansę na zmianę stanu, a następnie w następnej pętli losowania ponownie iterujesz wszystkie obiekty gry i dajesz im szansę na narysowanie się.
Chociaż działa to dość dobrze w prostej grze z prostym rendererem do przodu, często prowadzi do kilku gigantycznych obiektów gry, które muszą przechowywać swoje modele, wiele tekstur i, co najgorsze, ze wszystkich grubych metod rysowania, które tworzą ścisłe połączenie między obiektem gry, aktualna strategia renderowania i wszelkie klasy związane z renderowaniem.
Gdybym miał zmienić strategię renderowania z naprzód na odroczony, musiałbym zaktualizować wiele obiektów w grze. A obiekty gry, które tworzę, nie nadają się do wielokrotnego użytku. Oczywiście, dziedziczenie i / lub kompozycja może pomóc mi w walce z duplikacją kodu i nieco ułatwić zmianę implementacji, ale nadal wydaje mi się, że jej brakuje.
Być może lepszym sposobem byłoby całkowite usunięcie metody Draw z klasy GameObject i utworzenie klasy Renderer. GameObject nadal musiałby zawierać pewne dane dotyczące jego wyglądu, takie jak model, który ma być reprezentowany i jakie tekstury powinny zostać namalowane na modelu, ale sposób wykonania zostanie pozostawiony do renderowania. Jednak podczas renderowania często występuje wiele przypadków granicznych, więc chociaż usunęłoby to ścisłe powiązanie GameObject z Rendererem, Renderer nadal musiałby wiedzieć wszystko o wszystkich obiektach gry, które sprawiłyby, że byłby gruby, wszystko wiedział i ściśle powiązane. Naruszyłoby to sporo dobrych praktyk. Może projektowanie zorientowane na dane może załatwić sprawę. Obiektami gier z pewnością byłyby dane, ale w jaki sposób mechanizm renderujący byłby przez to sterowany? Nie jestem pewny.
Więc jestem zagubiony i nie mogę wymyślić dobrego rozwiązania. Próbowałem użyć zasad MVC, a kiedyś miałem pewne pomysły, jak to wykorzystać w grach, ale ostatnio nie wydaje się to tak odpowiednie, jak myślałem. Chciałbym wiedzieć, jak wszyscy rozwiązujecie ten problem.
Podsumowując, interesuje mnie, w jaki sposób można osiągnąć następujące cele projektowe.
- Brak logiki renderowania w obiekcie gry
- Luźne sprzężenie między obiektami gry a silnikiem renderowania
- Nie wszyscy znający renderer
- Najlepiej środowisko przełączające między silnikami renderującymi
Idealna konfiguracja projektu byłaby oddzielną „logiką gry” i renderowała projekt logiki, który nie musi się nawzajem odnosić.
Ten pociąg myślowy zaczął się, gdy usłyszałem na Twitterze, że John Carmack mówi, że ma system tak elastyczny, że może wymieniać silniki renderujące w czasie wykonywania, a nawet może powiedzieć swojemu systemowi, aby używał obu rendererów (renderera oprogramowania i renderera przyspieszanego sprzętowo) jednocześnie, aby mógł sprawdzić różnice. Systemy, które do tej pory programowałem, nie są nawet tak elastyczne