Broń, strzelanie, platformówka

Broń, strzelanie, platformówka
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Witam, próbuje zrobić strzelanie postaci. Gdy próbuje strzelić wyskakuje błąd, który mówi, że wyszedłem za range wektora.
Posiadam klasę Entity, która odpowiada za pozycje postaci itd., jak i za broń, a tak naprawdę kule. Klasa GameplayScreen odpowiada za to co się dzieje na mapie, wczytuje tile map, postacie i obrazy. Stworzyłem dwuwymiarowy wektor Entity std::vector<std::vector<Entity*>> vEntity; i metodę, która "tworzy broń". Tą metodę wywołuję w czasie, kiedy przycisnę dobry przycisk, w tym czasie gra się kraszuje i wyskakuje błąd.
Tak wygląda kod : https://pastebin.com/0DmUdsRd

System::getManager() zwraca klasę, która wczytuje np. menu, opcje, nową gre itd. ->getGame() zwraca instancje do GameplayScreen ->getGame()->getPosX() zwraca pozycje x mapy (mapa się rusza jeśli pozycja postaci jest większa niż pozycja ekranu). vEntity[i][j]->getBlockID() zwraca numer obrazka, w tym przypadku 4, ustawione w klasie PlayerGun oznacza grafikę kuli.

Projekt wzorowany https://github.com/jakowskidev/uMario_Jakowski

Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
0

W metodzie Update usuwasz elementy vectora, po którym iterujesz. Najlepiej w takich przypadkach iterować w odwrotnej kolejności (od końca).


🕹️⌨️🖥️🖱️🎮
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Od końca, to znaczy?

Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
0

To znaczy, że w pętli zamiast od pierwszego indeksu (0), iterujesz od ostatniego indeksu.


🕹️⌨️🖥️🖱️🎮
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0
Kopiuj
	for (int i = vEntity.size() - 1; i >= 0; i--)
	{
		for (int j = vEntity[i].size() - 1; j >= 0; j--)
		{
			if (vEntity[i][j]->entityState == -1)
			{
				delete vEntity[i][j];
				vEntity[i].erase(vEntity[i].begin() + j);
				continue;
			}
		}
	}

Coś takiego? Tylko tego punktu zrobić tak, czy dla całej metody? Co to zmienia? Nadal w sumie jest błąd.

edytowany 1x, ostatnio: donpedro5555
2

Jest tak, bo masz warunek na usunięcie, więc nie wszystko jest usuwane po kolei. Podczas usuwania iteratory są "invalidowane" co oznacza, że nie mozesz ich już używać. Nejlepiej użyć funkcji std::remove_if:

Kopiuj
for (int i = vEntity = 0; i < vEntity.size(); i++)
    {

        vEntity[i].erase(
            std::remove_if(
                vEntity[i].begin(), 
                vEntity[i].end(), 
                [](const Entity* entity){ return entity->entityState == -1; }
            ), 
            vEntity[i].end());
    }

Wówczas powinno zadziałać.
Więcej informacji na temat remove i remove_if masz tutaj.

gośćabc
int i = vEntity = 0; i < vEntity.size(); i++ co to w ogóle jest
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Oki, wszystko fajnie, tylko nadal pokazuje się błąd: "(vector subscript out of range");. Tutaj coś jest skopcone z dodawaniem do vectora w metodzie addPlayerGun(int, int, int);

edytowany 1x, ostatnio: donpedro5555
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
0

źle, że odwołujesz się do tego vectora przez magic number.

Skoro piszesz nową aplikację, to może skorzystaj ze smart pointerów?

Czy musisz pisać własny silnik, czy po prostu nie znasz innych opcji, żeby stworzyć własną grę?


🕹️⌨️🖥️🖱️🎮
gośćabc
źle, że odwołujesz się do tego vectora przez magic number. to jest pewnie ten problem, ale skąd on ma wiedzieć o co Ci chodzi
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Szczerze, nie jestem jeszcze w tych sprawach tak obeznany, chce po prostu się czegoś nowego nauczyć. NIe chce żeby było to na jakiejś "prostackiej" zasadzie, chociaż skoro nie działa to nie jest na żadnej zasadzie :D. Nie rozumiem ostatniego pytania.

edytowany 1x, ostatnio: donpedro5555
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
0
donpedro5555 napisał(a):

Nie rozumiem ostatniego pytania.

