Skocz do zawartości

Obiekt za szybki...


Zając

Rekomendowane odpowiedzi

Co zrobić z obiektem który jest za szybki, a mianowicie przenika przez inne obiekty? Chodzi o nabój w strzelance od góry. Kombinowałem na parę sposobów, jak np. zrobienie podłużnego niewidzialnego sprite'a pocisku, ale problem i tak pozostaje przy.. ścianach. Bo jeżeli przeciwnik stoi blisko ściany z drugiej strony to i tak dostawał. Wtedy zrobiłem obiekt który sprawdza czy jest "wolna droga", tyle że po tym kiedy wróg stał przy ścianie, przed nami, to i tak nie dostawał... "collision_line" też chyba odpada bo by zaliczało wszystkie obiekty na lini wcześniejszego i obecnego położenia... Jaki jest najprostszy sposób się tym zająć?

Odnośnik do komentarza
Udostępnij na innych stronach

Nie wiem, może po prostu wolno myślę i tego nie ogarniam ale w takiej sytuacji jak ustawić żeby sprawdzał czy przeciwnik jest przed ścianą? Zwraca ID obiektu znajdującego się bliżej A, ale wyznaczonego obiektu, czyli wszystko fajnie, zaliczy najbliższego przeciwnika jeżeli inny jest za nim. Ale już jeżeli są dwa typy przeciwników, dwa inne obiekty to wtedy zaliczy oba. (No bo do każdego obiektu muszę ten kod dać...) Poza tym to mi dalej nie wyjaśnia co zrobić kiedy obiekt jest za ścianą, a collision_line zalicza i obiekt i ścianę. Bo wtedy zaliczy obie kolizje. Nie mogę też ustawić np że najpierw sprawdza kolizję ze ścianą a na "else" kolizję z obiektem bo wtedy jeżeli obiekt jest przed nami, a za nim ściana to pocisk zaliczy kolizję ze ścianą tylko. Kurde jeżeli dziwnie piszę to dlatego że jestem zmęczony ale po prostu dalej ni widzę rozwiązania mojego problemu..

Odnośnik do komentarza
Udostępnij na innych stronach

W przykładzie sprawdzam kolizję ze ścianą tą samą funkcją, tyle że jak ustawić żeby zaliczał kolizję tego co jest bliżej... Bo tak to zalicza tego co jest pierwsze w kodzie po prostu. Ten link co dałeś prześledzę jak się okaże, że nie ma prostszego rozwiązania.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

GML
var c1,c2;

 

c1 = collision_line(x,y,xprevious,yprevious,obj_npc,false,true);

c2 = collision_line(x,y,xprevious,yprevious,obj_wall,false,true);

 

if c1 || c2 {

x = xprevious;

y = yprevious;

move_contact_all(direction,speed);

 

if distance_to_object(c1) < distance_to_object(c2) {

event_perform(ev_collision,obj_npc);

} else {

event_perform(ev_collision,obj_wall);

}

}

 

Teraz jest OK?

 

 

BTw. zamiast pisać:

GML
instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

instance_create(other.x,other.y,obj_blood);

 

Możesz napisać:

 

GML
repeat(10) instance_create(other.x,other.y,obj_blood);
Odnośnik do komentarza
Udostępnij na innych stronach

O jakich prędkościach pocisku mowa, że takie rzeczy się dzieją?

 

W przykładzie jakim dałem, już nie pamiętam ale w grze nad którą pracuję jest 75. W ogóle wyjaśni mi ktoś czemu jak mam na end_step collision event, to potem z tego collision event nie zalicza mi w ogóle "other"? :mellow: W sensie że jak np jest other.hp-=5 to wyskakuje że nie zna zmiennej, normalnie jak nie mam tego sprawdzania kolizji w end step i zaliczy kolizje to działa. Ehh załamać sie idzie. :crying:

Odnośnik do komentarza
Udostępnij na innych stronach

No niestety ale przy takich prędkościach standardowe eventy kolizji nie będą działać poprawnie, musisz zrobić własne dużo bardziej precyzyjne. Najlepiej sprawdzaj linię polizji pomiędzy pozycją poprzedna a aktualną pocisku, potem ( gdy linia ta zauważy kolizję ) cofnij pocisk na poprzednią pozycję i pętlą while przesuwaj pocisk małymi kroczkami do przodu aż nie napotka najbliższego obiektu. ( im mniejsze kroki tym bardziej precyzyjna będzie kolizja ale sprawdzenie kolizji będzie się wykonywać dłużej )

