[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 » |