To co teraz robisz jest dość "niskopoziomowe". Jeśli nikt Cię nie zmusza, żebyś pisał grę "na czysto", to poleciłbym zapoznanie się z Unity 3D.
Tam po prostu dodajesz obiekty na scenę i one po prostu się renderują ;) Jeśli to gra 2D, to jak chcesz mieć obiekty renderowane w odpowiedniej kolejności, po prostu ustawiasz dla obrazków (sprite'ów) odpowiedni sorting layer i sorting order.

Jak tworzysz nowy obiekt, to nie musisz się martwić o to, czy dodasz go do odpowiedniego wektora. Po prostu dodajesz go gdzieś w drzewie obiektów, ewentualnie ustawiając obiekt rodzica.

Jeśli nie chcesz być programistą silników, tylko chcesz stworzyć grę, to przy obecnych technologiach nie ma sensu, żebyś zawracał sobie głowę tym co teraz robisz ;)


🕹️⌨️🖥️🖱️🎮
edytowany 4x, ostatnio: Spine
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Aaaa, nie lubię pisać w unity czy ue4. Nie sprawia mi to frajdy. Lubie sobie właśnie posiedzieć nad takim czystym kodem, jest to przyjemne dla mnie. I jakby udało mi się kiedyś tak rozwinąć, to silnik fajnie też by było zrobić. Podoba mi się takie spędzanie czasu.
Jak wyglądałoby w takim razie coś "fajniejszego" i działającego do rzeczy typu przeciwnicy, strzelanie, itp.?

edytowany 3x, ostatnio: donpedro5555
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
1
donpedro5555 napisał(a):

Jak wyglądałoby w takim razie coś "fajniejszego" i działającego do rzeczy typu przeciwnicy, strzelanie, itp.?

Najważniejsza jest możliwość osiągnięcia rzeczy podstawowych dla współczesnych gier (kolizje, fizyka, wyświetlanie, udźwiękowienie), zachowując porządek w projekcie (im mniej kodu piszemy, tym mniej błędów generujemy).

  1. Strzelanie.
  • Robisz sobie w edytorze prefab pocisku,
  • dołączasz do niego skrypty: collider (np. prostokąt, i zaznaczasz, że jest triggerem), rigidbody (ciało fizyczne), twój własny nowy skrypt dla pocisku;
  • w skrypcie dla pocisku piszesz kod, co pocisk ma robić w przypadku kolizji, czyli metodę OnTriggerEnter2D() (zmniejszenie życia wroga, pokazanie efektu cząsteczkowego, puszczenie dźwięku), oraz metodę Start(), która ustawia pociskowi wektor kierunku przemnożony przez prędkość pocisku;
  • w ustawieniach fizyki w macierzy kolizji klikasz sobie, że obiekty na warstwie pocisków mogą kolidować tylko z wrogami;
  • kiedy gracz chce strzelić, wystarczy dodać pocisk na scenę funkcją Instantiate(prefabPocisku, pozycjaPocisku, obrótPocisku);, pozycję i obrót można pobrać z obiektu, który dodajemy jako dziecko obiektu broni gracza. Skrypt pocisku zadba o to, żeby pocisk leciał i kolidował z wrogami ;)
  1. Przeciwnicy
    Podobnie jak przy pociskach, można zrobić prefaby przeciwników, które tylko dodajemy na scenę w odpowiednich miejscach, wspomagając się edytorem.

  2. Inne rzeczy
    W Unity każdy build na PC jest wyposażony w menu wyboru rozdzielczości. Do builda dołączane są wszystkie pliki potrzebne do uruchomienia gry.
    Efekty cząsteczkowe, animowanie modeli 3D, podział gry na sceny/poziomy. W Unity to zrobisz, nie pisząc żmudnego, wadliwego kodu.


🕹️⌨️🖥️🖱️🎮
edytowany 8x, ostatnio: Spine
D5
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 7 lat
  • Postów:7
0

Jak w takim razie powinna wyglądać taka funkcja Instantiate? Trochję szukałem w necie, nie znalazłem wnętrza tej metody żeby zrobić wzorzec i spróbować go w swoim kodzie.

edytowany 1x, ostatnio: donpedro5555
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:2 minuty
  • Postów:6659
0

Przerób sobie jakiś kurs Unity, zobacz co Instantiate robi. Zobacz jak wygląda drzewo obiektów w edytorze. Z doświadczeniem wyniesionym z innych silników, będziesz miał podstawy by zaprojektować własny.

Dostęp do kodu Unity też można uzyskać...


🕹️⌨️🖥️🖱️🎮
edytowany 1x, ostatnio: Spine

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.