Mam trudności z uzyskaniem ruchomego prostokąta, który mógłby zderzyć się z więcej niż jednym prostokątem.
Używam SFML i ma przydatną funkcję o nazwie, intersects
która bierze 2 prostokąty i zwraca przecięcia. Mam wektor pełen prostokątów, z którym chcę, aby mój ruchomy prostokąt kolidował. Pętlę przez to za pomocą następującego kodu (p jest ruchomym prostokątem).
IsCollidingWith
zwraca bool, ale także używa SFML intersects
do opracowania skrzyżowań.
while(unsigned i = 0; i!= testRects.size(); i++){
if(p.IsCollidingWith(testRects[i]){
p.Collide(testRects[i]);
}
}
i rzeczywisty Collide()
kod:
void gameObj::collide( gameObj collidingObject ){
printf("%f %f\n", this->colliderResult.width, this->colliderResult.height);
if (this->colliderResult.width < this->colliderResult.height) {
// collided on X
if (this->getCollider().left < collidingObject.getCollider().left ) {
this->move( -this->colliderResult.width , 0);
}else {
this->move( this->colliderResult.width, 0 );
}
}
if(this->colliderResult.width > this->colliderResult.height){
if (this->getCollider().top < collidingObject.getCollider().top ) {
this->move( 0, -this->colliderResult.height);
}else {
this->move( 0, this->colliderResult.height );
}
}
a IsCollidingWith()
kod to:
bool gameObj::isCollidingWith( gameObj testObject ){
if (this->getCollider().intersects( testObject.getCollider(), this->colliderResult )) {
return true;
}else {
return false;
}
Działa to dobrze, gdy Rect
na scenie jest tylko 1 . Jednak, gdy jest ich więcej niż jeden Rect
, powoduje to problem podczas opracowywania 2 kolizji jednocześnie.
Masz pomysł, jak sobie z tym poradzić? Przesłałem film na YouTube, aby pokazać mój problem. Konsola po prawej stronie pokazuje szerokość i wysokość skrzyżowań. Na konsoli widać, że próbuje obliczyć 2 kolizje naraz. Myślę, że właśnie tutaj powstaje problem.
Wreszcie poniższy obraz wydaje się dobrze ilustrować mój problem:
źródło
collider
obiekty są zwracane przezthis->getCollider()
zaktualizowane przezthis->move()
?Odpowiedzi:
Twój obraz ilustruje jeden z wielu problemów z próbą użycia wypukłych kształtów - szczególnie prostokątów - do symulacji płaskiej powierzchni, takiej jak podłoga. Algorytm prowadzi do zablokowania postaci na wewnętrznych krawędziach kształtów tworzących podłogę.
Prostym rozwiązaniem jest sprawdzenie tylko kolizji pionowej, popraw to, a następnie ponownie sprawdź kolizję poziomą. Chyba że spadniesz i ześlizgniesz się po ścianie, w takim przypadku najpierw sprawdź, czy nie występują kolizje w poziomie. Skąd wiesz, kiedy sprawdzić, który pierwszy? Możesz to zrobić na podstawie tego, który składnik prędkości jest większy (jeśli ruch poziomy jest większy, najpierw sprawdź zderzenia pionowe, w przeciwnym razie sprawdź zderzenia poziome).
Tym, co może być jeszcze prostsze - i bardziej wydajne - jest wygenerowanie listy krawędzi dla twojego świata. Oznacza to, że dla twoich pudeł tworzących podłogę ustaw flagę wskazującą, że tylko ich górna krawędź jest w rzeczywistości zderzalna, a następnie zignoruj kolizje z innymi krawędziami. Nie będziesz w stanie użyć do tego procedury kolizji SFML, ale szczerze mówiąc, kolizje pudełkowe to prawdopodobnie najłatwiejszy fragment kodu, jaki kiedykolwiek napiszesz w grze. Ta technika działa szczególnie dobrze, jeśli twój świat jest wyrównany do siatki. Sprawdziłbym doskonałe samouczki Metanet (http://www.metanetsoftware.com/technique.html/) dotyczące tej techniki.
Będziesz miał wiele innych problemów, próbując zbudować prostą platformówkę 2D, taką jak ty. Zdecydowanie najlepszy zasób, jaki widziałem w tym kontekście, to następujący, który powinieneś przeczytać, a następnie przeczytać ponownie:
http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/
źródło
Być może prostym rozwiązaniem byłoby sprawdzenie kolizji z każdym prostokątem i cofnięcie się w przeciwnym kierunku, dopóki nie zostaną wykryte kolizje. Jeśli to rozwiąże problem, wdrożenie również powinno być dość proste.
źródło
Nie sądzę, że obliczenie 2 kolizji to problem, tylko problem z wydajnością. Aby kolizja została poprawnie obsłużona, konieczne może być jej dwukrotne przetestowanie. Korzystając ze schematu, pomyśl, że jeśli A jest najpierw testowane względem B, to będzie musiało zostać przetestowane również na innych polach i może równie dobrze kolidować z innym.
Mam nadzieję, że to jest pomocne?
źródło
To naprawdę nie jest optymalna metoda, powinieneś próbować ustalić najwcześniejszy moment, kiedy lub pierwszy punkt wzdłuż ścieżki ruchomych obiektów, w których dochodzi do kolizji, i przenieść obiekty do tej pozycji (lub pozycji w obliczonym czasie), próbując poprawne w oparciu o pozycje penetrujące po ruchu jest bardzo problematyczne, ale możesz użyć obecnego procesu z niewielką zmianą. Po prostu sprawdzaj, czy nie ma kolizji.
Zauważ, że zdarzają się sytuacje, w których doprowadzi to do nieskończonej pętli (pomyśl o sytuacji, w której przeniesienie pudełka z kolizji skutkuje inną kolekcją, a przeniesienie pudełka z tej kolizji powoduje przeniesienie go z powrotem do tej samej pozycji zderzenia, co poprzednio)
źródło