Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Przechowywanie obiektów gry w kontenerach tablicy (wektorach)

Ostatnio zmodyfikowano 2015-04-17 09:35
Autor Wiadomość
Patrycjerz
Temat założony przez niniejszego użytkownika
Przechowywanie obiektów gry w kontenerach tablicy (wektorach)
» 2015-04-17 08:22:12
Witam państwa, jestem tu nowy, więc proszę o wyrozumiałość :)

Tworząc grę natrafiłem na problem. Problem jest natury projektowej, nie technicznej.

Przechowuję moje obiekty ze sceny w wektorze i ma on typ klasy bazowej wszystkich obiektów na scenie. Jeśli naładuję ten wektor obiektami z klasy bazowej, jak i pochodnych, to na końcu wektor, mając typ klasy bazowej, uniemożliwi, przy wyciągnięciu z niego obiektu klasy pochodnej, wywołanie jej metod, ponieważ typ obiektu jest zawarty w typie wektora.

I tu mam pytanie. Jak magazynować obiekty z różnych klas? Jeśli wszystkie dziedziczą z jednej klasy, to czy nie ma możliwości wygodnego odwoływania się do metod klas pochodnych z wektora klasy bazowej. Może trzeba wykorzystać rzutowanie?

Jeśli zbytnio zagmatwałem, to mogę wytłumaczyć to inaczej :)
P-131032
akwes
» 2015-04-17 08:36:39
Owszem, można wykonać rzutowanie, jednak aby to zrobić należy mieć pewność co do typu obiektu (albo nieefektywnie rzutować przez wszystkie typy za pomocą dynamic_cast). Możemy również wstawić enum określający nam rodzaj klasy ale wtedy po co nam polimorfizm?

Trzymanie obiektów gry w jednym kontenerze jest szkodliwe dla wydajności. Należy takie obiekty trzymać w osobnych kontenerach albo przynajmniej sortować ten jeden według typu. Jeżeli nie masz problemów z wydajnością to możesz dalej mieć jeden wektor wskaźników ogólnych oraz kilka list wskaźników określonego typu. Dla wszystkich obiektów wykonasz ogólne akcje zaś dla obiektów wyspecjalizowanych wyspecjalizowane akcje. Jeżeli Twoje ogólne obiekty wymagają interakcji z wyspecjalizowanymi typami to masz gdzieś błąd projektowy w postaci źle rozłożonych odpowiedzialności i kod nie zachowuje się polimorficznie. Wtedy musisz pomyśleć nad projektem klas, które przechowujesz aby były bardziej "uniwersalnie używalne" :)
P-131034
Patrycjerz
Temat założony przez niniejszego użytkownika
» 2015-04-17 08:47:11
Jeśli mam klasę Obiekt - klasa bazowa, oraz np. Gracz i Przeciwnik - klasy pochodne, to jeśli trzymam je w jednym wektorze, to automatyzacja kodu jest prosta (jedna pętla for), ale jeśli będę trzymał różne typy obiektów w różnych wektorach, to automatyzacja będzie utrudniona, a także przy dodaniu kolejnej klasy pochodnej będę musiał tworzyć nowy wektor i zmieniać metody. Jaki jest mój błąd w rozumieniu tego? Pragnę, aby metody odpowiedzialne np. za kolizje były uniwersalne, a tak to nie są.
P-131035
Quirinnos
» 2015-04-17 08:55:56
Cześć,
tak jak piszę Akwes, takie przetrzymywanie jest mało wydajne, mało tego - jest mało uniwersalne. Ogólnie przy grach powinno unikać się dziedziczenia, bo przy większych projektach robi się bałagan i problem z rozbudową. Bo możesz mieć klasę Jednostka, po której dziedziczą obiekty statyczne, jak i dynamiczne. W statycznych masz np Klasę drzewo, kamień itp. W dynamicznych wilka, orka, demona. O co jak będziesz chciał zrobić demona drzewnego? Urobisz się po pachy. Jeśli masz trochę czasu, chęci i samozaparcia zalecam poczytanie o entity component system.
http://cowboyprogramming.com​/2007/01/05​/evolve-your-heirachy/
http://www.randygaul.net/2013​/05/20​/component-based-engine-design/
P-131036
akwes
» 2015-04-17 08:56:02
Dlaczego potrzebujesz rzutować w przypadku kolizji?

C/C++
class GameObject {
public:
    virtual Rect getColisionRect() = 0;
};

class Player
    : public GameObject
{
public:
    virtual Rect getColisionRect() { return Rect( x, y, 10, 10 ) };
};

class BigPlayer
    : public GameObject
{
public:
    virtual Rect getColisionRect() { return Rect( x, y, 100, 50 ) };
};

bool isColiding( Rect & a, Rect & b );

Jeżeli dziedziczysz tylko po to, aby trzymać w jednym kontenerze to postępujesz źle. Dziedziczyć powinieneś dla wspólnego interfejsu, dlatego też nie powinno być mowy o różnicach w interfejsie.
P-131037
Patrycjerz
Temat założony przez niniejszego użytkownika
» 2015-04-17 09:04:14
Dzięki Quirinnos za pomoc, ale te artykuły po angielsku nie przejdą, bo po prostu nie umiem go wystarczająco, ale może kiedyś :)

A co do tych metod wirtualnych, to działają one nawet przy jednym wektorze? I czy tworzenie interfejsu klas, jako klasa abstrakcyjna, jest dobrym posunięciem konstrukcyjnym (aby kod był bardziej uniwersalny)?
P-131038
akwes
» 2015-04-17 09:05:52
Interfejsy powinny być abstrakcyjne a zachowanie obiektów polimorficzne. Pamiętaj aby w wektorze trzymać wskaźniki na obiekt a nie obiekty.
P-131039
Patrycjerz
Temat założony przez niniejszego użytkownika
» 2015-04-17 09:09:49
Bo jeśli będę trzymał w wektorze obiekty, to pomysł z interfejsem nie zadziała? I chyba ostatnie pytanie. Jeśli będę miał kilka wektorów dla kilku klas, to jak jest to z tą uniwersalnością kodu. Muszę przekazywać w argumencie wszystkie wektory, np. do metody sprawdzającej kolizję? Myślę, że można to lepiej zrobić. Proszę o jak najwięcej porad, bo najwyraźniej nie jestem jeszcze dobrze zaznajomiony z obiektowością (pierwszy tak duży projekt) :)
P-131040
« 1 » 2
  Strona 1 z 2 Następna strona