Zarządzanie listami różnych typów podmiotów - czy istnieje lepszy sposób?

9

Tworzę kosmiczną grę 2D na urządzenia mobilne, ale robi się naprawdę skomplikowana, a moje rozwiązanie jest naprawdę mylące i generuje wiele powtarzających się segmentów kodu.

Mam światowej klasy, w której mam multible listy różnych obiektów, takich jak:

List<Enemy> enemys;
List<Projectile> projectiles;
List<Collectable> collectables;
List<Asteroid> asteroids;
List<Effect> effects;
..

Każda lista jest aktualizowana przez światowej klasy. ale to nie wszystko. Każdy wróg ma listę silników i listę skrytobójców, która jest aktualizowana przez wroga. Teraz każdy silnik dodaje niektóre efekty ognia do „efektów” z listy światów, a każdy luncher broni dodaje pociski do „pocisków” z listy świata. Wszystkie te klasy mają inny parametr, więc potrzebuję dodatkowej aktualizacji ORAZ dodatkowej funkcji renderowania dla każdej klasy.

Przynajmniej wszystkie są potomkami „GameObject”, który zapewnia im podstawowe rzeczy, takie jak wektory położenia, prędkości i przyspieszenia, granice wielokątów oraz funkcje takie jak applyForce i skończona maszyna stanów

Czy istnieje lepszy lub bardziej powszechny sposób na zrobienie tego? jak jedna klasa catch-all, która zawiera wszystkie możliwe parametry i metody dla wszystkich różnych obiektów. (myślę, że spowodowałoby to jeszcze bardziej kłopotliwy kod)

Orzech
źródło
Jest to podobne do mojego pytania: gamedev.stackexchange.com/questions/22559/ ... Sugeruję, aby spojrzeć na udzielone odpowiedzi.
Derek

Odpowiedzi:

5

Czy istnieje lepszy lub bardziej powszechny sposób na zrobienie tego? jak jedna klasa catch-all, która zawiera wszystkie możliwe parametry i metody dla wszystkich różnych obiektów.

Tak, to się nazywa architektura. Spojrzeć tutaj szczegóły.

Pozwoliłoby to tylko jednej liście podmiotów w Twojej światowej klasie:

List<Entity>

To jeden przykład Kompozycji nad dziedziczeniem .

Laurent Couvidou
źródło
3

W granicach twojego pierwotnego pytania jedną z opcji byłoby rozbicie list na Akcje zamiast Typów podobnych do tego, co masz. Na przykład, miałbyś opcję „ List<HasAI>i” dla, List<Collidable>a kiedy tworzysz nowy obiekt, dodaje się on do dowolnej listy akcji, której potrzebuje, kiedy obiekt zostanie zniszczony, wówczas usuwa się z tych list. Obiekt może znajdować się na wielu listach.

Drugim krokiem tej opcji jest refaktoryzacja klas z hierarchii na taką, która korzysta z interfejsów, więc typ HasAI jest klasą, która implementuje interfejs IBrains jako przykład. Dopasowanie tego, że List<HasAI>tylko obiekty wymagają interfejsu IBrains.

To powinno pomóc w uporządkowaniu części złożoności.

Patrick Hughes
źródło
2

Myślę, że musisz zrobić abstrakcję renderowania we własnych klasach, myślę, że jeden dla gracza, a drugi dla wroga (a może tylko jeden dla gracza, a następnie stwórz instancję dla gracza i wroga - nie w 100% pewna twojego projektu gry).

Możesz użyć wzorca gościa, aby mechanizm renderujący zapętlał różne obiekty i decydował, co narysować, co może być mniej skomplikowane.

nycynik
źródło
2

Korzystanie z klasy bazowej i poleganie na polimorfizmie jest bardzo dobrym pomysłem. Ale istnieją pewne alternatywne podejścia. Warto przeczytać dwa artykuły Noela Llopisa. Ostatnio przyglądałem się projektowaniu zorientowanemu na dane i sądzę, że ma on swoje zalety.

Artykuły są tu i tutaj . Może uprościć twój kod nieco bardziej niż polimorfizm. Ale jak wszystko YMMV, spójrz i sprawdź, czy pasuje do tego, co próbujesz osiągnąć. Polimorfizm wykorzystuje dziedziczenie, a DOD wykorzystuje agregację, zarówno zalety, jak i wady, więc wybierz swoją truciznę.

Britchie
źródło
1

Możesz to zrobić, wykorzystując OOP, a zwłaszcza polimorfizm.

Zasadniczo musisz stworzyć klasę podstawową, z której odziedziczą wszystkie podmioty gry. Ta klasa bazowa, jest jak najbardziej abstrakcyjna, będzie zawierała takie funkcje, jak Creation, Update i Być może Destroy.

Następnie pozyskujesz wszystkie pozostałe przedmioty gry z tej klasy. Prawdopodobnie będziesz musiał dodać refleksję do swojego kodu, jeśli Twój język go nie obsługuje, aby zrobić bardziej zaawansowane rzeczy, ale można tego uniknąć, jeśli wiesz, jak poprawnie uporządkować swoje dziedzictwo.

Marlock
źródło
1
Już to zrobił - wszystkie jego klasy są dziećmi GameObject. Musi tylko zamienić swoją serię list w jedną listę GameObjects.
SomeGuy,