Skocz do zawartości

Cienie


Rekomendowane odpowiedzi

Witam, to znowu Ja :mellow:

Powoli sobie dziubie w kodzie i natrafiam na nowe problemy, a na problemy z Game Makerem najlepsi są ludzie z tego forum :thumbsup:

Chciałbym zrobić(właściwie to już troche zrobiłem) cień bohatera. Miałby on być ciągle na podłożu i podążać za bohaterem. Problem jest taki, że to nie top down tylko platformówka. Poradników nie ma (albo jestem ślepy), a sam od godziny dobrnąłem do tego miejsca:

 

- z alfą dla cienia

- bez afly dla cienia (i się jakoś zepsuła -.-)

 

A chciałbym, żeby to wyglądało tak:

 

giphy.gif

 

giphy.gif

 

 

 

 

GML
///Draw shadow

sh = sprite_height/2;

sw = sprite_width/2;

if(collision_rectangle(x-sw/2,y,x+sw/2,y+sh+4,oSolid,true,true))

{

if(sh_alpha != 1) then sh_alpha += 0.1;

}

 

if(!collision_rectangle(x-sw/2,y,x+sw/2,y+sh+1,oSolid,true,true))

{

if(sh_alpha != 0) then sh_alpha -= 0.1;

}

 

draw_sprite_ext(sShadow,0,x,y+4,1,1,0,c_white,sh_alpha)

sh_alpha (shadow_alpha) - ustawiony w create na 1;

 

Czyli gracz posiada cień, który jest do niego przylepiony, a powinien być ciągle na podłożu. Gdy collision_rectangle nie wykrywa podłoża zmniejsza alpha spritu, a gdy wykrywa, zwiększa go.

 

Próbowałem to na masę sposobów:

a) distance_to_object

B) distance_to_point

c) lenghtdir_y

d) stworzyłem obiekt (ale tworzenie dla każdego stworka byłoby chyba mało optymalne)

e) stworzyłem zmienną, która wzrastała gdy yprevious != y (i tu było stosunkowo najbliżej celu)

 

Nie ma jakieś funkcji typu "distance_to_object" ale tylko dla y? Byłbym wdzięczny za pomoc, nakierowanie.

Odnośnik do komentarza
Udostępnij na innych stronach

Nie ma jakieś funkcji typu "distance_to_object" ale tylko dla y? Byłbym wdzięczny za pomoc, nakierowanie.

To jest zwykłe działanie matematyczne: współrzędna y dla punktu A minus współrzędna y dla punktu B.

 

Jest jeszcze point_distance() i tego radzę używać zamiast distance_to_object. Różni się to tym że point_distance mierzy faktyczną odległość między punktem A a punktem B a distance_to_object mierzy odległość między krawędziami bounding boxa obiektu z krawędzią drugiego obiektu

 

point_distance() to nic innego jak działanie sqrt( sqr(A.x-B.x)+sqr(A.y-B.y) )

 

 

Edit:

A co do tematu, to co chcesz osiągnąć zrobisz najoptymalniej dzieki temu: https://gmclan.org/index.php?czytajart=74

Odnośnik do komentarza
Udostępnij na innych stronach

Hmm... z matmy to ja buc jestem (tak, jutro matura z matmy)

A gdyby tak bohater miał wystający z siebie colission_line skierowany w dół. Gdyby napotkał instancję, pobierałby ID. Cień byłby rysowany na tym obiekcie (id.x, id.y). Gdyby nie znajdował instancji, to cień przylepiałby się do bohatera (, bo i tak alpha cienia byłaby już z wartością 0)

 

fioletowa linia - colission_line

giphy.gif

 

Dobry tok myślenia, czy nie za bardzo i mam zacząć rozkminiać Twoją odpowiedź (,bo dla mnie to wszystko za mądrze brzmi :mellow: )

Odnośnik do komentarza
Udostępnij na innych stronach

Tak zrobisz to za pomocą collision line. Collision line zwraca ID naptkanej instacji.

Chciałem byś zrobił wykrywanie odległości między nogami postaci a najbliższej pod nim platformy za pomocą wyszukiwania binarnego ale jeżeli to jest za trudne to ławiejszym sposobem dla ciebie będzie wypuszczenie collision_line w pętli for i zatrzymanie wykonywania tej pętli kiedy linia się z czymś zetknie. Wtedy sobie policzysz ile kroków pętla przeszła i będziesz wiedzieć jaką odległość collision_line pokonał. Na pozycji tej odległości narysujesz cień.

 

Edit:

 

Tzn coś takiego:

 

GML
maxymalnaDlugoscLini = 200;

dlugoscSkoku = 5;

 

wysokoscCienia = 0;

for ( var i = 0; i < maxymalnaDlugoscLini; i += dlugoscSkoku )

{

var ID = collision_line(x, y, x, y+i, oSolid, 0, 1);

if ( ID != noone )

{

wysokoscCienia = i;

break;

}

}

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki mistrzu!

 

Zrobiłem to trochę krócej i chciałbym, żebyś zobaczył czy w kodzie nie ma ewentualnych błędów. Jak na razie ich nie widzę i wszystko chodzi pięknie. Dzięki jeszcze raz.

 

GML
sh_dis = 0;

while(!collision_line(x, y, x, y+sh_dis, oSolid, 0, 1))