Odnośnik do komentarza
Udostępnij na innych stronach

No niestety ale przy takich prędkościach standardowe eventy kolizji nie będą działać poprawnie, musisz zrobić własne dużo bardziej precyzyjne. Najlepiej sprawdzaj linię polizji pomiędzy pozycją poprzedna a aktualną pocisku, potem ( gdy linia ta zauważy kolizję ) cofnij pocisk na poprzednią pozycję i pętlą while przesuwaj pocisk małymi kroczkami do przodu aż nie napotka najbliższego obiektu. ( im mniejsze kroki tym bardziej precyzyjna będzie kolizja ale sprawdzenie kolizji będzie się wykonywać dłużej )

 

Moglbym prosić o prosty przykład? :)

Odnośnik do komentarza
Udostępnij na innych stronach

Już daję, ale to nie jest najszybsza metoda:

 

GML (collisionwhile)
// skrypt collision_while( cofajX, cofajY, obj );

x = argument0;

y = argument1;

 

var _count, _collision;

_count = 0;

 

while ( true )

{

_collision = instance_place( x, y, argument2 );

x += cos( direction*pi/180 );

y -= sin( direction*pi/180 );

_count += 1;

if ( _count > speed ) return noone;

if ( _collision != noone ) return _collision;

}

 

Sposób użycia:

GML
if ( collision_line( xprevious, yprevious, x, y, oWall, 0, 0 ) )

{

if ( collision_while( xprevious, yprevious, oWall ) )

instance_destroy();

}

 

Skrypt zwraca ID 1 napotkanej instacji więc możesz sobie zwrócić twoje .other

 

 

Ten bedzie działał jeszcze szybciej, ale nie ma blokady przeciwko zapętleniu się ( na wypadek gdyby poszło coś nie tak )

GML (collisionwhile)
// skrypt collision_while( cofajX, cofajY, obj );

x = argument0;

y = argument1;

 

var _collision;

 

while ( true )

{

_collision = instance_place( x, y, argument2 );

x += cos( direction*pi/180 );

y -= sin( direction*pi/180 );

if ( _collision != noone ) return _collision;

}

 

Edit: Origin ustaw na czubku pocisku. Sprawdzanie kolizji wykonuj w evencie end step

Odnośnik do komentarza
Udostępnij na innych stronach

A puźniej płacz że masz mało fps'ów. Jeśli strzeli w przestrzeń o długości 5000px collisio line wykona się ok 67 razy co bardzo spowolni grę.

Tutaj collision line jest sprawdzany raz.

A długość przestrzeni w którą strzela nie ma znaczenia. W tym skrypcie, wartość prędkości decyduje o tym ile razy wykona się pętla. W najgorszym wypadku pętla wykona się tyle razy ile wynosi prędkość a w najlepszym tylko raz.

Odnośnik do komentarza
Udostępnij na innych stronach

Nie ogarniam tego skryptu, ale działa, z tym że...

a) Musiałem ustawić szybkość na ponad 1000 bo, dalej czasami zaliczało kolizję jak był za ścianą.

(Myślę że chodzi o to, że skoro to jest na end step, to przed tym w sytuacji kiedy nabój znajduje się tam gdzie przeciwnik to zalicza normalną kolizję przed wykonaniem end step)

B) Jak wspomniałem nie ogarniam tego skryptu, ale działa, z tym że dalej other nie znajduje...

 

Tak czy siak wielkie dzięki za po moc do tej pory. :)

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Jeśli chodzi o to co podałem, to tam czasem może być błąd, że któraś z funkcji zwraca -1 i distance_to_object() się źle wylicza wtedy. Nie mniej mi się na taką sytuację trafić nie udało, co nie znaczy, że ona nie może zaistnieć, bo jak widać w kodzie, nie jest to sprawdzane.

Odnośnik do komentarza
Udostępnij na innych stronach

Nie ogarniam tego skryptu, ale działa, z tym że...

