Kolizja Rectangle w XNA

Kolizja Rectangle w XNA
TE
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 3 lata
  • Postów:61
0

Problem trapi mnie od bardzo długiego czasu i nie jestem pewien czy jestem za młody żeby to zrozumieć, czy po prostu pomijam jakąś ważną część, ale za nic nie mogę zrozumieć jak napisać prostą, działającą kolizję używając Rectangle - jak w prostych platformówkach, pomijając fakt skoków itp. - po prostu, aby jeden Rectangle, używając WSAD mógł poruszać się po TiledMap'ie zbudowanej z Rectangle oznaczających ściany - i przez nie, normalnie w świecie - nie przenikał.

Kopiuj
List<Rectangle> levelHitboxes = new List<Rectangle>();

Lista Rectangle oznaczających ściany. Każdy rectangle ma swoją pozycję w świecie i wymiary równe 32x32.

Kopiuj
Vector2 position; // Pozycja gracza
Rectangle playerHitbox; // Hitbox gracza

Gracz również jest Rectangle'm o wymiarach 32x32, gdzie jego X i Y oznacza Vector2 position.

Próbowałem wiele razy umieścić kolizję, która wygląda mniej więcej tak:

Kopiuj
// Dla skrótu - pozycje ściany
int RLEFT = rect.X;
int RRIGHT = rect.X + rect.Width;
int RUP = rect.Y;
int RDOWN = rect.Y + rect.Height;
// Dla skrótu - pozycje gracza
int PLEFT = playerHitbox.X;
int PRIGHT = playerHitbox.X + playerHitbox.Width;
int PUP = playerHitbox.Y;
int PDOWN = playerHitbox.Y + playerHitbox.Height;
Kopiuj
foreach(Rectangle rect in levelHitboxes){
if(playerHitbox.Intersects(rect)){
    if(PRIGHT > RLEFT && PLEFT < RLEFT){
        // Collision RIGHT
        collisionRight = true;
    }
    if(PLEFT < RRIGHT && PRIGHT > RRIGHT){
        // Collision LEFT
        collisionLeft = true;
    }

    if(PDOWN > RUP && PUP < RUP){
        // Collision DOWN
        collisionBot = true;
    }
    if(PUP < RDOWN && PDOWN > RDOWN){
        // Collision TOP
        collisionTop = true;
    }
}
}

Kolizja świruje tylko w dwóch osiach (X i Y), gdy działa tylko jedna, wszystko jest jak należy. Przykładem jest dotknięcie góry ściany przez dół gracza i nagle odpala się kolizja Left Right i Top, gdzie gracz nie dotyka swoją prawą oraz lewą stroną niczego.
Czytałem sporo na temat kolizji w Internecie, może nie dokładnie, sam nie wiem, ale nigdy nie znalazłem sensownego rozwiązania. Nie chcę zbytnio korzystać z dodatkowych bibliotek czy silników, chciałbym poznać sam dogłębne rozwiązanie tego problemu, bo wydaje mi się, że nie jest aż takie trudne, ale brakuje mi tego "klucza".

dam1an
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
  • Postów:1589
0

Jeśli dobrze rozumiem to powinno być tak:

Kopiuj
if(PRIGHT>=RRIGHT){
        // Collision RIGHT
        collisionRight = true;
    }
    if(PLEFT<=RLEFT){
        // Collision LEFT
        collisionLeft = true;
    }
 
    if(PDOWN>=RDOWN){
        // Collision DOWN
        collisionBot = true;
    }
    if(PUP<=RUP){
        // Collision TOP
        collisionTop = true;
    }
TE
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 3 lata
  • Postów:61
0

@dam1an
Nie koniecznie to zadziała. Oto przykład z zastosowaniem Twojego sposobu:
user image

Jako że mamy pętle foreach, to dla każdego Rectangle sprawdzana jest kolizja.
Gracz jest zaznaczony na biało.
Załóżmy że aktualnie badamy przypadek 1, gdzie aktywna ściana zaznaczona jest na czerwono, a ściana z przypadku 2 na szaro. Gracz się z nim styka, czyli następuje kolizja która jest zaznaczona niebieską linią, wtedy collisionRight = true; i tutaj jest OK.
Teraz sprawdzamy przypadek 2, gdzie aktywna jest inna ściana zaznaczona na czerwono, a ściana z przypadku 1 na szaro. Gracz się z nią nie styka, ale z instrukcji

Kopiuj
if(PRIGHT >= RRIGHT)

wychodzi prawda, ponieważ gracz jest dalej niż prawa strona ściany, dlatego nadal mamy collisionRight = true; mimo, że kolizji nie ma.

Ten problem jest zarówno w instrukcji if(playerHitbox.Intersects(rect)) jak i bez niej. Z "Intersects" problem jest taki, iż nagle wszystkie zmienne (collision: top, bot, left, right) stają się True i gracz nie może ruszyć się w ogóle.

Dlatego dodaje jeszcze PLEFT < PRIGHT, żeby sprawdzić czy gracz w ogóle dotyka ściany.

edytowany 3x, ostatnio: Temessis
Sopelek
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 8 lat
  • Lokalizacja:Kraków
  • Postów:467
0

Jest mnóstwo informacji o sprawdzaniu takiej kolizji na internecie. Wystarczy poszukać w google.
Możesz też sobie to rozrysować na kartce i pomyśleć, bo akurat kolizje takich obiektów są trywialne do sprawdzenia.

Najlepiej sprawdzaj kiedy kolizja NIE występuje.

edytowany 1x, ostatnio: Sopelek

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.