Skocz do zawartości

Lengthdir i Primitive


Rekomendowane odpowiedzi

Oto kurs tłumaczączy funkcje lengthdir_x i lengthdir_y oraz pokazujący jak można używać rysowania primitiveów.

A więc na początek stwórzmy sobie jakiś obiekt. Ja nazwałem go obj_shape. W jego drawie wklejmy taki kod:

GML
draw_line_color(190,80,190,140,c_yellow,c_orange);

draw_line_color(190,110,550,110,c_yellow,c_orange);

for(i=0;i<360;i+=1)

{

draw_point_color(190+i,110-cos(degtorad(i))*30,c_green);

draw_point_color(190+i,110-sin(degtorad(i))*30,c_red);

};

Włącz grę i obserwuj przepiękny widok. Widzimy Kartezjański układ współrzędnych, a na nim dwie takie falowate linie. Tytułem wyjaśnień są to wykresy dwóch funkcji trygonometrycznych: sinusa(czerwony) i cosinusa(zielony). Przejdźmy do analizy kodu. pierwsze dwie linijki rysują układ współrzędnych. Następnie mamy pętlę for(od 0 do 360, co 1), a w niej:

190+i oznacza, że rysujemy punkt o x 190(która jest wartością przykładową, w której cały układ umieściłem)+i, czyli wartość postępu pętli(można by to tak ująć). 110-cos(degtorad(i))*30 sprawia już więcej problemu do zrozumienia. 110 to przykładowe y, na którym umieściłem układ. Hmm, dlaczego pętla for kończy się na 360? Zapala się lampka i już wiesz, że 360 stopni to kąt pełny. A więc stopnie. Funkcja cos przyjmuje argument, który jest kątem podanym w radianach(przedstawienie kąta w postaci ilości T\, przy czym T\=180 stopni), więc, aby zamienić stopnie na radiany używamy funkcji degtorad. No dobrze, teraz dlaczego minus? Dlatego, że w Kartezjańskim układzie współrzędnych y rośnie w góręm, a w GMie w dół(zastosowałem - tylko dla efektu wizualnego). No i na koniec *30 jest dlatego, że cosinus zwraca wartość od 1 do -1, więc trzeba dla czytelności trzeba tą wartość powiększyć(30 to przykładowa wartość). Z następną linijką jest dokładnie tak samo, tylko, że używamy funkcji sin.

Osoby spostrzegawcze powinny zauważyć, że wartość cosinusa przy danym kącie pomnożona przez jakąś wartość dystansu i dodana do danego x oraz wartość sinusa przy tym samym kącie pomnożona przez tą samą wartość dystansu i dodana do danego y daje współrzędne punktu położonego w danej odległości i pod danym kątem od danego x i y

Dla dodatkowego wyjaśnienia tej sprawy doklejmy kod:

GML
draw_text_color(500,43,'cos(degtorad(x))=y',c_green,c_green,c_green,c_green,1);

draw_text_color(500,59,'sin(degtorad(x))=y',c_red,c_red,c_red,c_red,1);

draw_text(170,64,'y=to co funkcja zwraca');

draw_text(530,120,'x=podany kat');

draw_text(190,150,'cos(degtorad(x))*dist=lengthdir_x(dist,x)');

draw_text(190,166,'sin(degtorad(x))*dist=lengthdir_y(dist,x)');

I uruchommy grę.

No i tu pojawiają się lengthdir_x i lengthdir_y, które jak widać są uproszczeniem stworzonym przez GMa. Zobrazujemy to rysując obracającą się linię. Dodajmy kod:

GML
direction+=1;

draw_line_color(500,300,500+lengthdir_x(80,direction),300+lengthdir_y(80,direction),c_navy,c_maroon);

Punkt 1 to ten od którego wychodzi kolor niebieski, a punkt 2(do którego dodaliśmy wartość lengthdirów) to ten z którego wychodzi kolor czerowny.

No cóż, skoro przez to przebrnęliśmy, to zapraszam do następnej części kursu.

Aby rozpocząć rysowanie prymitywów musimy użyć funkcji:

GML
draw_primitive_begin(kind)

Przy czym to kind, to rodzaj rysowania, a są one następujące:

GML
pr_pointlist //rusyjemy osobne punkty

pr_linelist //rysujemy linie, stworzone z każdych kolejnych dwóch wierzchołków, więc ich liczba musi być wielokrotnością dwójki

pr_linestrip //rysujemy linię, przy czym każdy nastepny wierzchołek jest połączony ze swoim poprzednikiem

pr_trianglelist //rysujemy trójkąty, stworzone z każdych następnych trzech wierzchołków, więc ich liczba musi być wielokrotnością trojki

pr_trianglestrip //rysujemy trójkąty połączone ze sobą, przy czym każdy następny wierzchołek tworzy trójkąt z dwoma poprzednikami

