Algorytm Kolizji

0

Witajcie!
Mam mały problem z algorytmem kolizji, ale najpierw może opiszę zaistniałą sytuację:
Napisałem program w Delphi (DelphiX)- 'edytor map kafelkowych', z pomoca ktorego wstawiam obrazki 25px/25px (mapa 24obrazki /32 obrazki). Oprócz wstawiania, ich pozycja zapisywana jest do tablicy 32:24. Później tablica zapisywana jest do binarnego pliku.
Drugi program - gra, odczytuje tablicę, oraz rysuje taką mapę. (mapa- ruch gracza-mapa itd robi za odswiezanie, ale mniejsza o to). Zrobiłem funkcję kolizja, która sprawdza czy piksel na który chce wjechać gracz należy do kwadracika 'przejezdnego' (if mapa[x div 25][y div 25]=puste...)... I do tego momentu wszystko pięknie działa.
Problem:
Jak zrobić, aby tak samo zachowywały się obiekty, nie zintegrowane z mapą, które pojawiają się/znikają/przesuwają się (np: jakiś stworek, gracz drugi, np: nagle utworzony na wskutek jakiegoś działania kamień itp.) - aby nie można było na nie wjechać... Byłbym wdzięczny za pomoc jeśli chodzi o opisanie algorytmu...

0

Zrób 2 warstwy. Na jednej masz stałe obiekty, a na drugiej ruchome.

//
Raczej myślałem o czyms innym, nie o samym DelphiX, o którym nie mam zółtego pojęcia. Masz w tablicy zapisaną mapę, ona jest stała i niezmienna. Stwórz sobie drugą taka samą tablicę (albo dodaj wymiar do tablicy w której trzymasz mapę), w której bedą tylko obiekty zmienne, łącznie z postaciami graczy. Coś na zasadzie sprajtów (jesli pole jest równe zero to znaczy, że jest wolne).

Jesli nie zrozumiałem, o co własciwie chodzi, to równiez sorki.

0

Nie <ort>rozumie </ort>dokładnie jak to tam masz, ale jak robiłem gierki kiedys na kalkulator to miałem podobny problem miałem mapę zapisaną w postaci macierzy, no i teraz w zależności co tam była za liczba to takie było odpowiednie pole. Nie musisz robić drugiej warstwy (o ile masz podobne rozwiązanie) możesz po prostu sumować wartości. Najlepiej binarnie by było to zilustrować

01 - stan B
10 - stan C
11 - stan B i C

Binarnie było by o tyle lepiej że mógłbyś stosować operatory logiczne jak and i or ... Jeśli nie trafiłem w sedno to sorx

0

b0bik - zrozum, że moja mapa działa. Gracz 'zatrzymuje się' na ścianie, ale nie wiem jak to mam zrobić dla innych obiektów ruchomych... Bo mapa jest 24/32 a jak koleś stanie na skrzyżowaniu, między 4 kwadratami mapy to co ? Chyba nie zrobię, że wszystkie 4 kwadraty są 'NieDoWjechania'...
Co do warstw - wiesz może jak operować na nich z poziomu DelphiX (nie czysty DirectX) :/?? Btw - jak już będę je miał -... co dalej ? nie zmienia to faktu, ze jakos muszę powiedziec graczowi, ze nie moze wjechac na inna postac...

0

Pomiń zupełnie istnienie mapy w tej kwestii. Imho powinieneś sprawdzać czy odległość jednego "playera" od drugiego nie jest mniejsza od zadanej wcześniej wartości (nie wiem jakie kształty mają te twoje postaci, ale najprościej uznać że są to koła i sprawdzać czy odległość nie jest mniejsza od r1 + r2)

0

Theriel nie do konca wiem o co Ci chodzi gdyz wyjasniasz to niezbyt jasno, albo ja po prostu slabo jarze :-D ale jesli choc troche Cie zrozumialem to sprawa wyglada tak:

Masz mapke i nagle na tej mapce pojawia sie jakis obiekt,, np kamien.
Masz gracza ktory porusza sie po tej mapce i nie chcesz zeby on wlazl na kamien.
Jesli tak to widze tu dwa rozwiazania:

  1. Dorzucasz do definijcji mapy jeszcze jedna wlasciwosc a mianowcie typ terenu. Nastepnie sprawdzasz pozycje

if (mapa[x div 25][y div 25]=puste) and (mapa.TypTerenu=kamien) then TwojaProcedura.

2.Wykorzystujesz detekcje kolizji zaimplementowana w DelphiX.
overridujesz procedure TSprite.DoMove i w niej sprawdzasz kolzizje twojego spritea np ludzika ze spritem np kamienem.

//dodane

