Obiektowość -> wywołanie klasy w tej klasie.

0

Witam jestem początkującym w programowaniu obiektowym, więc proszę o wyrozumiałość, ale nie wiedziałem jak szukać danej frazy.

Mam kod gry w której stworzyłem klasę silnika by kod główny gry był w pełny sposób autonomiczny, klasa silnika korzysta z klas pocisku, gracza i wrogów które korzystają ze zmiennych klasy Engine np. gracz ustawia swoją pozycję pod względem wielkości okna z klasy Engine. Aktualnie wykorzystuje po prostu globalną zmienną Engine dzięki której klasy zewnętrzne mają dostęp lecz chciałbym aby klasa Engine mogła wywoływać metody tych klas używając swojego własnego obiektu wewnątrz klasy.

Utworzyłem w deklaracji klas w atrybutach przekazywanych wskaźnik na obiekt klasy Engine, ale nie wiem w jaki sposób wewnątrz klasy Engine przekazać obiekt do atrybutów. Dla wyjaśnienia:

Konstruktor pocisku ->

Bullet::Bullet(Engine_Main &Engine)
{
   Engine_Main Engine = &Engine; //Nie wiem tutaj też czy dobrze wskazuje
}

a wewnątrz klasy Engine_Main podczas tworzenia pocisku nie wiem jak odnieść się by klasa sama przypisywała temu swój obiekt, w którym aktualnie wykonywana jest operacja.

5

Jeśli klasa pocisku musi korzystać z klasy całego silnika gry, to ewidentnie masz poważne błędy projektowe.

0

Klasa pocisku korzysta z okna gry które jest zdefiniowane w klasie.

Czyli mam użyć tylko okna z klasy engine zamiast całej klasy? Wtedy będzie w porządku czy nadal będzie to błąd projektowy?

Klasa pocisku także korzysta z vectora który przechowuje pociski w klasie Engine.

3

Pocisk powinien być pociskiem – nic więcej. Pociskiem powinna zarządzać klasa obiektu, do którego on należy lub klasa, która nim steruje. Jeśliby przedstawić w postaci drzewa zależności pomiędzy obiektami w silniku, to pocisk powinien być którymś jego liściem – znajdować się na samym dole.

0
void Enemy::Move(vector<Enemy> &enemies, float elapsedTime)
{
    for (int i = 0; i < enemies.size(); i++)
    {
        enemies[i].position.x -= speed * elapsedTime;
        enemies[i].position.y = enemies[i].enemyObj.getPosition().y;
    }
}

Czyli taki kod jak powyżej nie wchodzi w grę? Mimo iż jest on wywoływany tylko przez klasę silnika?

3

klasa Enemy to powinien być rodzaj obiektu (1000 obiektów = 1000 instancji klasy Enemy), a nie jakiś menedżer obiektów, który zarządza wszystkimi obiektami danego rodzaju.

Chyba, że robisz jakieś ECS, to wtedy okej, jeśli robisz to w jakimś celu i świadomym tego, że nie jest to codzienne podejście do OOP. Ale przypuszczam, że podobnie jak w przypadku jednego wątku sprzed kilku dni* to po prostu obiektówka na pół gwizdka, a w rezultacie takie programowanie proceduralne opakowane w klasy (nie to, żeby programowanie proceduralne było zawsze złe, ale cóż...)

0

Czyli to Engine ma zarządzać obiektami klasy enemy itp. ?
Nie będzie to tworzyło bałaganu w kodzie metod klasy Engine?

Np. w metodzie Engine::Draw(); mam statycznie rysować po kolei wszystkie obiekty vectorów player, enemy, bullet itp. ? Mam dziwne wrażenie, że narobi to bałaganu w metodzie.

3
Błękitny Krawiec napisał(a):

Czyli to Engine ma zarządzać obiektami klasy enemy itp. ?

Klasa silnika ma zarządzać wszystkimi obiektami znajdującymi się w nim.

Nie będzie to tworzyło bałaganu w kodzie metod klasy Engine?

Teraz masz bałagan, w dodatku spory.

Np. w metodzie Engine::Draw(); mam statycznie rysować po kolei wszystkie obiekty vectorów player, enemy, bullet itp. ?

Nie wiem co rozumiesz przez „statyczne rysowanie”, ale chodzi o to, że renderowaniem obrazu ma się zajmować klasa znajdująca się wysoko (lub najwyżej) w hierarchi opakowania. Silnik wie co się w nim znajduje, wie które obiekty znajdują się w zasięgu wzroku. Pocisk powinien wiedzieć tylko o sobie (czym jest i jakie ma parametry) i jednocześnie nie powinien wiedzieć do kogo należy, bo mu to do niczego nie jest potrzebne.

3

Np. w metodzie Engine::Draw(); mam statycznie rysować po kolei wszystkie obiekty vectorów player, enemy, bullet itp. ?

Silnik nie musi(i nie powinien) mieć świadomości tego, czy dany obiekt należy do klasy enemy czy do klasy bullet. Może traktować wszystkie obiekty tak samo, jako np. GameObject - i to jest ten rzadki przypadek, w którym dziedziczenie się przydaje, bo jeśli wszystkie obiekty gry, czy to bullet czy enemy będą dziedziczyć z jednej klasy bazowej (albo implementować jeden bazowy interfejs) o przykładowej nazwie GameObject to możemy je potraktować tak samo przez silnik (i np. wrzucić do jednej listy)

Co do rysowania natomiast - to zadaj sobie pytanie, czy każdy obiekt rysujesz tak samo, czy inaczej? Jeśli "rysowanie" polega zawsze na tym samym, np. na wyświetleniu obrazka i np. enemy będzie miał przypisany obrazek enemy.png a bullet będzie miał przypisany obrazek bullet.png to nie ma sensu, żeby obiekty same się rysowały. Można po prostu do każdego obiektu dodać właściwość/pole z nazwą pliku graficznego. Wtedy silnik może sam sobie to renderować na podstawie nazwy pliku.

Gorzej jeśli każdy obiekt by się renderował inaczej (ale to też można by jakoś ogarnąć, tylko należałoby pomyśleć nad tym, co się chce dokładnie osiągnąć). Od biedy silnik mógłby udostępnić obiektowi jakieś API do rysowania (ale pytanie, czy to w ogóle potrzebne).

Ale generalnie warto oddzielać logikę gry (np. liczba energii, szybkość, pozycja w świecie, komendy typu "atakuj") od technicznych szczegółów implementacji (jakim jest rysowanie na ekranie) i tym się powinien zajmować silnik.

Czyli to Engine ma zarządzać obiektami klasy enemy itp. ?

Nie. Silnik raczej powinien zarządzać obiektami gry, nie mając świadomości do jakiej klasy należą.

0

Macie może jakiś przykład prostego silnika gry który jedynie rysuje obiekty w oknie i umożliwia np. poruszanie postacią?
Najlepiej oparty na sfml, ale inne bilbioteki też mogą być. Pomogłoby mi to lepiej zrozumieć rozmieszczenie zadań po klasach i silniku.
Poza tym dziękuje za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0