[SDL, C++] Kolizja w klasie
Ostatnio zmodyfikowano 2011-12-29 22:56
mostrom Temat założony przez niniejszego użytkownika |
[SDL, C++] Kolizja w klasie » 2011-12-29 22:49:33 Witam! Napisałem sobie klasę do obsługi ludzika w grze typu Dyna. Ponieważ dążę do uniwersalności, zamieściłem tam też funkcję zwracającą kierunek, w który ludzik nie może pójść, gdy nastąpi kolizja. Męczę się już z tym drugi dzień, i za każdą próbą jestem tylko o krok od doskonałości, jednak ten krok okazuje się nie do ogarnięcia przezemnie Klasa wygląda mniej więcej tak: class Ludek { public: void idz(); void pokaz( SDL_Surface * gdzie ); int kolizja( SDL_Rect blok ); void podajKierunek( int kierunek ) { _kierunek = kierunek; } int kierunek() { return _kierunek; } void update(); private: int _kierunek; int _posX; int _posY; int _wysokosc; int _szerokosc; SDL_Rect reLudek; SDL_Surface * surLudek; };
int Ludek::kolizja( SDL_Rect blok ) { int goraA, goraB; int dolA, dolB; int prawoA, prawoB; int lewoA, lewoB; goraA = _posY; goraB = blok.y; dolA = _posY + _wysokosc; dolB = blok.y + blok.h; prawoA = _posX + _szerokosc; prawoB = blok.x + blok.w; lewoA = _posX; lewoB = blok.x; if( dolA > goraB && goraA < dolB ) { if( prawoA >= lewoB && lewoA < lewoB ) return 2; else if( lewoA <= prawoB && prawoA > prawoB ) return 3; } if( prawoA > lewoB && lewoA < prawoB ) { if( dolA >= goraB && dolA < dolB ) return 0; if( goraA <= dolB && dolA > dolB ) return 1; } return 5; }
void Ludek::idz() { switch( _kierunek ) { case 0: reLudek.y += 1; break; case 1: reLudek.y -= 1; break; case 2: reLudek.x += 1; break; case 3: reLudek.x -= 1; break; default: break; } }
SDL_Rect bloczek; while( !koniec ) { if( keystate[ SDLK_RIGHT ] ) { if( ludek.kolizja( bloczek ) != 2 ) ludek.podajKierunek( 2 ); else continue; ludek.idz(); } if( keystate[ SDLK_LEFT ] ) { if( ludek.kolizja( bloczek ) != 3 ) ludek.podajKierunek( 3 ); else continue; ludek.idz(); } if( keystate[ SDLK_UP ] ) { if( ludek.kolizja( bloczek ) != 1 ) ludek.podajKierunek( 1 ); else ludek.podajKierunek( 0 ); ludek.idz(); } if( keystate[ SDLK_DOWN ] ) { if( ludek.kolizja( bloczek ) != 0 ) ludek.podajKierunek( 0 ); else ludek.podajKierunek( 1 ); ludek.idz(); } }
Nie mam pojęcia dlaczego (pewnie przez continue;), ale gdy się naciśnie naraz klawisz w górę i w dół i przy tym występuje kolizja, to moj ludek idzie w bok o jakies 20000 pixeli Raz zamknąłem metodę Ludek::kolizja() i używałem jej w publicznej metodzie Ludek::idz(); Jednak ta metoda okazałą się doskonałą tylko dla jedenj przeszkody. Kiedy próbowałem to samo rozwiązanie zastosować do tablicy kafelków SDL_Rect mapa[13][13], to kolizja nie działałą jak należy. Dlatego podałem wyżej wymieniony kod, bo uważam że jest najbardziej czytelny; |
|
malan |
» 2011-12-29 22:55:29 Pytanie natury organizacyjnej: czemu zmieniłeś kolorowanie składni (po mojej poprawce)? :/ |
|
mostrom Temat założony przez niniejszego użytkownika |
» 2011-12-29 22:56:55 Przepraszam, najwyraźniej edytowaliśmy w tym samym momencie, bo musiałem dodać kilka linijek :( Poradziłem sobie z tym problemem, zmieniając moment wykrycia kolizji na styczne zetknięcie się powierzchni. Nowa treść funkcji Ludek::kolizja(SDL_Rect przeszkoda): if( prawoA > lewoB && lewoA < prawoB ) { if( dolA == goraB && goraA < goraB ) return 0; if( goraA == dolB && dolA > dolB ) return 1; } if( dolA > goraB && goraA < dolB ) { if( prawoA == lewoB && lewoA < lewoB ) return 2; if( lewoA == prawoB && prawoA > prawoB ) return 3; }
return 5; Teraz chciałbym całą klasę uruchomić dla mapy kafelkowej, gdzie ludek porusza się po pikselach, i nie wiem jak zamieścić odpowiednie pętle for. Narazie mam taki niepoprawnie działający algorytm if( keystate[ SDLK_RIGHT ] ) { ludek.podajKierunek( 2 ); for( int y = 0; y < 13; y++ ) { for( int x = 0; x < 13; x++ ) { if(( x + 1 ) % 2 == 0 &&( y + 1 ) % 2 == 0 ) { if( ludek.kolizja( mapa[ x ][ y ] ) != ludek.kierunek() ) { if( x == 11 && y == 11 ) ludek.idz(); } } } } } Chciałbym, aby ludek się zatrzymał na przeszkodzie. Tymczasem kod powyżej zwraca kolizję tylko na chwilkę i idzie dalej. |
|
« 1 » |