pr_trianglefan //rysujemy trójkąty, przy czym każde kolejne dwa wierzchołki łączą się z pierwszym narysowanym

Aby narysować wierzchołek używamy funckji:

GML
draw_vertex(x,y); //zwykły wierzchołek

draw_vertex_color(x,y,kolor,przezroczystość); //i kolorowy wierzchołek;)

Aby zakończyć rysowanie i tym samym wyświetlić efekt używamy funkcji:

GML
draw_primitive_end();

Na początek stwórzmy sobie nowy skrypt o nazwie draw_figure i dajmy mu kod:

GML
/*argument0=x

argument1=y

argument2=promien

argument3=liczba wierzcholkow

argument4=rotacja

argument5=color1

argument6=color2

argument7=alpha*/

draw_primitive_begin(pr_trianglefan);

draw_vertex_color(argument0,argument1,argument5,argument7);

for(i=0;i<argument3;i+=1)

{

draw_vertex_color(argument0+lengthdir_x(argument2,argument4+i*360/argument3),argument1+lengthdir_y(argument2,argument4+i*360/argument3),argument6,argument7); draw_vertex_color(argument0+lengthdir_x(argument2,argument4+(i+1)*360/argument3),argument1+lengthdir_y(argument2,argument4++(i+1)*360/argument3),argument6,argument7);

};

draw_primitive_end();

Ta funkcja rysuje dowolny wielokąt foremny. Już tłumaczę. Rysujemy trianglefana, więc najpierw dajemy wierzchołek bazowy, a potem za pomocą pętli for rysujemy kolejne zestawy dwóch wierzchołków o podanym promieniu i kącie będącym iloczynem kąta rozchyłu pomiędzy kolejnymi wierzchołkami figury i postępu pętli(i). W przypadku drugiego wierzchołka wybieamy w przód apropo postępu pętli(wyrażenie i+1). Noi mamy wymarzony wielokąt foremny, którym możemy obracać, jest gradientowy i możemy mu nadać przezroczystość. Przejdźmy teraz do czegoś trudniejszego. Spróbujemy narysować gwiazdę!

Hehe. tak, mam dla was gotowca, ale nie ominie was analiza. xD

Gwiazda jest figurą, która bazuje się na wierzchołkach wielokąta foremnego. Połączenia każdego kolejnego wierchołka jest z dwoma najbliższymi wierzcholkami na boki od kąta przeciwnego w odległości względem środka wielokąta.

Załóżmy sobie skrypt o nazwie draw_star i dajmy mu kod:

GML
/*argument0=x

argument1=y

argument2=promien

argument3=liczba wierzcholkow

argument4=rotacja

argument5=color1

argument6=color2

argument7=alpha*/

var parzyste;

if argument3/2=argument3 div 2 then parzyste=1 else parzyste=0.5;

draw_primitive_begin(pr_trianglefan);

draw_vertex_color(argument0,argument1,argument5,argument7);

for(i=0;i<argument3;i+=1)

{ draw_vertex_color(argument0+lengthdir_x(argument2,argument4+i*360/argument3+180+(360/argument3)/parzyste),argument1+lengthdir_y(argument2,argument4+i*360/argument3+180+(360/argument3)/parzyste),argument6,argument7);

draw_vertex_color(argument0+lengthdir_x(argument2,argument4+i*360/argument3+180-(360/argument3)/parzyste),argument1+lengthdir_y(argument2,argument4+i*360/argument3+180-(360/argument3)/parzyste),argument6,argument7);

};

draw_primitive_end();

Niestety zaobserwowałem niekomfortowe zjawisko. Kiedy na wierzchołkach z definicji rysujemy trójkąty, to gwiazdy są poprzycinane. Na szczęście problem został załatwiony poprzez przeniesienie pierwszego wierzchołka do środka okręgu, a skoro tak to mamy wspólny punkt więc trianglefan i zaczynamy. Jeden vertex w środku, a potem pętla for. Zauważamy skomplikowane obliczenia uzyskujące kąt. +180 oznacza kąt przeciwny, a (360/argument3)/parzyste) pozwala obliczyć rozrzut kąta. Zmienna parzyste ma wartość 1, gdy liczba wierzchołków jest parzysta, a gdy nieparzysta to 0.5. No to powróćmy do naszego obiektu i dodajmuy mu w drawie:

GML
image_angle+=1;

draw_figure(70,50,30,7,image_angle,c_white,c_blue,0.8);

draw_star(70,130,50,8,image_angle,c_blue,c_aqua,0.7);

Tadam!

Dam wam jeszcze jeden przykład na zastosowanie primitive.

W create obiektu dodajmy:

GML
miesiace=12;

zarobki[1]=200;

zarobki[2]=430;

zarobki[3]=140;

zarobki[4]=700;

zarobki[5]=340;

zarobki[6]=620;

zarobki[7]=243;

zarobki[8]=650;