Poczytalem jeszcze te Twoje posty i rozumiem ze Ty chcesz aby jakies inne stworkiplynnie przesuwaly sie po planszy? Czyli np o 1 pxiel na milisekunde? Jesli tak to pozostaje Ci tylko druga metoda...

o to chodzilo?

Pozdrawiam,

Wodzu

0

Heh nie wiem, ale ja chyba naprawdę jakiś ciepuch jestem, bo wytlumaczyc nie potrafie... Obiekt stały nie stanowi dla mnie najmniejszego problemu, gdyż może on zajmować kwadrat, który w tablicy oznaczę jako nie do naruszenia. Ok. Problem natomiast, stanowi dla mnie obiekt, który się porusza, ponieważ jak stanie np: pomiędzy 2 kwadratami mapy to musiałbym zablokować oba, tym samym tracąc 25pix2 powierzchni... Heh nie wiem czy rozumiecie <-P

Wodzu - ..... ale moje obiekty się poruszają tak jak mają, i u nich wszystko działa, tylko nie wiedzą zabardzo kiedy mogą na coś wjechać, a kiedy nie mogą. Ten drugi przypadek jest rozwiązany tylko wtey, gdy dany obiekt zajmuje cały kwadrat, ale jeżeli zajmuje pół/stoi na skrzyżowaniu 4 innych to zaczyna sie problem bo zapisanie ze wszystkie z tych kwadratow sa nieprzejezdne mija sie z celem.

0

No to mowie Ci wykorzystaj detekcje kolizji ktora masz w DelphiX i samo Ci sprawdzi czy dany obiekt wjechal na dany obiekt....:)

0

Wodzu.... luknąłem na tą funkcję i:
w parametrach podaję pozycja_x, pozycja_y, szerokosc, wysokosc dla jednego i dla drugiego obiektu.... ale ja NIE MAM danego drugiego obiektu, bo nie wiem czy tam się jakiś znajduje... To jest dobre dla jednego i drugiego gracz (po prostu sprawdzam czy się nachodzą i tyle) ale sprawa się komplikuje, jeśli nie znam pozycji innych stworków (chyba ze zrobie tablice stworkow z ich aktualnym x i y.... co nie jest chyba glupie)

//Dopisane:
Dziękuję wszystkim serdecznie za pomoc, w szczególności Wodzowi, za którego idąc radą rozwiązałem problem kolizji graczy!!

0

Jak chodzi o tą tablicę z pozycją wszystkich "stworków" to to jest nie "nie głupie" a niemal jedyne słuszne... Tak mi się wydaje... I wtedy jak chcesz kimś poruszyć to uruchamiasz pętelkę, która sprawdza, czy dany "poruszający się" aktualnie obiekt nie wchodzi na żaden inny (po kolei jak leci). I masz...

0

Ciesze sie ze moglem Ci pomoc Therielu [browar]

A tablica stworkow wcale nie jest konieczna gdyz kazdy obieket typu TDXSprite( w DelphiX) ma juz przeciez pola pozycji X,Y i Z wiec wystarczy sprawdzac pozycje tych spritow. Ale tak naprawde to nie trzeba sprawdzac pozycyji tych spriteów recznie gdyz zrobi to za nas samo DelphiX i TDXSpriteEngine o czym zapewne przekonal sie Theriel:)

Pozdrawiam i powodzenia w kolidowaniu;P

Wodzu

0

Jeszcze raz dziękuję Wodzu.... a btw: nie korzystam ze spritow w DX <-] powodów kilka: 1. Nie nauczyłem się jeszcze dobrze ich obsługi 2.nie widzę zalet korzystania ze spritow DelphiX (x i y to mogę sobie sam zrobić w klasie własnej <-P)...

0

Hmm....dziwne bo przeciez cala animacja obrazkow ich przesuwanie....bazuje wlasnie na TDXSprite...no ale grunt ze Ci sie udalo zrobic to co chciales, a ja tutaj zbaczam z tematu posta:)
Jakbys chcial sie jednak jeszcze kiedys czegos dowiedziec o tych Spriteach..(wiem wiem..;P) to moge w miare mej skromnej wiedzy pomoc...:)

Trzymaj sie:)

0

A może wiecie, jak by to zrobić, że np. jest jakieś tło (mapa bitowa) i druga mapa bitowa z kluczowaniem koloru tła i obiektami, z którymi kolidują sprajty??

Programuję w directdraw, może tam czegoś takiego nie ma. A jak nie ma to gdzie może być?

0

W mojej grze :0 hehehe kolizje wykrywam w taki sposód :) , jak na programiste amatora :) ... To stary kodzik dlatego jest troche zabrudzony :) i nieestetycznie moze to wyglądać :). Ta procedurka jest w timerze w rzucona z intervalem na 15... Czysta amatorszczysna....

