Klasy pochodne wymagające różnych argumentów dla tej samej dziedziczonej metody.
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!

Klasy pochodne wymagające różnych argumentów dla tej samej dziedziczonej metody.

AutorWiadomość
» 2018-02-14 22:52:50
OK, sorry za niezrozumiałe słowa, po prostu takich słów używam na co dzień, ale postaram się pisać prościej.

Jeżeli rozumiesz angielską definicję słowa callback to o to mi chodziło, jeżeli nie to możesz poszukać też hasła delegate (delegat).
Generalnie z callbackami maż jeden poważny problem a mianowicie musisz zadbać o to aby obiekt który bindujesz w momencie wywołania metody istniał, ale jeżeli bindujesz się do obiektu który sam zawierasz w sobie to nie ma tego problemu. Nie wiem czy jasno napisałem, ale na przykład, jeżeli klasa Barrel zawiera w sobie collision object i ty do tego collision objectu bindujesz metodę klasy Barrel to nie powinno być problemu bo collision object nie może istnieć bez swojego "właściciela". Bindowanie to przypisanie obiektu i jego funkcji do zmiennej (sprawdź sobie std::function i std::bind).

Handlowanie już Saran opisał.

Ja swoją wiedzę czerpię głównie z pracy w Unreal'u, ale system kolizji jest na tyle prosty i uniwersalny, że większość silników implementuje go w podobny sposób (mam tu na myśli sam core systemu kolizji a nie jakieś dodatkowe funkcje czy optymalizacje). Z tego co wiem to silnik Redów obsługuje kolizje podobnie do unreal'a i cryengine chyba też.

Kanały kolizji także Saran opisał, od siebie dodam, że jeżeli już bym się decydował na dodanie ich do mniejszego projektu to raczej nie pozwoliłbym na ustawienie więcej niż jednego kanału dla obiektu.

I tak jak pisałem, dodanie nowego obiektu nie powinno wymuszać na tobie modyfikowania kodu dot. kolizji. Dużo też zależy od tego ile funkcji dodasz do klasy bazowej, jeżeli to będzie tylko prosty GameObject to będziesz musiał castować.

Po co jest tu this? Czyżby po to, by przekazać go do callbacka obiektu, z którym kolidujemy:

this jest też po to żeby wywołać metodę na odpowiednim obiekcie.

Mogę ci pokazać jak zrobiłem coś podobnego dla inputu w jakimś moim starym projekcie
C/C++
Spaceship::Spaceship()
{
    //...
   
    InputManager::BindAction( InputManager::ActionName::LEFT, std::bind( & Spaceship::MoveLeft, this, std::placeholders::_1 ) );
    InputManager::BindAction( InputManager::ActionName::RIGHT, std::bind( & Spaceship::MoveRight, this, std::placeholders::_1 ) );
    InputManager::BindAction( InputManager::ActionName::SHOOT, std::bind( & Spaceship::ShootProjectile, this, std::placeholders::_1 ) );
}

/////////////////////////

class InputManager
{
public:
    enum class ActionName { LEFT, RIGHT, SHOOT };
   
    /** Binds function to action name (function will be called when key assigned to actionname will be pressed) */
    static void BindAction( ActionName actionName, const std::function < void( float ) >& function );
   
private:
   
    static std::multimap < ActionName, std::function < void( float ) >> mActionNamesFunctions; // holds all functions assigned to ActionName (allows many functions to one action name)
};

Polecam ci ściągnąć (darmowego) unreal'a i pobawić się nim, na pewno sporo się nauczysz takich podstawowych rzeczy, ogólnej architektury silnika i powiązań między kluczowymi klasami.

Możesz tez podać swojego githuba to jak będę miał wolną chwilę to zerknę i może coś dopiszę ;)
P-169404
Temat założony przez niniejszego użytkownika
» 2018-02-16 00:33:55
Ok, ja się więc doedukuje, bo póki dotychczas nie wiedziałem nawet, że istnieje coś takiego jak bindowanie albo function object:PP
Generalnie z tego co widze muszę wejść w magiczny świat biblioteki standardowej. Tymczasem nie do końca wiem, co zrobić z tematem. Chyba najlepszym rozwiązaniem będzie okresowe zamknięcie go, żeby nie wisiał na stronie z tematami. Otworzę go kiedy będę wiedział więcej.

Zostawie go jeszcze na dzień czy dwa, bo może ktoś będzie coś chciał dodać (ewentualnie administrator każe go po prostu nieodwołalnie zamknąć, choć wolałbym nie, bo rozwinął się tu ciekawy wątek :d).


edit:
To ja jeszcze tylko odnośnie tych kanałów kolizji. Jak wspomniał @Saran, mamy kilka cech, np:
żyjące, pradawne, latające, zniszczalne.