{

//draw_line(x,y,x,y+sh_dis) // rysuj linie (dla debugu)

sh_dis += 1;

}

 

draw_sprite_ext(sShadow,0,x,y+sh_dis,1,1,0,c_white,sh_alpha)

 

PS: czy break; kończy pętle for? tak z ciekawości ^_^

Odnośnik do komentarza
Udostępnij na innych stronach

Musisz ustalić sobie limit tej pętli.

Zakładam też że taki cień ma być nie tylko na postaci gracza ale także na przeciwnikach czy innych obiektach tak więc sprawdzanie takiej kolizji z precyzją co do pixela będzie ultra niewydajne. Kilka przeciwników i spadnie mocno fps.

 

Tak brake kończy pętlę a contiune kończy aktualny krok pętli

Odnośnik do komentarza
Udostępnij na innych stronach

Uzjel:

A co w przypadku, jak nie będzie oSolid pod graczem?

No cóż, dobrze, że się o to zapytałeś. Sprawdziłem i okazało się, że gra zwiesza totalnie.

 

I am Lord:

Musisz ustalić sobie limit tej pętli.

Tak zrobiłem. Nie tylko wizualnie pasuje mi lepiej (poprzednio były małe błędy z alphą cienia) ale pewnie, tak jak wspomniałeś, gra zyska na optymalizacji ^_^

 

Ostatecznie (chyba) wygląda to tak:

GML
for ( var i = 0; i < 65; i += 1 )

{

var ID = collision_line(x, y, x, y+i, oSolid, 0, 1);

if ( ID != noone )

{

draw_line(x,y,x,y+i) // rysuj linie (dla debugu)

sh_dis = i;

draw_sprite_ext(sShadow,0,x,y+sh_dis,1,1,0,c_white,sh_alpha)

break;

}

}

Odnośnik do komentarza
Udostępnij na innych stronach

Potrzebna ci taka precyzja? Myślę że skok o 2 pixele albo 3 byłby w twojej grze ok. Teraz wykonujesz maxymalnie 65 operacji sprawdzania kolizji na step i to tylko w jednym obiekcie a będziesz ich miał więcej.

możesz spróbować for ( var i = 0; i < 65; i += 3 ) i zobaczyć jak będzie to wyglądało

Odnośnik do komentarza
Udostępnij na innych stronach

Zrobiłem o 3px i cień miał drgawki, wyglądało to okropnie. Później zauważyłem, że nie posłuchałem samego siebie, bo początkowe założenia były takie, żeby cień rysował się na ID.y, a ja rysowałem go po wysokości Y z collision_line.

 

Tak było:

GML
for ( var i = 0; i < 65; i += 3 )

sh_dis = i;

[...]

draw_sprite_ext(sShadow,0,x,y+sh_dis,1,1,0,c_white,sh_alpha)

 

,a tak jest:

GML
draw_sprite_ext(sShadow,0,x,ID.y-(ID.sprite_height/2),1,1,0,c_white,sh_alpha);

 

Teraz wszystko płynnie się przesuwa i cieszy oko. Dziękuje ^_^

Odnośnik do komentarza
Udostępnij na innych stronach

Nie wiem czy nowy GM w końcu ma sensowne linecasty, ale jeśli nie to można go sobie zrobić za pomocą collision_line

 

Troche hackerska ale bardzo prosta metoda to osobny obiekt dla "cienia", który zawsze będzie miał współrzędną X taką samą jak twoja postać, natomiast Y co step ustawiany na tą samą co postać i od razu "move_contact_solid".

Z tym, że na dużych dystansach robisz sobie sporą pętlę co step. Taki pseudo linecast.

Odnośnik do komentarza
Udostępnij na innych stronach

Tylko, że ja mam trochę kod z alphą napisany niefajnie i gdy zwiększę wyszukiwanie do 16px to alpha cienia strasznie klatkuje. Mogę co najwyżej wyszukiwać co 5px, żeby zachować płynność przechodzenia alphy.

 

GML
if(i > 0 && i <= 20) then sh_alpha = 1;

if(i > 20 && i <= 25) then sh_alpha = 0.9;

if(i > 25 && i <= 30) then sh_alpha = 0.8;

if(i > 30 && i <= 35) then sh_alpha = 0.7;

if(i > 35 && i <= 40) then sh_alpha = 0.6;

if(i > 40 && i <= 45) then sh_alpha = 0.5;

if(i > 45 && i <= 50) then sh_alpha = 0.4;

if(i > 50 && i <= 55) then sh_alpha = 0.3;

if(i > 55 && i <= 60) then sh_alpha = 0.2;

if(i > 60 && i <= 64) then sh_alpha = 0.1;

if(i > 64 && i <= 65) then sh_alpha = 0;

 

Jestem przekonany, że to jest najszybszy ale i najgorszy sposób, jednak nie wpadłem na coś innego :/

Odnośnik do komentarza
Udostępnij na innych stronach

A zamiast tego jakbyś zrobił:

GML
H = (ID.y-(ID.sprite_height*0.5))-y; // odległość gracza od cienia na platformie

minH = 20;

maxH = 65;

 

sh_alpha = 1 - ( clamp(H, minH, maxH)-minH ) * ( 1/(maxH-minH) );

 

Wtedy skok sprawdzania kolizji nie będzie miał wpływu na alphę o ile się nie pomyliłem gdzieś

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ę...