Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Allegro] Kolizje 2D

Ostatnio zmodyfikowano 2010-09-11 21:35
Autor Wiadomość
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:
C/C++
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 );
   
    //clear_to_color(screen, makecol(300,300,300));
   
    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 ] )
    {
       
        //obsluga klawiszy;
        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.
P-21881
ison
» 2010-09-10 07:34:35
dlaczego ładujesz bufor z pliku?
wystarczy samo:
C/C++
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.
P-21882
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
C/C++
class obiekt
{
    int x, y, s, w;
    //inne
};
[ / 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; //wsk na obiekt
const int ilosc_przeszkod = 7;
std::vector < obiekt *> wektor_obiektow;
tabx[ ilosc_przeszkod ] = { 1, 2, 3, 4, 5, 6, 7 };
//tak samo y,s,w
for( int i = 0, i < ilosc_przeszkod, i++ )
{
    wsk_na_obiekt = new obiekt;
    obiekt->x = tabx[ i ]
    obiekt->y = taby[ i ] //ew. odpowiedni konstruktor i bedzie wtedy wsk=new obiekt(tabx[i],.....)
    wektor_obiektow.push_back( wsk_na_obiekt ); //tu trzymasz swoje utworzone obiekty
}
a pozniej jak kolega wyzej pisal, sprawdzasz tez petla for caly wektor (od [0] do
[wektor.size()] czy ktorys z obiektow ma kolizje
P-21883
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:
C/C++
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 :)
P-21887
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)
P-21889
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
P-21907
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
P-21908
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
P-21914
« 1 »
  Strona 1 z 1