Czy jest to tylko do sprawdzania czy coś ma z czymś kolizje? Jeżeli wspomniany Wojtek stoi na ziemi, to nie ma mieć kolizji z latające. Oczywiście, to ma sens, ale jak rozumiem, to ich jedyna funkcja?
W jaki sposób to implementować? enum'y które przechowują te cechy:
C/C++
enum rodzaj { latajace, zyjace, naziemne, pradawne,...};

I np. Pradawna latajaca ryba przechowuje te 3 cechy (pradawny, latający, żyjący).

Wojtek natomiast ma naziemny, żyjący.
Prócz tego ma zestaw "rodzajów obiektów" z którym (jak pisał Saran) nie może kolidować:
C/C++
std::vector < rodzaj > niemozliwaKolizja;
Jeśli PradawnaLatajacaRyba ma jakąś ceche, która jest w tym wektorze, to kolizji nie zajdzie.

Jak myślicie, dobry to plan?
P-169441
» 2018-02-18 22:12:08
Jeżeli nie będziesz miał masy kolidujących ze sobą obiektów albo wielu zróżnicowanych relacji kolizji to ja bym się tymi kanałami nie przejmował.

Ale mój pomysł polegał na tym, że każdy collision object ma swój typ kolizji oraz informacje jak ma reagować na inne typy kolizji, czyli np. coś takiego

C/C++
void Bullet::Init()
{
    CollisionObject.SetCollisionType( ECollisionType::Projectile );
    CollisionObject.SetResponseToChannel( ECollisionType::Player, true );
    CollisionObject.SetResponseToChannel( ECollisionType::InvisibleWall, false );
}

i wtedy w systemie kolizji musisz to odpowiednio obsłużyć, czyli pewnie jakoś sprawdzać kolizje z tymi z którymi mogą kolidować.

Jakiś pseudokod:
C/C++
for( CollisionClass & CollisionObject1: CollisionObjects )
{
    for( CollisionClass & CollisionObject2: CollisionObjects )
   
    if( CollisionObject1.isCollisionPossible( CollisionObject2.GetCollisionType() ) )
    {
        // rest of collision checking
    }
}
}
P-169506
Temat założony przez niniejszego użytkownika
» 2018-02-24 02:06:23
Witam ponownie :D

Wiem już na czym polega mechanizm bindowania itd.
natomiast mam pytanie odnośnie tego kodu:

C/C++
void SimpleBullet::Init()
{
    CollisionObject.RegisterForCollision( this, & SimpleBullet::OnCollision );
}

Więc tu przesyłamy metodę klasy SimpleBullet i wskaźnik na obiekt tej klasy, to jest jasne. Chcesz sobie tę metodę wraz z obiektem na rzecz którego ona ma być
wywoływana zbindować.
Ale jak wygląda definicja RegisterForCollision?
Próbowałem takową utworzyć na podstawie CollisionObject.RegisterForCollision( this, & SimpleBullet::OnCollision );
Oznacza to, że wyglądałaby tak:
CollisionObject::RegisterForCollision( GameObject * ptr, std::function < void( GameObject * HitObject, const Vector & HitLocation ) > )
jednak jakiegoś powodu u mnie nie działa poniższy program:

C/C++
class T
{
public:
    void Tfun( int a ) { std::cout << "a = " << a << "\n"; }
};

class CO // CollisionObject
{
public:
    std::function < void( int ) > f;
    CO( T * ptr, std::function < void( int ) > fun ) { f = std::bind( fun, ptr, std::placeholders::_1 ); } // przekazuje metodę i obiekt do zbindowania
};
int main()
{
   
    T obj;
    CO c( & obj, & T::Tfun ); // analogiczne do Twojego CollisionObject.RegisterForCollision( this, & SimpleBullet::OnCollision );, za this robi &obj


Natomiast ten - jak najbardziej:

C/C++
class CO // CollisionObject
{
public:
    std::function < void( int ) > f;
    CO( std::function < void( int ) > fun ) { f = fun; } // przesylamy juz "gotowa" funkcje
};
int main()
{
   
    T obj;
    CO a( std::bind( & T::Tfun, & obj, std::placeholders::_1 ) ); // bindujemy
}
A przecież nie różnią się niczym, prócz tego, że w pierwszym przypadku bindujemy w konstruktorze a w drugim przesyłamy do konstruktora wynik std::bind.
P-169591
» 2018-02-24 16:14:58
To co ja napisałem było tylko przykładem, nie musisz pisać dokładnie tak samo.

Musisz poczytać o różnicy pomiędzy wskaźniku na funkcje i wskaźniku na funkcje składową. Możesz tez poczytać, bardziej jako ciekawostka historyczna, o ptr_fun, mem_fun, mem_fun_ref i innych z functional z c++98 http://www.cplusplus.com​/reference/functional/.

Generalnie polecam jednak używać std::bind, mniej się narobisz.
P-169593
1 2 « 3 »
Poprzednia stronaStrona 3 z 3