zarobki[9]=1000;

zarobki[10]=820;

zarobki[11]=110;

zarobki[12]=60;

odstep=30;

skala=5;

Zdradzę wam, że namalujemy wykres niestałych zarobków.

Miesiące to ilość miesięcy, z których chcemy porównywać swoje zarobki. Tablica zarobki określa ile zarobiliśmy, w kolejnych miesiącach. odstep to odstęp w pixelach pomiędzy kolejnymi miesiącami. skala za to to wartość, przez którą będziemy dzielić, aby wysokość wykresu nie była zbyt wielka(no bo inaczej to 1000 złotych=1000 pixeli, a tako tylko 200).

No dobra. Teraz do drawu dodajmy to:

GML
draw_line(20,200,20,400);

draw_line(20,400,20+miesiace*odstep,400);

draw_primitive_begin(pr_linestrip)

draw_vertex(20,400)

for(i=1;i<=miesiace;i+=1)

{

draw_vertex(20+i*odstep,400-zarobki/skala)

};

draw_primitive_end();

I oto naszym oczom ukazuje się wykres zarobków. Widać, że najwięcej zarobiłeś we wrześniu(xD).

Wiem, że pojawią się pytania o texturowanie, więc uprzedzę was. Załóżmy sobie skrypcik draw_figure_texture i dajmy ten kod:

GML
*argument0=x

argument1=y

argument2=promien

argument3=liczba wierzcholkow

argument4=rotacja

argument5=color1

argument6=color2

argument7=alpha

argument8=textura*/

var txx,txy;

txx=texture_get_width(argument8);

txy=texture_get_height(argument8);

texture_set_interpolation(true);

texture_set_repeat(true);

draw_primitive_begin_texture(pr_trianglefan,argument8);

draw_vertex_texture_color(argument0,argument1,txx,txy,argument5,argument7);

for(i=0;i<argument3;i+=1)

{

draw_vertex_texture_color(argument0+lengthdir_x(argument2,argument4+i*360/argument3),argument1+lengthdir_y(argument2,argument4+i*360/argument3),txx*lengthdir_x(argument2,argument4+i*360/argument3),txy*lengthdir_y(argument2,argument4+i*360/argument3),argument6,argument7);

draw_vertex_texture_color(argument0+lengthdir_x(argument2,argument4+(i+1)*360/argument3),argument1+lengthdir_y(argument2,argument4++(i+1)*360/argument3),txx*lengthdir_x(argument2,argument4+(i+1)*360/argument3),txy*lengthdir_y(argument2,argument4++(i+1)*360/argument3),argument6,argument7);

};

draw_primitive_end();

Widzimy dwie nowe zmienne txx i txy, które mają wartość zwróconą przez dwie funkcje. Przy dobrych wymiarach textury powinne one zwracać wartość 1. Następnie widzimy funckje:

GML
texture_set_interpolation(true);

texture_set_repeat(true);

Dzięki temu texturowanie działa(pierwsze odpowiada za nie pobieranie tylko pierwszego pixela textury, a drugie za hmm nakładanie textury).

Widzimy, że funkcja rozpoczynający prymityw dostała na końcu _texture i dostała argument, którym notabene jest textura. Funkcje rysowania vertexów też się zmieniły. Przed kolorem i przezroczystością są dwa argumenty, które przymą wartość:

-pierwszy(czyli xtex): txx*rzeczy_dodane_do_do_wpsolrzednej_x

-drugi(czyli ytex): txy*rzeczy_dodane_do_do_wpsolrzednej_y

Kończymy rysowanie normalnie draw_primitive_end().

Teraz dodaj sobie jakiś background i nazwij go tex, a następnie dodaj do create obiektu:

GML
tx=background_get_texture(tex);

Noi dodaj do drawu obiektu:

GML
draw_figure_texture(500,420,35,9,image_angle,c_yellow,c_white,0.6,tx);

Ćwiczenia i pytania:

1.Przerób funkcję draw_figure tak, aby była trójkolorowa(zamiast dwu)

2.Funkcji draw_star zmień kind rysowania na pr_linestrip i przenieś pierwszy vertex do śrdoka pętli for. Zaobserwuj zmiany.

3.Przepuść rysowanie sinusoidy i cosinusoidy(wykresów funkcji cos i sin) dalej niż do 360 stopni. Zaobserwuj zależność wobec wartości 360 stopni.

4.Stwórz skrypt rysowania lini(krzywej) łączącej wszystkie instancje w roomie. podpowiadam, że należy użyć:

GML
for(i=0;i<instance_count;i+=1)

 

Oczywiście załączam przykład

:) Wyraźcie swą opinię o tym.

EDIT: A właśnie. Zapomniałem napisać, że nie wiem dlaczego, ale pentagram nie wychodzi. xD

Odnośnik do komentarza
Udostępnij na innych stronach

  • 4 tygodnie później...

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