Kolizja - sprawdzenie poprawności i ocena

0

Witam! Trochę ostatnio ściągnąłem kolizję z tego projektu http://lukaszjakowski.pl/project,20,mario-cpp.html zmieniając parę rzeczy.
Wydaje mi się jednak, że nie jest to dobry pomysł na wykrywanie kolizji i jak najszybciej powinienem go zmienić (nie wiem skąd takie myślenie).
Dlatego przyszedłem się zapytać czy powinienem coś z tym robić, a jeśli tak, to jak. Przyznam się szczerze, że nie umiem tego zrobić i nie mam bladego pojęcia jak zacząć. Dlatego właśnie trochę "ukradłem" ten sposób, bo jest prosty i działa.

https://github.com/DonTweaks/Collision-and-player-phys

0

płaskie repo :(

0

Ja jak bawiłem się grami 2d ale w JavaScripcie i Javie to uczyłem się z tych stron:
http://informatyka.wroc.pl/node/477
http://szymonsiarkiewicz.pl/poradniki/goto/kolizje/kolizje-w-grach-2d/
http://szymonsiarkiewicz.pl/poradniki/goto/kolizje/kolizje-w-grach-2d-czesc-2/

Ogólnie zasada polega na tym, aby każdy obiekt był opisany matematyczną funkcją - niekoniecznie liniową(wtedy dochodzą if'y), tak aby dało się obliczać czy funkcja ta nie weszłą w kolizję z inną funkcją.
Najprostszym sposobem są oczywiście AABB - tak jak w mario, i jest to nic innego jak definicja kwadratu. Najczęściej przybliża się obiekty okręgami i elipsami.

Ale jest masa artykułów na ten temat, wpisz w google frazę: "programming collision detection 2d"

0

Myślisz, że tego nie robiłem? Ogólnie regułę znam w sensie, że np.

for(int y = 0 ; y < map.size(); ++y)
    for(int x = 0; x < map[y].size(); ++x)
        {
            int mapX = x * 32;
            int mapY = y * 32;
            itd.

            int playerPosX = player.getPosX();
            .. itd

            if(checkCollision(mapX, mapY, mapW, mapH, playerPosX, playerPosY, ..., playerH)
            {
                teraz sprawdzam ifami po kolei każdy róg i ustawiam pozycje gracza
                if(playerX <= mapW)
                    player.setPosX(mapW);

            }
        }


checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
{
    if(x2 <= w1 && w2 >= x1 && ... && h2 >= y1)
    {
        return true;
    }
    return false;
}

Tylko problem polega na tym, że takie coś mi nie działa. Nie wiem kurka wódka dlaczego właśnie. Stoję w miejscu już chyba od ponad miesiąca i niczego nie mogę znaleźć.

Edit. Tutaj jest jak to działa

Jak widać, nie działa. Teraz napisałem to na szybko, żeby nie zmieniać na marne tyle kodu.
Czasami widzę jak postać chodzi wolniej. Ale to nadal nie jest kolizja.

0

No coś masz popsute, musisz nauczyc sie debugować kod, lol jak napisaleś ten kod skoro od miesiaca nie naprawileś takiej rzeczy?

Zacznij od tego, że napiszesz funkcje, która w pliku zapisze sprawdzone pozycje czyli wszystkie te twoje: int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2, wraz z jakimś identyfikatorem np ze sprawdzana jest kolizja z podłogą czy cymś, i wtedy zacznij sobie na kartce sprawdzać, sprawdź który warunek powinien sie wykonać a nie wykonuje, moze do funkcji trafiają złe dane lub coś?

A z ciekawośco to jak próbowałeś to debugować przez ten miesiac?

To na pewno twój kod? Po tym jak udeżasz w tą cegłę pozycja X gracza sie zatrzynuje i prawdopodbnie to jest przyczyną, co nie zmienia faktu, że powinieneś umieć to naprawić skoro napisaleś taki kawał kodu :)

0

Już na samym początku napisałem, że wziąłem to od http://lukaszjakowski.pl/project,20,mario-cpp.html i pozmieniałem trochę, np. pozbyłem się singletonu, zbędnych pointerów itd.
Który kod napisałem? Ten ?

for(int y = 0 ; y < map.size(); ++y)
    for(int x = 0; x < map[y].size(); ++x)
        {
            int mapX = x * 32;
            int mapY = y * 32;
            itd.

            int playerPosX = player.getPosX();
            .. itd

            if(checkCollision(mapX, mapY, mapW, mapH, playerPosX, ..., playerH)
            {
                teraz sprawdzam ifami po kolei każdy róg i ustawiam pozycje gracza
                if(playerX <= mapW)
                    player.setPosX(mapW);

            }
        }

checkCollision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
{
    if(x2 <= w1 && w2 >= x1 && ... && h2 >= y1)
    {
        return true;
    }
    return false;
}

Nie było trudno to napisać.
Tak jak już pisałem wyżej, rozumiem na jakiej zasadzie działa kolizja.
Dane są dobre, bo wypisuje sobie je na ekranie.
Jak debugowałem? W sumie to nie debugowałem (szukałem w internecie trochę, coś pisałem, ale raczej nic ciekawego, a jak już miałem dość, to pisałem inne rzeczy, np. przeciwników), bo co ma debugowanie do kolizji, skoro tutaj nawet nie wykrywa jej.

Tak na marginesie kolizja gracz-przeciwnik, przeciwnik-przeciwnik działa dobrze kiedy zloopuje w podobny sposób jak próbowałem z mapą.
Może to tak nie chce działać, bo działam na intach, tzn. loopuje przez collisionMap, które są intami, a przeciwnicy są obiektami. Nie wiem czy rozumiesz o co mi teraz chodzi.

0

Dane są dobre, bo wypisuje sobie je na ekranie.

Nie są dobre bo widze je na ekranie :) Twój licznik X zatrzymuje sie po udeżeniu w cegłe...

Jak debugowałem? W sumie to nie debugowałem (szukałem w internecie trochę, coś pisałem, ale raczej nic ciekawego, a jak już miałem dość, to pisałem inne rzeczy, np. przeciwników), bo co ma debugowanie do kolizji, skoro tutaj nawet nie wykrywa jej.

Debugowanie jest właśnie po to aby znaleźć błąd. Więc musisz sie tego nauczyc

0

Ale chyba nie o tych samych danych mówimy. Teraz mówie o tej kolizji, która loopuje przez inty, a nie o tej co podałem na githubie. Tam licznik X ma się zatrzymywać po uderzeniu w cegłę. Kolizja podana w kodzie githuba działa, tylko tak jak podałem na początku: "Wydaje mi się jednak, że nie jest to dobry pomysł na wykrywanie kolizji i jak najszybciej powinienem go zmienić (nie wiem skąd takie myślenie).".

0

Nie są dobre, bo po 1 twój X zatrzymuje sie na 610, a jesli idziesz w lewi i dane są dobre, to złe dane przekazujesz o pozycji sciany. Skoro warunek jest dobry i sprawdziłeś go na kartce, to przekazujesz złe dane do funkcji. Wyświetl te dane do pliku i upewnij sie co tam trafia.

0

zatrzymuje się na 610 bo to połowa mapy - playerW (Gracz zatrzymuje się na 1280/2 - playerW i wtedy mapa zaczyna się przesuwać w zależności od tego jaką player ma velX). Wtedy odejmuje od tego wyniku pozycję mapy i dostaje pozycję gracza. Mapa jest np. na -200.

610 -(-200) = 810 -> gracz jest na x = 810

Dane są dobre.
Zajmijmy się tym, że moge chodzić tylko do x = 610 (czy na jakiejkolwiek innej liczbie, żeby działało gdziekolwiek). Nieważne gdzie nie pójdę, czy w lewo, gdzie już nie ma takich rzeczy jak odejmowanie pozycji mapy (bo jest zawsze 0) to nadal kolizja nie będzie działać.

screenshot-20171205190046.png

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