Temporal Opublikowano 20 Lutego 2019 Udostępnij Opublikowano 20 Lutego 2019 Tworzę sobie taki projekcik, gdzie wykorzystuję kolizję opartą o tilesy, a nie obiekty. Mój skrypt, który jest taką alternatywą dla "place_meeting()", tylko działa na tilesach: Cytuj ///@arg xx ///@arg yy ///@arg collision_layer var xx = argument0; var yy = argument1; var tilemap_id = layer_tilemap_get_id(layer_get_id(argument2)); var right_collision = false; var left_collision = false; var top_collision = false; var bottom_collision = false; //save current position var xp = x; var yp = y; //update position and check for collision if (xx != xp){ x = xx; if (xx > xp){ // right movment collision right_collision = tilemap_get_at_pixel(tilemap_id, bbox_right, bbox_top) || tilemap_get_at_pixel(tilemap_id, bbox_right, bbox_top+sprite_height/2) || tilemap_get_at_pixel(tilemap_id, bbox_right, bbox_bottom); } else { // left movment collision left_collision = tilemap_get_at_pixel(tilemap_id, bbox_left, bbox_top) || tilemap_get_at_pixel(tilemap_id, bbox_left, bbox_top+sprite_height/2) || tilemap_get_at_pixel(tilemap_id, bbox_left, bbox_bottom ); } } if (yy != yp){ y = yy; if (yy > yp){ // down movment collision bottom_collision = tilemap_get_at_pixel(tilemap_id, bbox_left, bbox_bottom )|| tilemap_get_at_pixel(tilemap_id, bbox_left+sprite_width/2, bbox_bottom)|| tilemap_get_at_pixel(tilemap_id, bbox_right, bbox_bottom); } else { // up movment collision top_collision = tilemap_get_at_pixel(tilemap_id, bbox_left, bbox_top) || tilemap_get_at_pixel(tilemap_id, bbox_left+sprite_width/2, bbox_top)|| tilemap_get_at_pixel(tilemap_id, bbox_right, bbox_top); } } //move back x = xp; y = yp; //return return (right_collision || left_collision || top_collision || bottom_collision); Tak wygląda kod odnośnie kolizji: Cytuj // horizontal collision check if scr_tile_collision(x+hspd, y, "Collision"){ while(!scr_tile_collision(x+sign(hspd), y, "Collision")){ x+=sign(hspd); } hspd = 0; } x += hspd; // vertical collision check if scr_tile_collision(x, y+vspd, "Collision"){ while(!scr_tile_collision(x, y+sign(vspd), "Collision")){ y+=sign(vspd); } vspd = 0; } y += vspd; Nic odkrywczego, taki standard jeśli chodzi o precyzyjną kolizję, tutaj jednak odnosimy się do tilesów. Chcę w grze mieć wrogów, którzy mają zasięg widzenia i jeśli my jako gracz się w nim znajdziemy, to odpalają się pewne state'y. Problem jest taki, że ściany, platformy, to tilesy bez obiektów kolizyjnych, więc funkcja collision_line() odpada. Moje doświadczenie jest małe i coś tak kombinuję sobie, jak pierwszy lepszy pomysł do głowy trafi. Skoro mam własną funkcję do wykrywania kolizji między obiektami a tilesami, to pomyślałem, że może "wzrok" przeciwników, to będzie obiekt, ze spritem o wielkości 1 pixela, który będzie się skalował w osi x na maksymalny zasięg z zmiennej. Cytuj //line of sight with (my_line_of_sight){ x = other.x; y = other.y; image_xscale = other.seeing_max * other.dir; if scr_tile_collision(x+other.hspd, y, "Collision"){ while(scr_tile_collision(x+(other.hspd*2), y, "Collision")){ image_xscale=image_xscale - (other.hspd*2); } image_xscale = image_xscale-other.hspd other.seeing_wall = true; } else { other.seeing_wall = false; } } Problem jest taki, że kolizja z tilesami jest oparta o punkty bounding boxa tilesa. Rózne rozmiary kolidujących spirtów mogę powodować różne błędy i niewykrycie kolizji. W moim przypadku mamy 8 punktów sprawdzania kolizji i większości przypadków daje radę. Jeśli biała linia przejdzie za bardzo przez tilesa, to kolizja nie zachodzi i zmienna seeing_wall = false; Na screenie widać o co mi chodzi. Chciałbym żeby linia wchodząc w tilesa scalowała się w dół. Tak by nadal kolidowała z tilesem a się skracała tak by nie wychodziła poza obszar tilesa. Pewnie nie jest to najlepsze rozwiązanie, ale likwidacja tego jednego problemu dałaby mi to czego potrzebuję. Próbowałem coś na googlach szukać odnośnie collision_line z tilesami i jedyne co znalazłem jakiś niezrozumiały dla mnie skrypt, który był raycastem opartym o ds_grid. Jak na moje potrzeby, to jednak za bardzo skomplikowane. Może zamiast skalowanego obiektu na wzór linii zrobić obiekt "punkt", który jest w odległości od przeciwnika i w razie kolizji jest dopychany w pętli idealnie do punktu bounding boxa? samą linię mógłbym na potrzeby debbuginu rysować w drawie w odległości x przeciwnika do x punktu. Jakieś rady? Jeśli ktoś znałbym jakiś nie za bardzo skomplikowany sposób na zrobienie tego bez dodatkowych obiektów tylko na podstawie jakieś "zaawansowanej" matematyki, to się nie obrażę Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 21 Lutego 2019 Administratorzy Udostępnij Opublikowano 21 Lutego 2019 Jak chcesz naprawdę na skróty, to ustawiaj obiekty solid i rozciągaj je na całą wysokość danej ściany. W przypadku powyższego screena, można na 5 obiektach zrobić całe kolizje w grze zmieniając x-scale / y-scale . Jak etapy nie są ogromne, albo dodasz deaktywację poza ekranem, to naprawdę wdajnościowo nie będzie problemem, a cały powyższy problem poleci do kosza. Temporal 1 Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Temporal Opublikowano 21 Lutego 2019 Autor Udostępnij Opublikowano 21 Lutego 2019 Czyli darować sobie tilesy i wrócić do starych sprawdzonych obiektów kolizyjnych? Plansze w grze mają być duże, nie jakaś metroidvania, ale trochę tam ma się scrollować zanim etap się skończy. Pomysł z dezaktywacją obiektów, które są daleko od aktualnej kamery nie jest taki głupi i myślę, że nawet z moją małą wiedzą o GM'ie jestem w stanie ogarnąć temat. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się