zapalka121 Temat założony przez niniejszego użytkownika |
[Allegro] Kolizje 2D » 2010-09-10 06:56:53 Witam, piszę gierkę typu bomberman. I jak to często się zdarza na tym forum, mam problem z kolizjami :)
Otóż, postawiłem klocka i chcę żeby nie dało się na niego wejść z żadnej strony. narazie mam zrobione aby nie dało się od góry i od prawej strony klocka, lecz nie za ładnie to wygląda, ponieważ postać zostaje odpychana od tego klocka.
I niewiem także jak zrobić aby kolizja była sprawdzana z każdej strony postaci. Aktualnie jest ona sprawdzana tylko pod nogami ludka.
Oto kod:
bool kolizja( float x1, float y1, float s1, float w1, float x2, float y2, float s2, float w2 ) { if( x1 + s1 >= x2 && x1 <= x2 + s2 && y1 + w1 >= y2 && y1 <= y2 + w2 ) return( true ); return( false ); }; #include <allegro.h> #include <string> #include <vector>
int main() { allegro_init(); install_keyboard(); set_color_depth( 16 ); set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0 ); BITMAP * klocki = NULL; BITMAP * niebo = NULL; BITMAP * ludek = NULL; BITMAP * bufor = NULL; BITMAP * platfa = NULL; int zycie = 100; bufor = load_bmp( "bufor.bmp", default_palette ); if( !bufor ) { set_gfx_mode( GFX_TEXT, 0, 0, 0, 0 ); allegro_message( "Nie moge utworzyc bufora !" ); allegro_exit(); return 0; } klocki = load_bmp( "klocki.bmp", default_palette ); ludek = load_bmp( "ludek.bmp", default_palette ); niebo = load_bmp( "niebo.bmp", default_palette ); platfa = load_bmp( "platforma.bmp", default_palette ); if( !ludek ) { set_gfx_mode( GFX_TEXT, 0, 0, 0, 0 ); allegro_message( "Nie moge zaladowac obrazka Ludek !" ); allegro_exit(); return 0; } int ludek_w = 0; int klocki_x = 0, klocki_y = 450; int platfa_x = 100, platfa_y = 250; float ludek_ruch_y = 0; float ludek_ruch_x = 0; int niebo_x = 0, niebo_y = 0; float ludek_y = 370, ludek_x = 100; textprintf_ex( klocki, font, 20, 20, makecol( 0, 0, 0 ), - 1, "Zycie: %d", zycie ); while( !key[ KEY_ESC ] ) { if( key[ KEY_RIGHT ] ) { ludek_x += 2; } if( key[ KEY_LEFT ] ) { ludek_x -= 2; } if( key[ KEY_UP ] ) { ludek_y -= 2; } if( key[ KEY_DOWN ] ) { ludek_y += 2; } int predkosc1 = 0; int predkosc2 = 0; if( kolizja( ludek_x, ludek_y, 55, 50, platfa_x, platfa_y, 15, 98 ) == true && ludek_y == platfa_y ) { predkosc1 =- 10; predkosc2 = 0; } if( kolizja( ludek_x, ludek_y, 55, 50, platfa_x, platfa_y, 15, 98 ) == true && ludek_y == - 250 ) { predkosc1 = 10; predkosc2 = 0; } if( kolizja( ludek_x, ludek_y, 66, 1, platfa_x, platfa_y, 94, 40 ) == true && ludek_x == 110 ) { predkosc1 = 0; predkosc2 =- 10; } if( kolizja( ludek_x, ludek_y, 15, 20, platfa_x, platfa_y, 15, 50 ) == true && ludek_x == - 100 ) { predkosc1 = 0; predkosc2 = 10; } ludek_y += predkosc1; ludek_x -= predkosc2; rest( 1 ); clear_to_color( bufor, makecol( 150, 255, 0 ) ); blit( niebo, bufor, 0, 0, niebo_x, niebo_y, niebo->w, niebo->h ); masked_blit( platfa, bufor, 0, 0, platfa_x, platfa_y, platfa->w, platfa->h ); masked_blit( klocki, bufor, 0, 0, klocki_x, klocki_y, klocki->w, klocki->h ); masked_blit( ludek, bufor, 0, 0, ludek_x, ludek_y - ludek->h, ludek->w, ludek->h ); blit( bufor, screen, 0, 0, 0, 0, 640, 480 ); } if( key[ KEY_ESC ] ) { allegro_message( "No dobra..." ); } destroy_bitmap( klocki ); destroy_bitmap( niebo ); destroy_bitmap( ludek ); destroy_bitmap( bufor ); allegro_exit(); return 0; }
END_OF_MAIN();
Z góry thx. |
|
ison |
» 2010-09-10 07:34:35 dlaczego ładujesz bufor z pliku? wystarczy samo: bufor = create_bitmap( 640, 480 );
Jeśli zamieszczasz większy projekt to daj link do całej paczki. Uprościło by to sprawę bo nie trzeba byłoby tworzyć tych wszystkich bitmap. zrobienie kolizji między tobą a jednym klockiem zajęło ci 20 linii, wyobrażasz sobie co będzie w późniejszym etapie? Jeśli jeszcze nie czytałeś o programowaniu obiektowym to koniecznie przeczytaj. Utwórz sobie klasę klocek w której będziesz trzymał między innymi pozycję każdego klocka. Wszystkie ich pozycje możesz np. wczytywać z pliku i wrzucać do vektora klas klocek. Wtedy wystarczy że przy sprawdzaniu kolizji przelecisz forem przez wszystkie i sprawdzisz czy gracz z jakimkolwiek koliduje. |
|
dmx81 |
» 2010-09-10 08:49:19 problem odpychania:
jesli nacisniesz strzalke w lewo, postac przesuwa sie o 2, tak? wiec skaczesz sobie o te 2 w lewo, nagle jest klocek - postac pamieta, ze ma przesunac sie o 2, dodatkowo jest kolizja - postac teraz ma ludex_x+2-10 - wiec po napotkaniu kolizji, odepchnie ja o 8 w druga strone - jesli nie chcesz zeby odpychanie nastapilo to:
albo sprawdzaj, czy nie ma kolizji, dopiero dodaj przesuniecie np (jesli nie kolizja, to ludek_x+=2)
drugi sposob, zostaw jak masz, ale zmien wartosc predkosc z 10 do 2, co spowoduje zerowanie sie - czyli brak przesuniecia.
swoja droga tez bym przerobil na
class obiekt { int x, y, s, w; }; [ / code ] teraz tworzysz postac przez: obiekt ludek; mozesz dac odpowiedni konstruktor w klasie lub ludek.x =, ludek.y = itd a pozniej np [ code src = "C++" ] obiekt * wsk_na_obiekt; const int ilosc_przeszkod = 7; std::vector < obiekt *> wektor_obiektow; tabx[ ilosc_przeszkod ] = { 1, 2, 3, 4, 5, 6, 7 };
for( int i = 0, i < ilosc_przeszkod, i++ ) { wsk_na_obiekt = new obiekt; obiekt->x = tabx[ i ] obiekt->y = taby[ i ] wektor_obiektow.push_back( wsk_na_obiekt ); }
a pozniej jak kolega wyzej pisal, sprawdzasz tez petla for caly wektor (od [0] do
[wektor.size()] czy ktorys z obiektow ma kolizje |
|
SeaMonster131 |
» 2010-09-10 15:23:55 Albo po prostu, jeżeli każdy klocek ma takie same obramowanie (w jednakowym kolorze) to po prostu daj np: if( key[ KEY_UP ] && getpixel( bufor, pozycja_ludek_x, pozycja_ludek_y ) != makecol( 220, 110, 170 ) ) { pozycja_ludek_x--; }
Wtedy robisz każdy klocek z jakąś ramką (itp) o kolorze 220,110,170 i masz kolizje :) |
|
dmx81 |
» 2010-09-10 18:13:50 albo jeszcze jedna w allegro funkcja sprawdzajaca, czy ludek.x jest w bitmapie (czyli czy wszedl w klocek) nie pamietam dokladnie nazwy, trzeba poszukac w dokumentacji allegro, nazywala sie chyba is_inside_bitmap (....) i tam podawales o jaki punkt sie pytasz i w jakiej bitmapie (mozesz sprawdzic dla kazdego punktu nalezacego dla ludka (for(int i=ludek_x;i<ludek_s;i++){for(int j=ludek_y;j<ludek_w;j++){...}} ale wiadomo, dla prostych gierek jest ok, ale jakby mial tak sprawdzac wieksze obiekty, to troszke czasu mu na to zejdzie - ale tak tylko informuje, ze taka funckja jest i mozna z jej skorzystac (np sprawdzajac tylko rogi prostokata postaci xysw) |
|
zapalka121 Temat założony przez niniejszego użytkownika |
» 2010-09-11 16:02:53 Oto cały projekt. Trochę w nim pozmieniałem, i teraz wyskakują mi błędy typu: 'x' undeclared... tak samo y,s,w Link: http://www.speedyshare.com/files/24204635/Gra.rar |
|
ison |
» 2010-09-11 16:12:59 jeśli nie umiesz sobie poradzić z takimi błędami to musisz powtórzyć podstawy C++ nikt za ciebie całego projektu nie napisze |
|
dmx81 |
» 2010-09-11 21:35:29 niestety kolega wyzej ma racje - musialbys popracowac nieco, bo z kodu widac, ze nie do konca rozumiesz programowanie obiektowe. widze, ze poprawiles nieco kod o ludek.c, ale to nie wszystko, ale postaram sie wyjasnic o co chodzi:
po pierwsze tworzy sie klase tak jak to zrobiles, ale zeby dobrze zrozumiec co to klasa - klasa to tak jakby pojemnik - i zmienne jakie tam wypiszesz, takie bedzie mial kazdy obiekt tej klasy, czyli jesli zadeklarowales klase przez class Cpostac{...}, to znaczy, ze utworzyles dopiero cos jakby "szablon, wzor" - teraz tworzysz dopiero obiekt przez : Cpostac nazwa1; teraz nazwa1 posiada takie zmienne jak nazwa.x, nazwa1.y itd - posiada wszystko to, co zadeklarowales w Class Cpostac . - w tym miejscu w ramach cwiczen proponuje ci dopisac w deklaracji klasy zmienna typu BITMAP - abys kazdemu obiektowi mogl przypisac obrazek czyli w nawiasie dopisz: BITMAP obrazek (tak jak int x), a tworzac postac, zadbaj o jej nazwa1.obrazek....
to poki co tyle, jakby co pisz, jak znajde znow troszke czasu to napisze |
|
« 1 » |