procedure kolizja;
var
zmienna:integer;
begin
  for zmienna:=1 to ilosc_kolizji do begin
    if (form1.Phero.Left-form1.Back.Left<=kolizje_mapy[zmienna]._x2) and (form1.Phero.Left-form1.Back.Left+form1.Phero.Width>=kolizje_mapy[zmienna]._x1) and (form1.Phero.Top-form1.Back.Top+form1.Phero.Height=kolizje_mapy[zmienna]._y1) then KKdol:=false else KKdol:=true;
    if KKdol=false then begin
      if kolizje_mapy[zmienna].przejscie<>'none' then begin
        nastepna_mapa:=kolizje_mapy[zmienna].przejscie;
        form1.Back.Top:=kolizje_mapy[zmienna].nowa_mapa_back_Top;
        form1.Back.Left:=kolizje_mapy[zmienna].nowa_mapa_back_Left;
        form1.Phero.Top:=kolizje_mapy[zmienna].nowa_mapa_pos_Top;
        form1.Phero.Left:=kolizje_mapy[zmienna].nowa_mapa_pos_Left;
        ladowanie_mapy;
      end;
      break;
    end;
  end;
  for zmienna:=1 to ilosc_kolizji do begin
    if (form1.Phero.Left-form1.Back.Left+form1.Phero.Width=kolizje_mapy[zmienna]._x1) and (form1.Phero.Top-form1.Back.Top+form1.Phero.Height>=kolizje_mapy[zmienna]._y1) and (form1.Phero.Top-form1.Back.Top<=kolizje_mapy[zmienna]._y2)then KKprawo:=false else KKprawo:=true;
    if KKprawo=false then begin
      if kolizje_mapy[zmienna].przejscie<>'none' then begin
        nastepna_mapa:=kolizje_mapy[zmienna].przejscie;
        form1.Back.Top:=kolizje_mapy[zmienna].nowa_mapa_back_Top;
        form1.Back.Left:=kolizje_mapy[zmienna].nowa_mapa_back_Left;
        form1.Phero.Top:=kolizje_mapy[zmienna].nowa_mapa_pos_Top;
        form1.Phero.Left:=kolizje_mapy[zmienna].nowa_mapa_pos_Left;
        ladowanie_mapy;
      end;
      break;
    end;
  end;
  for zmienna:=1 to ilosc_kolizji do begin
    if (form1.Phero.Left-form1.Back.Left+form1.Phero.Width>=kolizje_mapy[zmienna]._x1+8) and (form1.Phero.Left-form1.Back.Left<=kolizje_mapy[zmienna]._x2-8) and (form1.Phero.Top-form1.Back.Top=kolizje_mapy[zmienna]._y2-8) then KKgora:=false else KKgora:=true;
    if KKgora=false then begin
      if kolizje_mapy[zmienna].przejscie<>'none' then begin
        nastepna_mapa:=kolizje_mapy[zmienna].przejscie;
        form1.Back.Top:=kolizje_mapy[zmienna].nowa_mapa_back_Top;
        form1.Back.Left:=kolizje_mapy[zmienna].nowa_mapa_back_Left;
        form1.Phero.Top:=kolizje_mapy[zmienna].nowa_mapa_pos_Top;
        form1.Phero.Left:=kolizje_mapy[zmienna].nowa_mapa_pos_Left;
        ladowanie_mapy;
      end;
      break;
    end;
  end;
  for zmienna:=1 to ilosc_kolizji do begin
    if (form1.Phero.Left-form1.Back.Left=kolizje_mapy[zmienna]._x2) and (form1.Phero.Top-form1.Back.Top<=kolizje_mapy[zmienna]._y2)and (form1.Phero.Top-form1.Back.Top+form1.Phero.Height>=kolizje_mapy[zmienna]._y1) then KKlewo:=false else KKlewo:=true;
    if KKlewo=false then begin
      if kolizje_mapy[zmienna].przejscie<>'none' then begin
        nastepna_mapa:=kolizje_mapy[zmienna].przejscie;
        form1.Back.Top:=kolizje_mapy[zmienna].nowa_mapa_back_Top;
        form1.Back.Left:=kolizje_mapy[zmienna].nowa_mapa_back_Left;
        form1.Phero.Top:=kolizje_mapy[zmienna].nowa_mapa_pos_Top;
        form1.Phero.Left:=kolizje_mapy[zmienna].nowa_mapa_pos_Left;
        ladowanie_mapy;
      end;
      break;
    end;
  end;
end;
</b>
0

19-12-2003 15:58
03-01-2006 14:58
Jest że tak powiem pewna różnica w datach... Trochę przesadziłeś z odświeżeniem...

// pytamy się w nowych postach, a starych nie odświeżamy! - Ktos

1 użytkowników online, w tym zalogowanych: 0, gości: 1