a) Musiałem ustawić szybkość na ponad 1000 bo, dalej czasami zaliczało kolizję jak był za ścianą.

(Myślę że chodzi o to, że skoro to jest na end step, to przed tym w sytuacji kiedy nabój znajduje się tam gdzie przeciwnik to zalicza normalną kolizję przed wykonaniem end step)

B) Jak wspomniałem nie ogarniam tego skryptu, ale działa, z tym że dalej other nie znajduje...

 

Tak czy siak wielkie dzięki za po moc do tej pory. :)

 

Nie musisz wiedzieć co się dzieje w samym skrypcie żeby go używać :P

 

1. Origin sprita pocisku ustaw na jego czubku.

2. Skrypt zadziała jeżeli do wyświetlania i przesuwania instancji pocisku używasz wbudowanych zmiennych, x, y, speed, direction, image_angle.

3. Skrypt poprawnie zadziała tylko w end step oraz draw.

4. Standardowe eventy kolizji z pociskiem powywalaj .

 

5. End step pocisku:

GML
var _other;

if ( collision_line( xprevious, yprevious, x, y, oWall, 0, 0 ) )

{

_other = collision_while( xprevious, yprevious, oWall )

if ( _other )

{

instance_destroy(); // zaistniala kolizja ten kod wykona sie w instancji pocisku

with ( _other )

{

instance_destroy(); // a ten kod wykona się w instacji sciany

}

}

}

Odnośnik do komentarza
Udostępnij na innych stronach

Nie musisz wiedzieć co się dzieje w samym skrypcie żeby go używać :P

 

1. Origin sprita pocisku ustaw na jego czubku.

2. Skrypt zadziała jeżeli do wyświetlania i przesuwania instancji pocisku używasz wbudowanych zmiennych, x, y, speed, direction, image_angle.

3. Skrypt poprawnie zadziała tylko w end step oraz draw.

4. Standardowe eventy kolizji z pociskiem powywalaj .

 

5. End step pocisku:

GML
var _other;

if ( collision_line( xprevious, yprevious, x, y, oWall, 0, 0 ) )

{

_other = collision_while( xprevious, yprevious, oWall )

if ( _other )

{

instance_destroy(); // zaistniala kolizja ten kod wykona sie w instancji pocisku

with ( _other )

{

instance_destroy(); // a ten kod wykona się w instacji sciany

}

}

}

 

Czuję się głupi, ale jak to przerobić żeby sprawdzał więcej niż jeden obiekt? Bo jak skopiuje cały kod i wkleje pod spodem przerabiając go na to co ma zrobić z innym obiektem to i tak jeżeli sprawdzanie kolizji ze ścianą jest pierwsze, a obiekt stoi tuż przed ścianą to pocisk zaliczy kolizję ze ścianą.

Odnośnik do komentarza
Udostępnij na innych stronach

Narysuj sytuację na rysunku bo nie ogarniam co chcesz w końcu zrobić.

 

przykladp.jpg

 

W takiej sytuacji zalicza mi kolizję ze ścianą a nie przeciwnikiem, w kodzie mam takie coś:

 

GML
var _other;

if ( collision_line( xprevious, yprevious, x, y, obj_block, 0, 0 ) )

{

_other = collision_while( xprevious, yprevious, obj_block )

if ( _other )

{

instance_destroy(); // POCISK

with ( _other )

{

 

}

}

}

 

 

 

 

var _other;

if ( collision_line( xprevious, yprevious, x, y, obj_walker, 0, 0 ) )

{

_other = collision_while( xprevious, yprevious, obj_walker )

if ( _other )

{

instance_destroy(); // POCISK

with ( _other )

{

s_walkercol() //OTHER

}

}

}

 

obj_block jest parentem dla wszelkiego typu ścian, a nie mogą mieć takiego samego parenta bo inny kod ma się wykonywać przy kolizji z ojb_walker :mellow: Skrypt s_walkercol() zawiera co ma się dziać przy kolizji z obj_walker.

 

Ps. A jak zamienie te dwa kody miejscami to wtedy będzie mógł przeciwnik dostać mimo tego że za ścianą będzie.

Odnośnik do komentarza
Udostępnij na innych stronach

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ę
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...