Spróbuję ci pomóc wypisując w punktach parę rad/wyjaśnień:
Po pierwsze.. zakładamy, że w kodzie ma się znaleźć:
> Klasa EnemyManager
Przechowująca wskaźniki do klasy Enemy oraz wywołująca ich główne metody
> Klasa Enemy (Klasa bazowa)
Zawierająca podstawę przeciwnika tj. zmienne (np. punkty życia), główne metody wirtualne (np. Init(), Live(), Draw())
> Dziedzice klasy Enemy (Klasy dziedziczące)
Określające konkretne zachowanie dla konkretnego przeciwnika oraz posiadające róże dodatkowe zmienne i metody typu: TimeToExplosion, Shoot().
--------------------------
Teraz pora na wyjaśnienie mechanizmów:
class EnemyManager()
> vector<Enemy*> Container; //Zawiera wszystkich przeciwników
> void Live() //Funkcja wykonująca się w logice.. Dla każdego przeciwnika wywołuje jego główną metodę logiki.. coś w stylu: Container[i]->Update();
> void DestroyEnemy() //Podobnie jak Live().. tyle, że w tym wypadku sprawdza czy metoda Enemy.IsDead() zwraca true czy false.. jeżeli zwraca true to z kontenera usuwamy danego delikwenta.. przy odrobinie sprytu można połączyć tą metodę z poprzednią.
> void Draw() //Podobnie jak wcześniej.. metoda ta wywołuje metodę Draw() dla wszystkich przeciwników.. Znajduje się ona jednak w renderze, a nie w logice!
> void AddNewEnemy(Enemy *NewEnemy) //Dodaje nowego przeciwnika do kontenera.. można jej używać np. w ten sposób: EnemyManager.AddNewEnemy(new WaterGolem());
> ~EnemyManager() // "Delete'uje" wszystkie obiekty w kontenerze
class Enemy
> //Jakieś zmienne, które będzie zawierał każdy przeciwnik
> virtual void Live() //Po prostu logika przeciwnika (ta metoda może być pusta)
> virtual void Draw() // -\\- render przeciwnika (ta metoda może być pusta)
> virtual ~Enemy() // Destruktor (w klasie bazowej) MUSI być wirtualny (może być pusty)
> virtual bool IsDead() // Zwraca true jeżeli przeciwnik "nie żyje"/powinien zostać usunięty ze kontenera w menadżerze
class WaterGolem : public Enemy
> //Dodatkowe zmienne potrzebne dla tego konkretnego typu przeciwnika
> void Live() //j.w. jednak tym razem nie może być pusta
> void Draw() // -\\-
> void IsDead() // Jeżeli warunek życia zmienił się (np. dodałeś czas do śmierci przeciwnika) to należy tą metodę tutaj zadeklarować.. jeżeli wyglądała by tak samo jak w klasie bazowej to nie musisz jej tu tworzyć.
--------------------------
Jak to ma działać?
Mając gotową klasę EnemyManager wywołujesz jej główne metody (tj. Live(), Draw()) w odpowiednich miejscach głównej pętli logiki.. teraz gdy będziesz chciał dodać nowego przeciwnika to wystarczy, że zapiszesz np. EnemyManager.AddNewEnemy(new WaterGolem(51,15)) //Gdzie 51,15 to pozycja gdzie ma się pojawić.. operator new zwraca wskaźnik dlatego taki zapis jest w 100% akceptowalny.
Oczywiście do tego wszystkiego należy jeszcze dodać chociażby kontrolę ilość przeciwników (aby nie dodawało więcej niż jakaś określona liczba.. co za dużo to nie zdrowo), albo przesyłanie odpowiednich zmiennych do menadżera by wiedział na czym renderować przeciwników.. czy też funkcję sprawdzającą kolizję z graczem.. ale to już jest zupełnie inny temat. Mam nadzieję, że pomogłem i rozwiałem twoje wątpliwości.
↧
Odpowiedź: Lista przeciwników z użyciem polimorfizmu - jak w odpowiedni sposób dodawać obiekty?
↧